Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
35b482b
InfoLabel component boilerplate
behowell Mar 7, 2023
1ac74f2
Initial implementation of InfoLabel
behowell Mar 7, 2023
30b500b
Initial implementation of InfoLabel
behowell Mar 8, 2023
bcbbcde
VR tests
behowell Mar 8, 2023
b559925
change file
behowell Mar 8, 2023
eebf516
Update api.md
behowell Mar 8, 2023
64afdbb
Propagate size to InfoButton
behowell Mar 9, 2023
e702572
Add InfoLabel bundle size test
behowell Mar 9, 2023
024e6c3
Add size story
behowell Mar 9, 2023
014a679
Merge branch 'master' of https://github.com/microsoft/fluentui into i…
behowell Mar 14, 2023
ab92cf8
Merge branch 'infolabel/create' of https://github.com/behowell/fluent…
behowell Mar 14, 2023
e5f80ba
Fix doc link in story
behowell Mar 14, 2023
c51ed89
Export InfoLabel from react-components/unstable
behowell Mar 14, 2023
7e00967
Merge branch 'master' of https://github.com/microsoft/fluentui into i…
behowell Mar 14, 2023
31a0200
api.md
behowell Mar 14, 2023
3187869
Update documentation and stories
behowell Mar 14, 2023
8e0a297
Add VR test for no InfoButton
behowell Mar 14, 2023
00c509a
Add tests
behowell Mar 14, 2023
f17b83f
Clean up useInfoLabel
behowell Mar 14, 2023
dcaf0a6
change file
behowell Mar 14, 2023
54bba7a
Rename content prop to info.
behowell Mar 14, 2023
65a3cbf
Merge branch 'master' of https://github.com/microsoft/fluentui into i…
behowell Mar 15, 2023
35bdcb2
Update dependency version on react-label
behowell Mar 15, 2023
dbe07dd
Clean up InfoButtonBestPractices
behowell Mar 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as React from 'react';

import { Steps, StoryWright } from 'storywright';
import { InfoLabel } from '@fluentui/react-infobutton';
import { storiesOf } from '@storybook/react';
import { TestWrapperDecoratorFixedWidth } from '../utilities/TestWrapperDecorator';

