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/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 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..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,7 +1,6 @@ import * as React from 'react'; import { getNativeElementProps, slot } from '@fluentui/react-utilities'; import type { DrawerHeaderTitleProps, DrawerHeaderTitleState } from './DrawerHeaderTitle.types'; -import { useDialogTitle_unstable } from '@fluentui/react-dialog'; /** * Create the state required to render DrawerHeaderTitle. @@ -16,13 +15,19 @@ export const useDrawerHeaderTitle_unstable = ( props: DrawerHeaderTitleProps, ref: React.Ref, ): DrawerHeaderTitleState => { - const { root: heading, action, components: titleComponents } = useDialogTitle_unstable(props, ref); + let heading = slot.resolveShorthand(props.heading); + + if (!heading) { + heading = { + children: props.children, + }; + } return { components: { root: 'div', - heading: titleComponents.root, - action: titleComponents.action, + heading: 'h2', + action: 'div', }, root: slot.always( @@ -32,17 +37,15 @@ export const useDrawerHeaderTitle_unstable = ( }), { elementType: 'div' }, ), - heading: slot.optional(props.heading, { - renderByDefault: true, + heading: slot.optional(getNativeElementProps(heading.as ?? 'h2', heading), { defaultProps: { - ...heading, - className: undefined, // remove className from heading + children: props.children, }, - elementType: titleComponents.root, + renderByDefault: true, + elementType: 'h2', }), 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';