diff --git a/packages/react-components/react-tags/etc/react-tags.api.md b/packages/react-components/react-tags/etc/react-tags.api.md index a96f539e01bfc4..659e2b81f72266 100644 --- a/packages/react-components/react-tags/etc/react-tags.api.md +++ b/packages/react-components/react-tags/etc/react-tags.api.md @@ -4,6 +4,9 @@ ```ts +/// + +import { Avatar } from '@fluentui/react-avatar'; import type { ComponentProps } from '@fluentui/react-utilities'; import type { ComponentState } from '@fluentui/react-utilities'; import type { ForwardRefComponent } from '@fluentui/react-utilities'; @@ -27,29 +30,55 @@ export const TagButton: ForwardRefComponent; export const tagButtonClassNames: SlotClassNames; // @public -export type TagButtonProps = ComponentProps & {}; +export type TagButtonProps = ComponentProps & { + size?: 'extra-small' | 'small' | 'medium'; + shape?: 'rounded' | 'circular'; + appearance?: 'filled-darker' | 'filled-lighter' | 'tint' | 'outline'; + disabled?: boolean; + checked?: boolean; + dismissable?: boolean; +}; // @public (undocumented) export type TagButtonSlots = { - root: Slot<'div'>; + root: NonNullable>; + contentButton?: Slot<'button'>; + avatar?: Slot; + icon?: Slot<'span'>; + primaryText?: Slot<'span'>; + secondaryText?: Slot<'span'>; + dismissButton?: NonNullable>; }; // @public -export type TagButtonState = ComponentState; +export type TagButtonState = ComponentState & Required>; // @public (undocumented) export const tagClassNames: SlotClassNames; // @public -export type TagProps = ComponentProps & {}; +export type TagProps = ComponentProps & { + size?: 'extra-small' | 'small' | 'medium'; + shape?: 'rounded' | 'circular'; + appearance?: 'filled-darker' | 'filled-lighter' | 'tint' | 'outline'; + disabled?: boolean; + checked?: boolean; + dismissable?: boolean; +}; // @public (undocumented) export type TagSlots = { - root: Slot<'div'>; + root: NonNullable>; + content?: Slot<'span'>; + avatar?: Slot; + icon?: Slot<'span'>; + primaryText?: Slot<'span'>; + secondaryText?: Slot<'span'>; + dismissButton?: NonNullable>; }; // @public -export type TagState = ComponentState; +export type TagState = ComponentState & Required>; // @public export const useTag_unstable: (props: TagProps, ref: React_2.Ref) => TagState; diff --git a/packages/react-components/react-tags/package.json b/packages/react-components/react-tags/package.json index 61d50878668ca7..6df62172ac1f7f 100644 --- a/packages/react-components/react-tags/package.json +++ b/packages/react-components/react-tags/package.json @@ -32,6 +32,8 @@ "@fluentui/scripts-tasks": "*" }, "dependencies": { + "@fluentui/react-avatar": "^9.4.10", + "@fluentui/react-icons": "^2.0.196", "@fluentui/react-jsx-runtime": "9.0.0-alpha.2", "@fluentui/react-theme": "^9.1.7", "@fluentui/react-utilities": "^9.8.0", diff --git a/packages/react-components/react-tags/src/components/Tag/Tag.test.tsx b/packages/react-components/react-tags/src/components/Tag/Tag.test.tsx index 80af2199dba4ba..f883681c531f31 100644 --- a/packages/react-components/react-tags/src/components/Tag/Tag.test.tsx +++ b/packages/react-components/react-tags/src/components/Tag/Tag.test.tsx @@ -3,16 +3,27 @@ import { render } from '@testing-library/react'; import { Tag } from './Tag'; import { isConformant } from '../../testing/isConformant'; +const requiredProps = { + avatar: { + name: 'Katri Athokas', + }, + icon: 'i', + primaryText: 'Primary text', + secondaryText: 'Secondary text', + dismissable: true, +}; + describe('Tag', () => { isConformant({ Component: Tag, displayName: 'Tag', + requiredProps, }); // TODO add more tests here, and create visual regression tests in /apps/vr-tests it('renders a default state', () => { - const result = render(Default Tag); + const result = render(Default Tag); expect(result.container).toMatchSnapshot(); }); }); diff --git a/packages/react-components/react-tags/src/components/Tag/Tag.types.ts b/packages/react-components/react-tags/src/components/Tag/Tag.types.ts index 2bb2b4b3227976..8cffeea46be0d1 100644 --- a/packages/react-components/react-tags/src/components/Tag/Tag.types.ts +++ b/packages/react-components/react-tags/src/components/Tag/Tag.types.ts @@ -1,17 +1,30 @@ import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; +import { Avatar } from '@fluentui/react-avatar'; export type TagSlots = { - root: Slot<'div'>; + root: NonNullable>; + content?: Slot<'span'>; + avatar?: Slot; + icon?: Slot<'span'>; + primaryText?: Slot<'span'>; + secondaryText?: Slot<'span'>; + dismissButton?: NonNullable>; }; /** * Tag Props */ -export type TagProps = ComponentProps & {}; +export type TagProps = ComponentProps & { + size?: 'extra-small' | 'small' | 'medium'; + shape?: 'rounded' | 'circular'; + appearance?: 'filled-darker' | 'filled-lighter' | 'tint' | 'outline'; + disabled?: boolean; + checked?: boolean; + dismissable?: boolean; +}; /** * State used in rendering Tag */ -export type TagState = ComponentState; -// TODO: Remove semicolon from previous line, uncomment next line, and provide union of props to pick from TagProps. -// & Required> +export type TagState = ComponentState & + Required>; diff --git a/packages/react-components/react-tags/src/components/Tag/__snapshots__/Tag.test.tsx.snap b/packages/react-components/react-tags/src/components/Tag/__snapshots__/Tag.test.tsx.snap index f2701f46afe480..f66f95a0e95775 100644 --- a/packages/react-components/react-tags/src/components/Tag/__snapshots__/Tag.test.tsx.snap +++ b/packages/react-components/react-tags/src/components/Tag/__snapshots__/Tag.test.tsx.snap @@ -5,7 +5,57 @@ exports[`Tag renders a default state 1`] = `
- Default Tag + + + + KA + + + + i + + + Primary text + + + Secondary text + + +
`; diff --git a/packages/react-components/react-tags/src/components/Tag/renderTag.tsx b/packages/react-components/react-tags/src/components/Tag/renderTag.tsx index 27af51419c971f..ab3e1d6e61433b 100644 --- a/packages/react-components/react-tags/src/components/Tag/renderTag.tsx +++ b/packages/react-components/react-tags/src/components/Tag/renderTag.tsx @@ -13,5 +13,17 @@ export const renderTag_unstable = (state: TagState) => { const { slots, slotProps } = getSlotsNext(state); // TODO Add additional slots in the appropriate place - return ; + return ( + + {slots.content && ( + + {slots.avatar && } + {slots.icon && } + {slots.primaryText && } + {slots.secondaryText && } + + )} + {slots.dismissButton && state.dismissable && } + + ); }; diff --git a/packages/react-components/react-tags/src/components/Tag/useTag.ts b/packages/react-components/react-tags/src/components/Tag/useTag.ts deleted file mode 100644 index 67bed0af432f4f..00000000000000 --- a/packages/react-components/react-tags/src/components/Tag/useTag.ts +++ /dev/null @@ -1,28 +0,0 @@ -import * as React from 'react'; -import { getNativeElementProps } from '@fluentui/react-utilities'; -import type { TagProps, TagState } from './Tag.types'; - -/** - * Create the state required to render Tag. - * - * The returned state can be modified with hooks such as useTagStyles_unstable, - * before being passed to renderTag_unstable. - * - * @param props - props from this instance of Tag - * @param ref - reference to root HTMLElement of Tag - */ -export const useTag_unstable = (props: TagProps, ref: React.Ref): TagState => { - return { - // TODO add appropriate props/defaults - components: { - // TODO add each slot's element type or component - root: 'div', - }, - // TODO add appropriate slots, for example: - // mySlot: resolveShorthand(props.mySlot), - root: getNativeElementProps('div', { - ref, - ...props, - }), - }; -}; diff --git a/packages/react-components/react-tags/src/components/Tag/useTag.tsx b/packages/react-components/react-tags/src/components/Tag/useTag.tsx new file mode 100644 index 00000000000000..0965e8455d9712 --- /dev/null +++ b/packages/react-components/react-tags/src/components/Tag/useTag.tsx @@ -0,0 +1,60 @@ +import * as React from 'react'; +import { getNativeElementProps, resolveShorthand } from '@fluentui/react-utilities'; +import { Dismiss16Filled } from '@fluentui/react-icons'; +import { Avatar } from '@fluentui/react-avatar'; +import type { TagProps, TagState } from './Tag.types'; + +/** + * Create the state required to render Tag. + * + * The returned state can be modified with hooks such as useTagStyles_unstable, + * before being passed to renderTag_unstable. + * + * @param props - props from this instance of Tag + * @param ref - reference to root HTMLElement of Tag + */ +export const useTag_unstable = (props: TagProps, ref: React.Ref): TagState => { + const { + checked = false, + disabled = false, + dismissable = false, + shape = 'rounded', + size = 'medium', + appearance = 'filled-lighter', + } = props; + + return { + components: { + root: 'div', + content: 'span', + avatar: Avatar, + icon: 'span', + primaryText: 'span', + secondaryText: 'span', + dismissButton: 'button', + }, + checked, + disabled, + dismissable, + shape, + size, + appearance, + root: getNativeElementProps('div', { + ref, + ...props, + }), + content: resolveShorthand(props.content, { required: true }), + avatar: resolveShorthand(props.avatar), + icon: resolveShorthand(props.icon), + primaryText: resolveShorthand(props.primaryText), + secondaryText: resolveShorthand(props.secondaryText), + dismissButton: resolveShorthand(props.dismissButton, { + required: true, + defaultProps: { + disabled, + type: 'button', + children: , + }, + }), + }; +}; diff --git a/packages/react-components/react-tags/src/components/Tag/useTagStyles.ts b/packages/react-components/react-tags/src/components/Tag/useTagStyles.ts index 6faa08d90aaf48..d388013ad1ebeb 100644 --- a/packages/react-components/react-tags/src/components/Tag/useTagStyles.ts +++ b/packages/react-components/react-tags/src/components/Tag/useTagStyles.ts @@ -1,11 +1,15 @@ -import { makeStyles, mergeClasses } from '@griffel/react'; +import { makeStyles, mergeClasses, shorthands } from '@griffel/react'; import type { TagSlots, TagState } from './Tag.types'; import type { SlotClassNames } from '@fluentui/react-utilities'; export const tagClassNames: SlotClassNames = { root: 'fui-Tag', - // TODO: add class names for all slots on TagSlots. - // Should be of the form `: 'fui-Tag__` + content: 'fui-Tag__content', + avatar: 'fui-Tag__avatar', + icon: 'fui-Tag__icon', + primaryText: 'fui-Tag__primaryText', + secondaryText: 'fui-Tag__secondaryText', + dismissButton: 'fui-Tag__dismissButton', }; /** @@ -13,8 +17,30 @@ export const tagClassNames: SlotClassNames = { */ const useStyles = makeStyles({ root: { - // TODO Add default styles for the root element + display: 'inline-flex', }, + content: { + display: 'inline-grid', + gridTemplateColumns: 'auto 8px auto auto 8px auto', + gridTemplateRows: '1fr auto auto 1fr', + gridTemplateAreas: ` + "avatar . icon . ." + "avatar . icon primary ." + "avatar . icon secondary ." + "avatar . icon . ." + `, + }, + avatar: { + alignSelf: 'center', + ...shorthands.gridArea('avatar'), + }, + icon: { + alignSelf: 'center', + ...shorthands.gridArea('icon'), + }, + primaryText: { ...shorthands.gridArea('primary') }, + secondaryText: { ...shorthands.gridArea('secondary') }, + dismissButton: {}, // TODO add additional classes for different states and/or slots }); @@ -25,9 +51,36 @@ const useStyles = makeStyles({ export const useTagStyles_unstable = (state: TagState): TagState => { const styles = useStyles(); state.root.className = mergeClasses(tagClassNames.root, styles.root, state.root.className); - - // TODO Add class names to slots, for example: - // state.mySlot.className = mergeClasses(styles.mySlot, state.mySlot.className); + if (state.content) { + state.content.className = mergeClasses(tagClassNames.content, styles.content, state.content.className); + } + if (state.avatar) { + state.avatar.className = mergeClasses(tagClassNames.avatar, styles.avatar, state.avatar.className); + } + if (state.icon) { + state.icon.className = mergeClasses(tagClassNames.icon, styles.icon, state.icon.className); + } + if (state.primaryText) { + state.primaryText.className = mergeClasses( + tagClassNames.primaryText, + styles.primaryText, + state.primaryText.className, + ); + } + if (state.secondaryText) { + state.secondaryText.className = mergeClasses( + tagClassNames.secondaryText, + styles.secondaryText, + state.secondaryText.className, + ); + } + if (state.dismissButton) { + state.dismissButton.className = mergeClasses( + tagClassNames.dismissButton, + styles.dismissButton, + state.dismissButton.className, + ); + } return state; }; diff --git a/packages/react-components/react-tags/src/components/TagButton/TagButton.test.tsx b/packages/react-components/react-tags/src/components/TagButton/TagButton.test.tsx index a5257d7328b180..00568aabcc30d1 100644 --- a/packages/react-components/react-tags/src/components/TagButton/TagButton.test.tsx +++ b/packages/react-components/react-tags/src/components/TagButton/TagButton.test.tsx @@ -3,16 +3,27 @@ import { render } from '@testing-library/react'; import { TagButton } from './TagButton'; import { isConformant } from '../../testing/isConformant'; +const requiredProps = { + avatar: { + name: 'Katri Athokas', + }, + icon: 'i', + primaryText: 'Primary text', + secondaryText: 'Secondary text', + dismissable: true, +}; + describe('TagButton', () => { isConformant({ Component: TagButton, displayName: 'TagButton', + requiredProps, }); // TODO add more tests here, and create visual regression tests in /apps/vr-tests it('renders a default state', () => { - const result = render(Default TagButton); + const result = render(Default TagButton); expect(result.container).toMatchSnapshot(); }); }); diff --git a/packages/react-components/react-tags/src/components/TagButton/TagButton.types.ts b/packages/react-components/react-tags/src/components/TagButton/TagButton.types.ts index d8590ba8b3d3b4..807800361a382e 100644 --- a/packages/react-components/react-tags/src/components/TagButton/TagButton.types.ts +++ b/packages/react-components/react-tags/src/components/TagButton/TagButton.types.ts @@ -1,17 +1,30 @@ import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; +import { Avatar } from '@fluentui/react-avatar'; export type TagButtonSlots = { - root: Slot<'div'>; + root: NonNullable>; + contentButton?: Slot<'button'>; + avatar?: Slot; + icon?: Slot<'span'>; + primaryText?: Slot<'span'>; + secondaryText?: Slot<'span'>; + dismissButton?: NonNullable>; }; /** * TagButton Props */ -export type TagButtonProps = ComponentProps & {}; +export type TagButtonProps = ComponentProps & { + size?: 'extra-small' | 'small' | 'medium'; + shape?: 'rounded' | 'circular'; + appearance?: 'filled-darker' | 'filled-lighter' | 'tint' | 'outline'; + disabled?: boolean; + checked?: boolean; + dismissable?: boolean; +}; /** * State used in rendering TagButton */ -export type TagButtonState = ComponentState; -// TODO: Remove semicolon from previous line, uncomment next line, and provide union of props to pick from TagButtonProps. -// & Required> +export type TagButtonState = ComponentState & + Required>; diff --git a/packages/react-components/react-tags/src/components/TagButton/__snapshots__/TagButton.test.tsx.snap b/packages/react-components/react-tags/src/components/TagButton/__snapshots__/TagButton.test.tsx.snap index 10f50a682bcb66..ad849b8d3f3003 100644 --- a/packages/react-components/react-tags/src/components/TagButton/__snapshots__/TagButton.test.tsx.snap +++ b/packages/react-components/react-tags/src/components/TagButton/__snapshots__/TagButton.test.tsx.snap @@ -5,7 +5,57 @@ exports[`TagButton renders a default state 1`] = `
- Default TagButton + +
`; diff --git a/packages/react-components/react-tags/src/components/TagButton/renderTagButton.tsx b/packages/react-components/react-tags/src/components/TagButton/renderTagButton.tsx index 25a0acd909b130..17836bf23f9c6d 100644 --- a/packages/react-components/react-tags/src/components/TagButton/renderTagButton.tsx +++ b/packages/react-components/react-tags/src/components/TagButton/renderTagButton.tsx @@ -13,5 +13,17 @@ export const renderTagButton_unstable = (state: TagButtonState) => { const { slots, slotProps } = getSlotsNext(state); // TODO Add additional slots in the appropriate place - return ; + return ( + + {slots.contentButton && ( + + {slots.avatar && } + {slots.icon && } + {slots.primaryText && } + {slots.secondaryText && } + + )} + {slots.dismissButton && state.dismissable && } + + ); }; diff --git a/packages/react-components/react-tags/src/components/TagButton/useTagButton.ts b/packages/react-components/react-tags/src/components/TagButton/useTagButton.ts deleted file mode 100644 index 912c9a85cc99f1..00000000000000 --- a/packages/react-components/react-tags/src/components/TagButton/useTagButton.ts +++ /dev/null @@ -1,28 +0,0 @@ -import * as React from 'react'; -import { getNativeElementProps } from '@fluentui/react-utilities'; -import type { TagButtonProps, TagButtonState } from './TagButton.types'; - -/** - * Create the state required to render TagButton. - * - * The returned state can be modified with hooks such as useTagButtonStyles_unstable, - * before being passed to renderTagButton_unstable. - * - * @param props - props from this instance of TagButton - * @param ref - reference to root HTMLElement of TagButton - */ -export const useTagButton_unstable = (props: TagButtonProps, ref: React.Ref): TagButtonState => { - return { - // TODO add appropriate props/defaults - components: { - // TODO add each slot's element type or component - root: 'div', - }, - // TODO add appropriate slots, for example: - // mySlot: resolveShorthand(props.mySlot), - root: getNativeElementProps('div', { - ref, - ...props, - }), - }; -}; diff --git a/packages/react-components/react-tags/src/components/TagButton/useTagButton.tsx b/packages/react-components/react-tags/src/components/TagButton/useTagButton.tsx new file mode 100644 index 00000000000000..5a359ada2eec39 --- /dev/null +++ b/packages/react-components/react-tags/src/components/TagButton/useTagButton.tsx @@ -0,0 +1,60 @@ +import * as React from 'react'; +import { getNativeElementProps, resolveShorthand } from '@fluentui/react-utilities'; +import type { TagButtonProps, TagButtonState } from './TagButton.types'; +import { Dismiss16Filled } from '@fluentui/react-icons'; +import { Avatar } from '@fluentui/react-avatar'; + +/** + * Create the state required to render TagButton. + * + * The returned state can be modified with hooks such as useTagButtonStyles_unstable, + * before being passed to renderTagButton_unstable. + * + * @param props - props from this instance of TagButton + * @param ref - reference to root HTMLElement of TagButton + */ +export const useTagButton_unstable = (props: TagButtonProps, ref: React.Ref): TagButtonState => { + const { + checked = false, + disabled = false, + dismissable = false, + shape = 'rounded', + size = 'medium', + appearance = 'filled-lighter', + } = props; + + return { + components: { + root: 'div', + contentButton: 'button', + avatar: Avatar, + icon: 'span', + primaryText: 'span', + secondaryText: 'span', + dismissButton: 'button', + }, + checked, + disabled, + dismissable, + shape, + size, + appearance, + root: getNativeElementProps('div', { + ref, + ...props, + }), + contentButton: resolveShorthand(props.contentButton, { required: true }), + avatar: resolveShorthand(props.avatar), + icon: resolveShorthand(props.icon), + primaryText: resolveShorthand(props.primaryText), + secondaryText: resolveShorthand(props.secondaryText), + dismissButton: resolveShorthand(props.dismissButton, { + required: true, + defaultProps: { + disabled, + type: 'button', + children: , + }, + }), + }; +}; diff --git a/packages/react-components/react-tags/src/components/TagButton/useTagButtonStyles.ts b/packages/react-components/react-tags/src/components/TagButton/useTagButtonStyles.ts index 64364e62d1d3c8..c03ad488ae53f5 100644 --- a/packages/react-components/react-tags/src/components/TagButton/useTagButtonStyles.ts +++ b/packages/react-components/react-tags/src/components/TagButton/useTagButtonStyles.ts @@ -1,11 +1,15 @@ -import { makeStyles, mergeClasses } from '@griffel/react'; +import { makeStyles, mergeClasses, shorthands } from '@griffel/react'; import type { TagButtonSlots, TagButtonState } from './TagButton.types'; import type { SlotClassNames } from '@fluentui/react-utilities'; export const tagButtonClassNames: SlotClassNames = { root: 'fui-TagButton', - // TODO: add class names for all slots on TagButtonSlots. - // Should be of the form `: 'fui-TagButton__` + contentButton: 'fui-TagButton__contentButton', + avatar: 'fui-TagButton__avatar', + icon: 'fui-TagButton__icon', + primaryText: 'fui-TagButton__primaryText', + secondaryText: 'fui-TagButton__secondaryText', + dismissButton: 'fui-TagButton__dismissButton', }; /** @@ -13,8 +17,30 @@ export const tagButtonClassNames: SlotClassNames = { */ const useStyles = makeStyles({ root: { - // TODO Add default styles for the root element + display: 'inline-flex', }, + contentButton: { + display: 'inline-grid', + gridTemplateColumns: 'auto 8px auto auto 8px auto', + gridTemplateRows: '1fr auto auto 1fr', + gridTemplateAreas: ` + "avatar . icon . ." + "avatar . icon primary ." + "avatar . icon secondary ." + "avatar . icon . ." + `, + }, + avatar: { + alignSelf: 'center', + ...shorthands.gridArea('avatar'), + }, + icon: { + alignSelf: 'center', + ...shorthands.gridArea('icon'), + }, + primaryText: { ...shorthands.gridArea('primary') }, + secondaryText: { ...shorthands.gridArea('secondary') }, + dismissButton: {}, // TODO add additional classes for different states and/or slots }); @@ -25,9 +51,40 @@ const useStyles = makeStyles({ export const useTagButtonStyles_unstable = (state: TagButtonState): TagButtonState => { const styles = useStyles(); state.root.className = mergeClasses(tagButtonClassNames.root, styles.root, state.root.className); - - // TODO Add class names to slots, for example: - // state.mySlot.className = mergeClasses(styles.mySlot, state.mySlot.className); + if (state.contentButton) { + state.contentButton.className = mergeClasses( + tagButtonClassNames.contentButton, + styles.contentButton, + state.contentButton.className, + ); + } + if (state.avatar) { + state.avatar.className = mergeClasses(tagButtonClassNames.avatar, styles.avatar, state.avatar.className); + } + if (state.icon) { + state.icon.className = mergeClasses(tagButtonClassNames.icon, styles.icon, state.icon.className); + } + if (state.primaryText) { + state.primaryText.className = mergeClasses( + tagButtonClassNames.primaryText, + styles.primaryText, + state.primaryText.className, + ); + } + if (state.secondaryText) { + state.secondaryText.className = mergeClasses( + tagButtonClassNames.secondaryText, + styles.secondaryText, + state.secondaryText.className, + ); + } + if (state.dismissButton) { + state.dismissButton.className = mergeClasses( + tagButtonClassNames.dismissButton, + styles.dismissButton, + state.dismissButton.className, + ); + } return state; }; diff --git a/packages/react-components/react-tags/stories/Tag/TagDefault.stories.tsx b/packages/react-components/react-tags/stories/Tag/TagDefault.stories.tsx index 342622eceed82b..c6639a6746769a 100644 --- a/packages/react-components/react-tags/stories/Tag/TagDefault.stories.tsx +++ b/packages/react-components/react-tags/stories/Tag/TagDefault.stories.tsx @@ -1,4 +1,20 @@ import * as React from 'react'; import { Tag, TagProps } from '@fluentui/react-tags'; +import { Calendar3Day28Regular } from '@fluentui/react-icons'; -export const Default = (props: Partial) => ; +export const Default = (props: Partial) => ( + } + primaryText="Primary text" + secondaryText="Secondary text" + dismissable={true} + {...props} + /> +); diff --git a/packages/react-components/react-tags/stories/TagButton/TagButtonDefault.stories.tsx b/packages/react-components/react-tags/stories/TagButton/TagButtonDefault.stories.tsx index 6956d82a32f358..08c2b41a875738 100644 --- a/packages/react-components/react-tags/stories/TagButton/TagButtonDefault.stories.tsx +++ b/packages/react-components/react-tags/stories/TagButton/TagButtonDefault.stories.tsx @@ -1,4 +1,20 @@ import * as React from 'react'; import { TagButton, TagButtonProps } from '@fluentui/react-tags'; +import { Calendar3Day28Regular } from '@fluentui/react-icons'; -export const Default = (props: Partial) => ; +export const Default = (props: Partial) => ( + } + primaryText="Primary text" + secondaryText="Secondary text" + dismissable={true} + {...props} + /> +);