diff --git a/change/@fluentui-react-tree-816beea2-f6e6-48f9-8dbc-d3bb8c34bd02.json b/change/@fluentui-react-tree-816beea2-f6e6-48f9-8dbc-d3bb8c34bd02.json new file mode 100644 index 0000000000000..8e2f2bc806991 --- /dev/null +++ b/change/@fluentui-react-tree-816beea2-f6e6-48f9-8dbc-d3bb8c34bd02.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "bugfix: aligns TreeItem leaf and branch nodes", + "packageName": "@fluentui/react-tree", + "email": "petrduda@microsoft.com", + "dependentChangeType": "none" +} diff --git a/packages/react-components/react-tree/etc/react-tree.api.md b/packages/react-components/react-tree/etc/react-tree.api.md index f6ae2215fb109..66f4cac3c7359 100644 --- a/packages/react-components/react-tree/etc/react-tree.api.md +++ b/packages/react-components/react-tree/etc/react-tree.api.md @@ -112,6 +112,7 @@ export type TreeItemLayoutProps = ComponentProps>; // @public (undocumented) export type TreeItemLayoutSlots = { root: Slot<'div'>; + content: NonNullable>; iconBefore?: Slot<'div'>; iconAfter?: Slot<'div'>; expandIcon?: Slot<'div'>; @@ -142,7 +143,7 @@ export type TreeItemPersonaLayoutProps = ComponentProps & { root: NonNullable>; media: NonNullable>; - main: NonNullable>; + content: NonNullable>; description?: Slot<'div'>; }; diff --git a/packages/react-components/react-tree/src/components/TreeItemLayout/TreeItemLayout.types.ts b/packages/react-components/react-tree/src/components/TreeItemLayout/TreeItemLayout.types.ts index 3f60a079a7f8d..92c581aff0947 100644 --- a/packages/react-components/react-tree/src/components/TreeItemLayout/TreeItemLayout.types.ts +++ b/packages/react-components/react-tree/src/components/TreeItemLayout/TreeItemLayout.types.ts @@ -3,6 +3,10 @@ import { ButtonContextValue } from '@fluentui/react-button'; export type TreeItemLayoutSlots = { root: Slot<'div'>; + /** + * Content. Children of the root slot are automatically rendered here + */ + content: NonNullable>; /** * Icon slot that renders right before main content */ diff --git a/packages/react-components/react-tree/src/components/TreeItemLayout/__snapshots__/TreeItemLayout.test.tsx.snap b/packages/react-components/react-tree/src/components/TreeItemLayout/__snapshots__/TreeItemLayout.test.tsx.snap index f07aa64b74c75..3215f259cff15 100644 --- a/packages/react-components/react-tree/src/components/TreeItemLayout/__snapshots__/TreeItemLayout.test.tsx.snap +++ b/packages/react-components/react-tree/src/components/TreeItemLayout/__snapshots__/TreeItemLayout.test.tsx.snap @@ -5,7 +5,11 @@ exports[`TreeItemLayout renders a default state 1`] = `
- Default TreeItemLayout +
+ Default TreeItemLayout +
`; diff --git a/packages/react-components/react-tree/src/components/TreeItemLayout/renderTreeItemLayout.tsx b/packages/react-components/react-tree/src/components/TreeItemLayout/renderTreeItemLayout.tsx index cd2d591217bc7..1a04c3f05aca0 100644 --- a/packages/react-components/react-tree/src/components/TreeItemLayout/renderTreeItemLayout.tsx +++ b/packages/react-components/react-tree/src/components/TreeItemLayout/renderTreeItemLayout.tsx @@ -16,7 +16,7 @@ export const renderTreeItemLayout_unstable = (state: TreeItemLayoutState) => { {slots.expandIcon && } {slots.iconBefore && } - {slotProps.root.children} + {slotProps.root.children} {slots.iconAfter && } {slots.actions && } diff --git a/packages/react-components/react-tree/src/components/TreeItemLayout/useTreeItemLayout.tsx b/packages/react-components/react-tree/src/components/TreeItemLayout/useTreeItemLayout.tsx index 126d2a3406647..2b675617ba934 100644 --- a/packages/react-components/react-tree/src/components/TreeItemLayout/useTreeItemLayout.tsx +++ b/packages/react-components/react-tree/src/components/TreeItemLayout/useTreeItemLayout.tsx @@ -23,7 +23,7 @@ export const useTreeItemLayout_unstable = ( props: TreeItemLayoutProps, ref: React.Ref, ): TreeItemLayoutState => { - const { iconAfter, iconBefore, expandIcon, as = 'span', aside, actions } = props; + const { content, iconAfter, iconBefore, expandIcon, as = 'span', aside, actions } = props; const layoutRef = useTreeItemContext_unstable(ctx => ctx.layoutRef); const expandIconRef = useTreeItemContext_unstable(ctx => ctx.expandIconRef); @@ -41,6 +41,7 @@ export const useTreeItemLayout_unstable = ( root: 'div', expandIcon: 'div', iconBefore: 'div', + content: 'div', iconAfter: 'div', actions: 'div', aside: 'div', @@ -48,6 +49,7 @@ export const useTreeItemLayout_unstable = ( buttonContextValue: { size: 'small' }, root: getNativeElementProps(as, { ...props, ref: useMergedRefs(ref, layoutRef) }), iconBefore: resolveShorthand(iconBefore, { defaultProps: { 'aria-hidden': true } }), + content: resolveShorthand(content, { required: true }), iconAfter: resolveShorthand(iconAfter, { defaultProps: { 'aria-hidden': true } }), aside: isAsideVisible ? resolveShorthand(aside) : undefined, actions: isActionsVisible diff --git a/packages/react-components/react-tree/src/components/TreeItemLayout/useTreeItemLayoutStyles.styles.ts b/packages/react-components/react-tree/src/components/TreeItemLayout/useTreeItemLayoutStyles.styles.ts index 0ca89dbb84d9a..a814aebca5720 100644 --- a/packages/react-components/react-tree/src/components/TreeItemLayout/useTreeItemLayoutStyles.styles.ts +++ b/packages/react-components/react-tree/src/components/TreeItemLayout/useTreeItemLayoutStyles.styles.ts @@ -9,6 +9,7 @@ import { useTreeItemContext_unstable } from '../../contexts/treeItemContext'; export const treeItemLayoutClassNames: SlotClassNames = { root: 'fui-TreeItemLayout', iconBefore: 'fui-TreeItemLayout__iconBefore', + content: 'fui-TreeItemLayout__content', iconAfter: 'fui-TreeItemLayout__iconAfter', expandIcon: 'fui-TreeItemLayout__expandIcon', aside: 'fui-TreeItemLayout__aside', @@ -50,11 +51,9 @@ const useRootStyles = makeStyles({ paddingLeft: `calc((var(${treeItemLevelToken}, 1) - 1) * ${tokens.spacingHorizontalXXL})`, }, medium: { - columnGap: tokens.spacingHorizontalSNudge, ...typographyStyles.body1, }, small: { - columnGap: tokens.spacingHorizontalXS, minHeight: '24px', ...typographyStyles.caption1, }, @@ -79,21 +78,6 @@ const useRootStyles = makeStyles({ }, }); -/** - * Styles for the before/after icon slot - */ -const useIconStyles = makeStyles({ - base: { - display: 'flex', - alignItems: 'center', - color: tokens.colorNeutralForeground2, - lineHeight: tokens.lineHeightBase500, - fontSize: tokens.fontSizeBase500, - }, - iconBefore: {}, - iconAfter: {}, -}); - /** * Styles for the action icon slot */ @@ -138,16 +122,61 @@ const useExpandIconStyles = makeStyles({ }, }); +/** + * Styles for the content slot + */ +const useContentStyles = makeStyles({ + base: { + ...shorthands.padding(0, tokens.spacingHorizontalXXS), + }, +}); + +/** + * Styles for the before/after icon slot + */ +const useIconStyles = makeStyles({ + base: { + display: 'flex', + alignItems: 'center', + color: tokens.colorNeutralForeground2, + lineHeight: tokens.lineHeightBase500, + fontSize: tokens.fontSizeBase500, + }, +}); + +const useIconBeforeStyles = makeStyles({ + medium: { + paddingRight: tokens.spacingHorizontalXS, + }, + small: { + paddingRight: tokens.spacingHorizontalXXS, + }, +}); + +const useIconAfterStyles = makeStyles({ + medium: { + paddingLeft: tokens.spacingHorizontalXS, + }, + small: { + paddingLeft: tokens.spacingHorizontalXXS, + }, +}); + /** * Apply styling to the TreeItemLayout slots based on the state */ export const useTreeItemLayoutStyles_unstable = (state: TreeItemLayoutState): TreeItemLayoutState => { - const { iconAfter, iconBefore, root } = state; + const { content, iconAfter, iconBefore, expandIcon, root } = state; const rootStyles = useRootStyles(); - const iconStyles = useIconStyles(); const actionsStyles = useActionsStyles(); const asideStyles = useAsideStyles(); + + const contentStyles = useContentStyles(); + const expandIconStyles = useExpandIconStyles(); + const iconStyles = useIconStyles(); + const iconBeforeStyles = useIconBeforeStyles(); + const iconAfterStyles = useIconAfterStyles(); const size = useTreeContext_unstable(ctx => ctx.size); const appearance = useTreeContext_unstable(ctx => ctx.appearance); @@ -162,11 +191,21 @@ export const useTreeItemLayoutStyles_unstable = (state: TreeItemLayoutState): Tr root.className, ); + content.className = mergeClasses(treeItemLayoutClassNames.content, contentStyles.base, content.className); + + if (expandIcon) { + expandIcon.className = mergeClasses( + treeItemLayoutClassNames.expandIcon, + expandIconStyles.base, + expandIcon.className, + ); + } + if (iconBefore) { iconBefore.className = mergeClasses( treeItemLayoutClassNames.iconBefore, iconStyles.base, - iconStyles.iconBefore, + iconBeforeStyles[size], iconBefore.className, ); } @@ -175,7 +214,7 @@ export const useTreeItemLayoutStyles_unstable = (state: TreeItemLayoutState): Tr iconAfter.className = mergeClasses( treeItemLayoutClassNames.iconAfter, iconStyles.base, - iconStyles.iconAfter, + iconAfterStyles[size], iconAfter.className, ); } diff --git a/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/TreeItemPersonaLayout.types.ts b/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/TreeItemPersonaLayout.types.ts index b15f5fb9bb5bc..7ceae9c99fc29 100644 --- a/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/TreeItemPersonaLayout.types.ts +++ b/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/TreeItemPersonaLayout.types.ts @@ -14,11 +14,11 @@ export type TreeItemPersonaLayoutSlots = Pick>; /** - * Main text. Children of the root slot are automatically rendered here + * Content. Children of the root slot are automatically rendered here */ - main: NonNullable>; + content: NonNullable>; /** - * Secondary text that describes or complements the main text + * Secondary text that describes or complements the content */ description?: Slot<'div'>; }; diff --git a/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/__snapshots__/TreeItemPersonaLayout.test.tsx.snap b/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/__snapshots__/TreeItemPersonaLayout.test.tsx.snap index 4d28b8064aa84..ac615454c8b90 100644 --- a/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/__snapshots__/TreeItemPersonaLayout.test.tsx.snap +++ b/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/__snapshots__/TreeItemPersonaLayout.test.tsx.snap @@ -9,7 +9,7 @@ exports[`TreeItemPersonaLayout renders a default state 1`] = ` class="fui-TreeItemPersonaLayout__media" />
Default TreeItemPersonaLayout
diff --git a/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/renderTreeItemPersonaLayout.tsx b/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/renderTreeItemPersonaLayout.tsx index e03c1440a9a46..86ad6770d0c89 100644 --- a/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/renderTreeItemPersonaLayout.tsx +++ b/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/renderTreeItemPersonaLayout.tsx @@ -26,7 +26,7 @@ export const renderTreeItemPersonaLayout_unstable = ( - + {slots.description && } {slots.actions && } diff --git a/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/useTreeItemPersonaLayout.tsx b/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/useTreeItemPersonaLayout.tsx index c0e683cd7a45f..ef222db21e458 100644 --- a/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/useTreeItemPersonaLayout.tsx +++ b/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/useTreeItemPersonaLayout.tsx @@ -18,7 +18,7 @@ export const useTreeItemPersonaLayout_unstable = ( props: TreeItemPersonaLayoutProps, ref: React.Ref, ): TreeItemPersonaLayoutState => { - const { media, children, main, description } = props; + const { media, children, content, description } = props; const treeItemLayoutState = useTreeItemLayout_unstable( { @@ -34,7 +34,7 @@ export const useTreeItemPersonaLayout_unstable = ( ...treeItemLayoutState, components: { expandIcon: 'div', - main: 'div', + content: 'div', description: 'div', root: 'div', media: 'div', @@ -42,7 +42,7 @@ export const useTreeItemPersonaLayout_unstable = ( actions: 'div', }, avatarSize: treeAvatarSize[size], - main: resolveShorthand(main, { required: true, defaultProps: { children } }), + content: resolveShorthand(content, { required: true, defaultProps: { children } }), media: resolveShorthand(media, { required: true }), description: resolveShorthand(description), }; diff --git a/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/useTreeItemPersonaLayoutStyles.styles.ts b/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/useTreeItemPersonaLayoutStyles.styles.ts index 6124df7ba2cd0..c79669aab55a7 100644 --- a/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/useTreeItemPersonaLayoutStyles.styles.ts +++ b/packages/react-components/react-tree/src/components/TreeItemPersonaLayout/useTreeItemPersonaLayoutStyles.styles.ts @@ -9,7 +9,7 @@ export const treeItemPersonaLayoutClassNames: SlotClassNames ctx.itemType); @@ -161,12 +161,12 @@ export const useTreeItemPersonaLayoutStyles_unstable = ( state.media.className = mergeClasses(treeItemPersonaLayoutClassNames.media, mediaStyles.base, state.media.className); - if (state.main) { - state.main.className = mergeClasses( - treeItemPersonaLayoutClassNames.main, - mainStyles.base, - state.description && mainStyles.withDescription, - state.main.className, + if (state.content) { + state.content.className = mergeClasses( + treeItemPersonaLayoutClassNames.content, + contentStyles.base, + state.description && contentStyles.withDescription, + state.content.className, ); } if (state.description) { diff --git a/packages/react-components/react-tree/stories/A_Tree/TreeDefault.stories.tsx b/packages/react-components/react-tree/stories/A_Tree/TreeDefault.stories.tsx index 2618cf5b1f1e0..1c92c4d2e6061 100644 --- a/packages/react-components/react-tree/stories/A_Tree/TreeDefault.stories.tsx +++ b/packages/react-components/react-tree/stories/A_Tree/TreeDefault.stories.tsx @@ -31,6 +31,9 @@ export const Default = () => { + + level 1, item 3 + ); }; diff --git a/packages/react-components/react-tree/stories/C_Layouts/TreeItemLayoutIconBefore.stories.tsx b/packages/react-components/react-tree/stories/C_Layouts/TreeItemLayoutIconBefore.stories.tsx index 645de195d24f0..1dcdff566f90f 100644 --- a/packages/react-components/react-tree/stories/C_Layouts/TreeItemLayoutIconBefore.stories.tsx +++ b/packages/react-components/react-tree/stories/C_Layouts/TreeItemLayoutIconBefore.stories.tsx @@ -24,7 +24,7 @@ export const IconBefore = () => { }>level 1, item 2 - level 2, item 1 + level 2, item 1 level 3, item 1