storiesOf('InfoLabel', module)
.addDecorator(TestWrapperDecoratorFixedWidth)
.addDecorator(story => (
<StoryWright steps={new Steps().snapshot('rest', { cropTo: '.testWrapper' }).end()}>{story()}</StoryWright>
))
.addStory('default', () => <InfoLabel info="Test">This is an info label</InfoLabel>, {
includeHighContrast: true,
includeDarkMode: true,
includeRtl: true,
})
.addStory('wrap', () => (
<InfoLabel info="Test">
This is a very long info label that should wrap to multiple lines and put the info button on the last line
</InfoLabel>
))
.addStory('size:small', () => (
<InfoLabel size="small" info="Test">
This is a small info label
</InfoLabel>
))
.addStory('size:large', () => (
<InfoLabel size="large" info="Test">
This is a large info label
</InfoLabel>
))
.addStory(
'required',
() => (
<InfoLabel required info="Test">
This is a required info label
</InfoLabel>
),
{
includeRtl: true,
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "chore: Export InfoLabel from react-components/unstable",
"packageName": "@fluentui/react-components",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "feat: Add InfoLabel component",
"packageName": "@fluentui/react-infobutton",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ import { infoButtonClassNames } from '@fluentui/react-infobutton';
import { InfoButtonProps } from '@fluentui/react-infobutton';
import { InfoButtonSlots } from '@fluentui/react-infobutton';
import { InfoButtonState } from '@fluentui/react-infobutton';
import { InfoLabel } from '@fluentui/react-infobutton';
import { infoLabelClassNames } from '@fluentui/react-infobutton';
import { InfoLabelProps } from '@fluentui/react-infobutton';
import { InfoLabelSlots } from '@fluentui/react-infobutton';
import { InfoLabelState } from '@fluentui/react-infobutton';
import { InputField_unstable as InputField } from '@fluentui/react-input';
import { inputFieldClassNames } from '@fluentui/react-input';
import { InputFieldProps_unstable as InputFieldProps } from '@fluentui/react-input';
Expand All @@ -43,6 +48,7 @@ import { RadioGroupFieldProps_unstable as RadioGroupFieldProps } from '@fluentui
import { renderAlert_unstable } from '@fluentui/react-alert';
import { renderField_unstable } from '@fluentui/react-field';
import { renderInfoButton_unstable } from '@fluentui/react-infobutton';
import { renderInfoLabel_unstable } from '@fluentui/react-infobutton';
import { renderSkeleton_unstable } from '@fluentui/react-skeleton';
import { renderSkeletonItem_unstable } from '@fluentui/react-skeleton';
import { renderTree_unstable } from '@fluentui/react-tree';
Expand Down Expand Up @@ -113,6 +119,8 @@ import { useFieldStyles_unstable } from '@fluentui/react-field';
import { useFlatTree_unstable } from '@fluentui/react-tree';
import { useInfoButton_unstable } from '@fluentui/react-infobutton';
import { useInfoButtonStyles_unstable } from '@fluentui/react-infobutton';
import { useInfoLabel_unstable } from '@fluentui/react-infobutton';
import { useInfoLabelStyles_unstable } from '@fluentui/react-infobutton';
import { useIntersectionObserver } from '@fluentui/react-virtualizer';
import { useSkeleton_unstable } from '@fluentui/react-skeleton';
import { useSkeletonContext } from '@fluentui/react-skeleton';
Expand Down Expand Up @@ -190,6 +198,16 @@ export { InfoButtonSlots }

export { InfoButtonState }

export { InfoLabel }

export { infoLabelClassNames }

export { InfoLabelProps }

export { InfoLabelSlots }

export { InfoLabelState }

export { InputField }

export { inputFieldClassNames }
Expand All @@ -216,6 +234,8 @@ export { renderField_unstable }

export { renderInfoButton_unstable }

export { renderInfoLabel_unstable }

export { renderSkeleton_unstable }

export { renderSkeletonItem_unstable }
Expand Down Expand Up @@ -356,6 +376,10 @@ export { useInfoButton_unstable }

export { useInfoButtonStyles_unstable }

export { useInfoLabel_unstable }

export { useInfoLabelStyles_unstable }

export { useIntersectionObserver }

export { useSkeleton_unstable }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,20 @@ export {
useInfoButton_unstable,
useInfoButtonStyles_unstable,
renderInfoButton_unstable,
InfoLabel,
infoLabelClassNames,
renderInfoLabel_unstable,
useInfoLabel_unstable,
useInfoLabelStyles_unstable,
} from '@fluentui/react-infobutton';
export type {
InfoButtonProps,
InfoButtonSlots,
InfoButtonState,
InfoLabelProps,
InfoLabelSlots,
InfoLabelState,
} from '@fluentui/react-infobutton';
export type { InfoButtonProps, InfoButtonSlots, InfoButtonState } from '@fluentui/react-infobutton';

// eslint-disable-next-line deprecation/deprecation
export { CheckboxField_unstable as CheckboxField, checkboxFieldClassNames } from '@fluentui/react-checkbox';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { InfoLabel } from '@fluentui/react-infobutton';

console.log(InfoLabel);

export default {
name: 'InfoLabel',
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import type { ComponentProps } from '@fluentui/react-utilities';
import type { ComponentState } from '@fluentui/react-utilities';
import { ForwardRefComponent } from '@fluentui/react-utilities';
import { Label } from '@fluentui/react-label';
import type { PopoverProps } from '@fluentui/react-popover';
import type { PopoverSurface } from '@fluentui/react-popover';
import * as React_2 from 'react';
Expand Down Expand Up @@ -36,15 +37,45 @@ export type InfoButtonSlots = {
// @public
export type InfoButtonState = ComponentState<InfoButtonSlots> & Required<Pick<InfoButtonProps, 'size'>>;

// @public
export const InfoLabel: ForwardRefComponent<InfoLabelProps>;

// @public (undocumented)
export const infoLabelClassNames: SlotClassNames<InfoLabelSlots>;

// @public
export type InfoLabelProps = ComponentProps<Partial<InfoLabelSlots>, 'label'> & {
info?: InfoButtonProps['content'];
};

// @public (undocumented)
export type InfoLabelSlots = {
root: NonNullable<Slot<'span'>>;
label: NonNullable<Slot<typeof Label>>;
infoButton: Slot<typeof InfoButton>;
};

// @public
export type InfoLabelState = ComponentState<InfoLabelSlots> & Pick<InfoLabelProps, 'size'>;

// @public
export const renderInfoButton_unstable: (state: InfoButtonState) => JSX.Element;

// @public
export const renderInfoLabel_unstable: (state: InfoLabelState) => JSX.Element;

// @public
export const useInfoButton_unstable: (props: InfoButtonProps, ref: React_2.Ref<HTMLElement>) => InfoButtonState;

// @public
export const useInfoButtonStyles_unstable: (state: InfoButtonState) => InfoButtonState;

// @public
export const useInfoLabel_unstable: (props: InfoLabelProps, ref: React_2.Ref<HTMLLabelElement>) => InfoLabelState;

// @public
export const useInfoLabelStyles_unstable: (state: InfoLabelState) => InfoLabelState;

// (No @packageDocumentation comment for this package)

```
1 change: 1 addition & 0 deletions packages/react-components/react-infobutton/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
},
"dependencies": {
"@fluentui/react-icons": "^2.0.175",
"@fluentui/react-label": "^9.1.3",
"@fluentui/react-popover": "^9.5.3",
"@fluentui/react-tabster": "^9.5.7",
"@fluentui/react-theme": "^9.1.6",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components/InfoLabel/index';
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as React from 'react';

import { render } from '@testing-library/react';
import { isConformant } from '../../testing/isConformant';
import { InfoLabel } from './InfoLabel';

describe('InfoLabel', () => {
isConformant({
Component: InfoLabel,
displayName: 'InfoLabel',
primarySlot: 'label',
testOptions: {
'has-static-classnames': [
{
props: {
info: 'Test',
},
},
],
},
});

it('renders an InfoButton when info is set', () => {
const result = render(<InfoLabel info="Test">Test label</InfoLabel>);
expect(result.getByRole('button')).toBeTruthy();
});

it("renders an InfoButton when the infoButton slot's content is set", () => {
const result = render(<InfoLabel infoButton={{ content: 'Test' }}>Test label</InfoLabel>);
expect(result.getByRole('button')).toBeTruthy();
});

it('does not render an InfoButton when info is not set', () => {
const result = render(<InfoLabel>Test label</InfoLabel>);
expect(result.queryByRole('button')).toBeNull();
});

it('sets the infoButton aria-labelledby to the label and infoButton', () => {
const result = render(<InfoLabel info="Test">Test label</InfoLabel>);

const infoButton = result.getByRole('button');
const label = result.getByText('Test label') as HTMLLabelElement;

expect(infoButton.getAttribute('aria-labelledby')).toBe(`${label.id} ${infoButton.id}`);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from 'react';

import type { ForwardRefComponent } from '@fluentui/react-utilities';
import type { InfoLabelProps } from './InfoLabel.types';
import { renderInfoLabel_unstable } from './renderInfoLabel';
import { useInfoLabel_unstable } from './useInfoLabel';
import { useInfoLabelStyles_unstable } from './useInfoLabelStyles';

/**
* InfoLabel component
*/
export const InfoLabel: ForwardRefComponent<InfoLabelProps> = React.forwardRef((props, ref) => {
const state = useInfoLabel_unstable(props, ref);

useInfoLabelStyles_unstable(state);
return renderInfoLabel_unstable(state);
});

InfoLabel.displayName = 'InfoLabel';
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Label } from '@fluentui/react-label';
import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';
import { InfoButton } from '../InfoButton';
import type { InfoButtonProps } from '../InfoButton';

export type InfoLabelSlots = {
root: NonNullable<Slot<'span'>>;

/**
* The Label component.
*
* It is not typically necessary to use this prop. The label text is the child of the `<InfoLabel>`, and other props
* such as `size` and `required` should be set directly on the `InfoLabel`.
*
* This is the PRIMARY slot: all native properties specified directly on `<InfoLabel>` will be applied to this slot,
* except `className` and `style`, which remain on the root slot.
*/
label: NonNullable<Slot<typeof Label>>;

/**
* The InfoButton component.
*
* It is not typically necessary to use this prop. The content can be set using the `info` prop of the InfoLabel.
*/
infoButton: Slot<typeof InfoButton>;
};

/**
* InfoLabel Props
*/
export type InfoLabelProps = ComponentProps<Partial<InfoLabelSlots>, 'label'> & {
/**
* The content of the InfoButton's popover.
*/
info?: InfoButtonProps['content'];
};

/**
* State used in rendering InfoLabel
*/
export type InfoLabelState = ComponentState<InfoLabelSlots> & Pick<InfoLabelProps, 'size'>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './InfoLabel';
export * from './InfoLabel.types';
export * from './renderInfoLabel';
export * from './useInfoLabel';
export * from './useInfoLabelStyles';
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from 'react';

import { getSlots } from '@fluentui/react-utilities';
import type { InfoLabelSlots, InfoLabelState } from './InfoLabel.types';

/**
* Render the final JSX of InfoLabel
*/
export const renderInfoLabel_unstable = (state: InfoLabelState) => {
const { slots, slotProps } = getSlots<InfoLabelSlots>(state);

return (
<slots.root {...slotProps.root}>
<slots.label {...slotProps.label} />
{slots.infoButton && <slots.infoButton {...slotProps.infoButton} />}
</slots.root>
);
};
Loading