From 91af07b634eafe82ab7643e2b69ae24554bc898f Mon Sep 17 00:00:00 2001 From: Marcos Moura Date: Thu, 31 Aug 2023 19:22:16 +0200 Subject: [PATCH 1/3] fix(react-drawer): refactor DrawerHeaderTitle slot creation while keeping the same API --- ...-93fb2624-7aa8-4c3a-9333-635dcac41292.json | 7 ++++ .../DrawerHeaderTitle.types.ts | 14 ++----- .../DrawerHeaderTitle/useDrawerHeaderTitle.ts | 41 +++++++++++-------- .../Drawer/DrawerWithTitle.stories.tsx | 40 ++++++++++++++++++ .../stories/Drawer/index.stories.tsx | 1 + 5 files changed, 75 insertions(+), 28 deletions(-) create mode 100644 change/@fluentui-react-drawer-93fb2624-7aa8-4c3a-9333-635dcac41292.json create mode 100644 packages/react-components/react-drawer/stories/Drawer/DrawerWithTitle.stories.tsx diff --git a/change/@fluentui-react-drawer-93fb2624-7aa8-4c3a-9333-635dcac41292.json b/change/@fluentui-react-drawer-93fb2624-7aa8-4c3a-9333-635dcac41292.json new file mode 100644 index 00000000000000..35a0e7c1914e68 --- /dev/null +++ b/change/@fluentui-react-drawer-93fb2624-7aa8-4c3a-9333-635dcac41292.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "fix: refactor DrawerHeaderTitle slot creation while keeping the same API", + "packageName": "@fluentui/react-drawer", + "email": "marcosvmmoura@gmail.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-components/react-drawer/src/components/DrawerHeaderTitle/DrawerHeaderTitle.types.ts b/packages/react-components/react-drawer/src/components/DrawerHeaderTitle/DrawerHeaderTitle.types.ts index 7f5c8b4ce6c13c..b0ab2aad4defc2 100644 --- a/packages/react-components/react-drawer/src/components/DrawerHeaderTitle/DrawerHeaderTitle.types.ts +++ b/packages/react-components/react-drawer/src/components/DrawerHeaderTitle/DrawerHeaderTitle.types.ts @@ -1,6 +1,4 @@ -import { DialogTitleSlots } from '@fluentui/react-dialog'; import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; -import * as React from 'react'; export type DrawerHeaderTitleSlots = { root: Slot<'div'>; @@ -9,24 +7,18 @@ export type DrawerHeaderTitleSlots = { * By default this is a h2, but can be any heading or div. * If `div` is provided do not forget to also provide proper `role="heading"` and `aria-level` attributes */ - heading?: DialogTitleSlots['root']; + heading?: Slot<'h2', 'h1' | 'h3' | 'h4' | 'h5' | 'h6' | 'div'>; /** * Action slot for the close button */ - action?: DialogTitleSlots['action']; + action?: Slot<'div'>; }; /** * DrawerHeaderTitle Props */ -export type DrawerHeaderTitleProps = ComponentProps & { - /** - * Content of the DrawerHeaderTitle - * Children is mandatory because DrawerHeaderTitle is a wrapper component - */ - children: React.ReactNode | undefined; -}; +export type DrawerHeaderTitleProps = ComponentProps; /** * State used in rendering DrawerHeaderTitle diff --git a/packages/react-components/react-drawer/src/components/DrawerHeaderTitle/useDrawerHeaderTitle.ts b/packages/react-components/react-drawer/src/components/DrawerHeaderTitle/useDrawerHeaderTitle.ts index e147958bf5f710..3bb7f658fe4e11 100644 --- a/packages/react-components/react-drawer/src/components/DrawerHeaderTitle/useDrawerHeaderTitle.ts +++ b/packages/react-components/react-drawer/src/components/DrawerHeaderTitle/useDrawerHeaderTitle.ts @@ -1,7 +1,24 @@ import * as React from 'react'; -import { getNativeElementProps, slot } from '@fluentui/react-utilities'; +import { getNativeElementProps, slot, resolveShorthand } from '@fluentui/react-utilities'; import type { DrawerHeaderTitleProps, DrawerHeaderTitleState } from './DrawerHeaderTitle.types'; -import { useDialogTitle_unstable } from '@fluentui/react-dialog'; + +const getHeadingSlot = (props: DrawerHeaderTitleProps) => { + let heading = resolveShorthand(props.heading); + + if (!heading) { + heading = { + children: props.children, + }; + } + + return slot.optional(getNativeElementProps(heading.as ?? 'h2', heading), { + defaultProps: { + children: heading.children || props.children, + }, + renderByDefault: true, + elementType: 'h2', + }); +}; /** * Create the state required to render DrawerHeaderTitle. @@ -16,33 +33,23 @@ export const useDrawerHeaderTitle_unstable = ( props: DrawerHeaderTitleProps, ref: React.Ref, ): DrawerHeaderTitleState => { - const { root: heading, action, components: titleComponents } = useDialogTitle_unstable(props, ref); - return { components: { root: 'div', - heading: titleComponents.root, - action: titleComponents.action, + heading: 'h2', + action: 'div', }, root: slot.always( getNativeElementProps('div', { - ref, ...props, + ref, }), { elementType: 'div' }, ), - heading: slot.optional(props.heading, { - renderByDefault: true, - defaultProps: { - ...heading, - className: undefined, // remove className from heading - }, - elementType: titleComponents.root, - }), + heading: getHeadingSlot(props), action: slot.optional(props.action, { - defaultProps: action, - elementType: titleComponents.action, + elementType: 'div', }), }; }; diff --git a/packages/react-components/react-drawer/stories/Drawer/DrawerWithTitle.stories.tsx b/packages/react-components/react-drawer/stories/Drawer/DrawerWithTitle.stories.tsx new file mode 100644 index 00000000000000..f898356b210f38 --- /dev/null +++ b/packages/react-components/react-drawer/stories/Drawer/DrawerWithTitle.stories.tsx @@ -0,0 +1,40 @@ +import * as React from 'react'; +import { DrawerInline, DrawerHeader, DrawerHeaderTitle } from '@fluentui/react-drawer'; +import { Button, makeStyles } from '@fluentui/react-components'; +import { Dismiss24Regular } from '@fluentui/react-icons'; + +const useStyles = makeStyles({ + drawer: { + width: '400px', + height: '600px', + }, +}); + +export const WithTitle = () => { + return ( + + + Drawer with title + Drawer with custom tag + } />}> + Drawer with title and action + + + + ); +}; + +WithTitle.parameters = { + docs: { + controls: { + disable: true, + }, + description: { + story: [ + '`DrawerHeaderTitle` is a component that provides a structured heading for a Drawer and can be used to display a title and an action.', + 'Although it works as a standalone component, it is intended to be used within a `DrawerHeader`.', + 'The title renders an `h2` element by default but it can be customized using the `heading` prop.', + ].join('\n'), + }, + }, +}; diff --git a/packages/react-components/react-drawer/stories/Drawer/index.stories.tsx b/packages/react-components/react-drawer/stories/Drawer/index.stories.tsx index f9be43e8eb0bf5..45ceb28f03fc71 100644 --- a/packages/react-components/react-drawer/stories/Drawer/index.stories.tsx +++ b/packages/react-components/react-drawer/stories/Drawer/index.stories.tsx @@ -19,6 +19,7 @@ export { Position } from './DrawerPosition.stories'; export { Size } from './DrawerSize.stories'; export { CustomSize } from './DrawerCustomSize.stories'; export { Separator } from './DrawerSeparator.stories'; +export { WithTitle } from './DrawerWithTitle.stories'; export { WithNavigation } from './DrawerWithNavigation.stories'; export { WithScroll } from './DrawerWithScroll.stories'; export { AlwaysOpen } from './DrawerAlwaysOpen.stories'; From beea9bce43f33f3038b68ff46030cd6baaf9ef9a Mon Sep 17 00:00:00 2001 From: Marcos Moura Date: Thu, 31 Aug 2023 19:27:06 +0200 Subject: [PATCH 2/3] fix: update API file --- .../react-drawer/etc/react-drawer.api.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/react-components/react-drawer/etc/react-drawer.api.md b/packages/react-components/react-drawer/etc/react-drawer.api.md index d5b87f4109689b..0a9d5bab9728f5 100644 --- a/packages/react-components/react-drawer/etc/react-drawer.api.md +++ b/packages/react-components/react-drawer/etc/react-drawer.api.md @@ -11,7 +11,6 @@ import type { ComponentState } from '@fluentui/react-utilities'; import { DialogProps } from '@fluentui/react-dialog'; import { DialogSurfaceProps } from '@fluentui/react-dialog'; import { DialogSurfaceSlots } from '@fluentui/react-dialog'; -import { DialogTitleSlots } from '@fluentui/react-dialog'; import type { ForwardRefComponent } from '@fluentui/react-utilities'; import { MotionShorthand } from '@fluentui/react-motion-preview'; import { MotionState } from '@fluentui/react-motion-preview'; @@ -97,15 +96,13 @@ export const DrawerHeaderTitle: ForwardRefComponent; export const drawerHeaderTitleClassNames: SlotClassNames; // @public -export type DrawerHeaderTitleProps = ComponentProps & { - children: React_2.ReactNode | undefined; -}; +export type DrawerHeaderTitleProps = ComponentProps; // @public (undocumented) export type DrawerHeaderTitleSlots = { root: Slot<'div'>; - heading?: DialogTitleSlots['root']; - action?: DialogTitleSlots['action']; + heading?: Slot<'h2', 'h1' | 'h3' | 'h4' | 'h5' | 'h6' | 'div'>; + action?: Slot<'div'>; }; // @public From 181b7cb05e936903e69809e22e6f7aa977a3187c Mon Sep 17 00:00:00 2001 From: Marcos Moura Date: Sun, 3 Sep 2023 19:19:15 +0200 Subject: [PATCH 3/3] fix(react-drawer): refactor DrawerHeaderTitle slot creation while keeping the same API --- .../DrawerHeaderTitle/useDrawerHeaderTitle.ts | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/packages/react-components/react-drawer/src/components/DrawerHeaderTitle/useDrawerHeaderTitle.ts b/packages/react-components/react-drawer/src/components/DrawerHeaderTitle/useDrawerHeaderTitle.ts index 3bb7f658fe4e11..c62ae15a3480a7 100644 --- a/packages/react-components/react-drawer/src/components/DrawerHeaderTitle/useDrawerHeaderTitle.ts +++ b/packages/react-components/react-drawer/src/components/DrawerHeaderTitle/useDrawerHeaderTitle.ts @@ -1,25 +1,7 @@ import * as React from 'react'; -import { getNativeElementProps, slot, resolveShorthand } from '@fluentui/react-utilities'; +import { getNativeElementProps, slot } from '@fluentui/react-utilities'; import type { DrawerHeaderTitleProps, DrawerHeaderTitleState } from './DrawerHeaderTitle.types'; -const getHeadingSlot = (props: DrawerHeaderTitleProps) => { - let heading = resolveShorthand(props.heading); - - if (!heading) { - heading = { - children: props.children, - }; - } - - return slot.optional(getNativeElementProps(heading.as ?? 'h2', heading), { - defaultProps: { - children: heading.children || props.children, - }, - renderByDefault: true, - elementType: 'h2', - }); -}; - /** * Create the state required to render DrawerHeaderTitle. * @@ -33,6 +15,14 @@ export const useDrawerHeaderTitle_unstable = ( props: DrawerHeaderTitleProps, ref: React.Ref, ): DrawerHeaderTitleState => { + let heading = slot.resolveShorthand(props.heading); + + if (!heading) { + heading = { + children: props.children, + }; + } + return { components: { root: 'div', @@ -42,12 +32,18 @@ export const useDrawerHeaderTitle_unstable = ( root: slot.always( getNativeElementProps('div', { - ...props, ref, + ...props, }), { elementType: 'div' }, ), - heading: getHeadingSlot(props), + heading: slot.optional(getNativeElementProps(heading.as ?? 'h2', heading), { + defaultProps: { + children: props.children, + }, + renderByDefault: true, + elementType: 'h2', + }), action: slot.optional(props.action, { elementType: 'div', }),