Skip to content

Commit 470f27a

Browse files
rachethecreatorMitch-At-Work
authored andcommitted
add breadcrumb to semantic style hooks (#34837)
1 parent d29f61f commit 470f27a

File tree

13 files changed

+356
-1
lines changed

13 files changed

+356
-1
lines changed

packages/react-components/semantic-style-hooks-preview/library/etc/semantic-style-hooks-preview.api.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
import { AccordionHeaderState } from '@fluentui/react-accordion';
88
import { AvatarState } from '@fluentui/react-avatar';
99
import { BadgeState } from '@fluentui/react-badge';
10+
import { BreadcrumbButtonState } from '@fluentui/react-breadcrumb';
11+
import { BreadcrumbDividerState } from '@fluentui/react-breadcrumb';
12+
import { BreadcrumbItemState } from '@fluentui/react-breadcrumb';
13+
import { BreadcrumbState } from '@fluentui/react-breadcrumb';
1014
import { ButtonState } from '@fluentui/react-button';
1115
import { CheckboxState } from '@fluentui/react-checkbox';
1216
import { CompoundButtonState } from '@fluentui/react-button';
@@ -68,6 +72,18 @@ export const useSemanticAvatarStyles: (_state: unknown) => AvatarState;
6872
// @public
6973
export const useSemanticBadgeStyles: (_state: unknown) => BadgeState;
7074

75+
// @public
76+
export const useSemanticBreadcrumbButtonStyles: (_state: unknown) => BreadcrumbButtonState;
77+
78+
// @public
79+
export const useSemanticBreadcrumbDividerStyles: (_state: unknown) => BreadcrumbDividerState;
80+
81+
// @public
82+
export const useSemanticBreadcrumbItemStyles: (_state: unknown) => BreadcrumbItemState;
83+
84+
// @public
85+
export const useSemanticBreadcrumbStyles: (_state: unknown) => BreadcrumbState;
86+
7187
// @public (undocumented)
7288
export const useSemanticButtonStyles: (_state: unknown) => ButtonState;
7389

packages/react-components/semantic-style-hooks-preview/library/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"@fluentui/react-accordion": "^9.6.8",
2828
"@fluentui/react-avatar": "^9.7.6",
2929
"@fluentui/react-badge": "^9.2.54",
30+
"@fluentui/react-breadcrumb": "^9.1.6",
3031
"@fluentui/react-button": "^9.4.6",
3132
"@fluentui/react-checkbox": "^9.3.6",
3233
"@fluentui/react-dialog": "^9.12.8",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export { useSemanticBreadcrumbStyles } from './useSemanticBreadcrumbStyles.styles';
2+
export { useSemanticBreadcrumbButtonStyles } from './useSemanticBreadcrumbButtonStyles.styles';
3+
export { useSemanticBreadcrumbDividerStyles } from './useSemanticBreadcrumbDividerStyles.styles';
4+
export { useSemanticBreadcrumbItemStyles } from './useSemanticBreadcrumbItemStyles.styles';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import { makeStyles, mergeClasses } from '@griffel/react';
2+
import { breadcrumbButtonClassNames, type BreadcrumbButtonState } from '@fluentui/react-breadcrumb';
3+
import { getSlotClassNameProp_unstable } from '@fluentui/react-utilities';
4+
import { buttonClassNames } from '@fluentui/react-button';
5+
import { useSemanticButtonStyles } from '../Button/useSemanticButtonStyles.styles';
6+
import { iconFilledClassName, iconRegularClassName } from '@fluentui/react-icons';
7+
import * as semanticTokens from '@fluentui/semantic-tokens';
8+
9+
/**
10+
* CSS variable names used internally for styling in the Breadcrumb.
11+
*/
12+
const breadcrumbCSSVars = {
13+
breadcrumbIconSizeVar: '--fui-Breadcrumb--icon-size',
14+
breadcrumbIconLineHeightVar: '--fui-Breadcrumb--icon-line-height',
15+
};
16+
17+
const useIconStyles = makeStyles({
18+
base: {
19+
fontSize: `var(${breadcrumbCSSVars.breadcrumbIconSizeVar})`,
20+
height: `var(${breadcrumbCSSVars.breadcrumbIconSizeVar})`,
21+
lineHeight: `var(${breadcrumbCSSVars.breadcrumbIconLineHeightVar})`,
22+
width: `var(${breadcrumbCSSVars.breadcrumbIconSizeVar})`,
23+
marginRight: semanticTokens.gapInsideCtrlSmDefault,
24+
},
25+
small: {
26+
[breadcrumbCSSVars.breadcrumbIconSizeVar]: '12px',
27+
[breadcrumbCSSVars.breadcrumbIconLineHeightVar]: semanticTokens.textGlobalCaption1LineHeight,
28+
},
29+
medium: {
30+
[breadcrumbCSSVars.breadcrumbIconSizeVar]: semanticTokens._ctrlBreadcrumbSizeSmIcon,
31+
[breadcrumbCSSVars.breadcrumbIconLineHeightVar]: semanticTokens.textGlobalBody2LineHeight,
32+
},
33+
large: {
34+
[breadcrumbCSSVars.breadcrumbIconSizeVar]: semanticTokens.sizeCtrlIcon,
35+
[breadcrumbCSSVars.breadcrumbIconLineHeightVar]: semanticTokens.textGlobalSubtitle2LineHeight,
36+
},
37+
});
38+
39+
const defaultButtonStyles = {
40+
backgroundColor: semanticTokens.nullColor,
41+
color: semanticTokens.foregroundCtrlOnTransparentRest,
42+
cursor: 'auto',
43+
};
44+
45+
const currentIconStyles = {
46+
...defaultButtonStyles,
47+
[`& .${buttonClassNames.icon}`]: {
48+
color: 'unset',
49+
},
50+
[`& .${iconFilledClassName}`]: {
51+
display: 'none',
52+
},
53+
[`& .${iconRegularClassName}`]: {
54+
display: 'inline',
55+
},
56+
};
57+
58+
const useStyles = makeStyles({
59+
root: {
60+
minWidth: 'unset',
61+
textWrap: 'nowrap',
62+
},
63+
small: {
64+
height: '24px',
65+
fontFamily: semanticTokens.textStyleDefaultRegularFontFamily,
66+
fontSize: semanticTokens.textGlobalCaption1FontSize,
67+
fontWeight: semanticTokens.textStyleDefaultRegularWeight,
68+
lineHeight: semanticTokens.textGlobalCaption1LineHeight,
69+
padding: semanticTokens.gapInsideCtrlToLabel,
70+
},
71+
medium: {
72+
height: semanticTokens._ctrlBreadcrumbSizeDefault,
73+
fontFamily: semanticTokens.textStyleDefaultRegularFontFamily,
74+
fontSize: semanticTokens.textRampItemBodyFontSize,
75+
fontWeight: semanticTokens.textStyleDefaultRegularWeight,
76+
lineHeight: semanticTokens.textRampItemBodyLineHeight,
77+
padding: semanticTokens.gapInsideCtrlToLabel,
78+
},
79+
large: {
80+
height: semanticTokens._ctrlBreadcrumbSizeLgDefault,
81+
fontFamily: semanticTokens.textStyleDefaultRegularFontFamily,
82+
fontSize: semanticTokens.textGlobalBody2FontSize,
83+
fontWeight: semanticTokens.textStyleDefaultRegularWeight,
84+
lineHeight: semanticTokens.textGlobalBody2LineHeight,
85+
padding: semanticTokens.gapInsideCtrlLgToLabel,
86+
},
87+
current: {
88+
':hover': {
89+
...currentIconStyles,
90+
},
91+
':hover:active': {
92+
...currentIconStyles,
93+
},
94+
':disabled': {
95+
...currentIconStyles,
96+
},
97+
},
98+
currentSmall: {
99+
fontFamily: semanticTokens.textStyleDefaultRegularFontFamily,
100+
fontSize: semanticTokens.textGlobalCaption1FontSize,
101+
fontWeight: semanticTokens.textCtrlButtonWeightDefault,
102+
lineHeight: semanticTokens.textGlobalCaption1LineHeight,
103+
},
104+
currentMedium: {
105+
fontFamily: semanticTokens.textStyleDefaultRegularFontFamily,
106+
fontSize: semanticTokens.textRampItemBodyFontSize,
107+
fontWeight: semanticTokens.textCtrlButtonWeightDefault,
108+
lineHeight: semanticTokens.textRampItemBodyLineHeight,
109+
},
110+
currentLarge: {
111+
fontFamily: semanticTokens.textStyleDefaultRegularFontFamily,
112+
fontSize: semanticTokens.textRampLgItemBodyFontSize,
113+
fontWeight: semanticTokens.textCtrlButtonWeightDefault,
114+
lineHeight: semanticTokens.textRampLgItemBodyLineHeight,
115+
},
116+
});
117+
118+
/**
119+
* Apply styling to the BreadcrumbButton slots based on the state
120+
*/
121+
export const useSemanticBreadcrumbButtonStyles = (_state: unknown): BreadcrumbButtonState => {
122+
'use no memo';
123+
124+
const state = _state as BreadcrumbButtonState;
125+
126+
const styles = useStyles();
127+
const iconStyles = useIconStyles();
128+
129+
const currentSizeMap = {
130+
small: styles.currentSmall,
131+
medium: styles.currentMedium,
132+
large: styles.currentLarge,
133+
};
134+
state.root.className = mergeClasses(
135+
state.root.className,
136+
breadcrumbButtonClassNames.root,
137+
styles[state.size],
138+
styles.root,
139+
state.current && currentSizeMap[state.size],
140+
state.current && styles.current,
141+
getSlotClassNameProp_unstable(state.root),
142+
);
143+
144+
if (state.icon) {
145+
state.icon.className = mergeClasses(
146+
state.icon.className,
147+
iconStyles.base,
148+
iconStyles[state.size],
149+
getSlotClassNameProp_unstable(state.icon),
150+
);
151+
}
152+
153+
useSemanticButtonStyles(state);
154+
155+
return state;
156+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { makeStyles, makeResetStyles, mergeClasses } from '@griffel/react';
2+
import { breadcrumbDividerClassNames, type BreadcrumbDividerState } from '@fluentui/react-breadcrumb';
3+
import { getSlotClassNameProp_unstable } from '@fluentui/react-utilities';
4+
import * as semanticTokens from '@fluentui/semantic-tokens';
5+
6+
/**
7+
* Styles for the root slot
8+
*/
9+
const useStyles = makeResetStyles({
10+
display: 'flex',
11+
});
12+
13+
const useIconStyles = makeStyles({
14+
small: {
15+
fontSize: '12px',
16+
},
17+
medium: {
18+
fontSize: semanticTokens._ctrlBreadcrumbSizeSmIcon,
19+
},
20+
large: {
21+
fontSize: semanticTokens.sizeCtrlIcon,
22+
},
23+
});
24+
25+
/**
26+
* Apply styling to the BreadcrumbDivider slots based on the state
27+
*/
28+
export const useSemanticBreadcrumbDividerStyles = (_state: unknown): BreadcrumbDividerState => {
29+
'use no memo';
30+
31+
const state = _state as BreadcrumbDividerState;
32+
33+
const styles = useStyles();
34+
const iconStyles = useIconStyles();
35+
const { size = 'medium' } = state;
36+
37+
state.root.className = mergeClasses(
38+
state.root.className,
39+
breadcrumbDividerClassNames.root,
40+
styles,
41+
iconStyles[size],
42+
getSlotClassNameProp_unstable(state.root),
43+
);
44+
45+
return state;
46+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { makeResetStyles, mergeClasses } from '@griffel/react';
2+
import { breadcrumbItemClassNames, type BreadcrumbItemState } from '@fluentui/react-breadcrumb';
3+
import { getSlotClassNameProp_unstable } from '@fluentui/react-utilities';
4+
import * as semanticTokens from '@fluentui/semantic-tokens';
5+
6+
const useBreadcrumbItemResetStyles = makeResetStyles({
7+
display: 'flex',
8+
alignItems: 'center',
9+
color: semanticTokens.foregroundContentNeutralSecondary,
10+
boxSizing: 'border-box',
11+
textWrap: 'nowrap',
12+
});
13+
14+
/**
15+
* Apply styling to the BreadcrumbItem slots based on the state
16+
*/
17+
export const useSemanticBreadcrumbItemStyles = (_state: unknown): BreadcrumbItemState => {
18+
'use no memo';
19+
20+
const state = _state as BreadcrumbItemState;
21+
22+
const resetStyles = useBreadcrumbItemResetStyles();
23+
24+
state.root.className = mergeClasses(
25+
state.root.className,
26+
breadcrumbItemClassNames.root,
27+
resetStyles,
28+
getSlotClassNameProp_unstable(state.root),
29+
);
30+
31+
return state;
32+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { makeResetStyles, mergeClasses } from '@griffel/react';
2+
import { breadcrumbClassNames, type BreadcrumbState } from '@fluentui/react-breadcrumb';
3+
import { getSlotClassNameProp_unstable } from '@fluentui/react-utilities';
4+
5+
const useListClassName = makeResetStyles({
6+
listStyleType: 'none',
7+
display: 'flex',
8+
alignItems: 'center',
9+
margin: 0,
10+
padding: 0,
11+
});
12+
13+
/**
14+
* Apply styling to the Breadcrumb slots based on the state
15+
*/
16+
export const useSemanticBreadcrumbStyles = (_state: unknown): BreadcrumbState => {
17+
'use no memo';
18+
19+
const state = _state as BreadcrumbState;
20+
21+
const listBaseClassName = useListClassName();
22+
state.root.className = mergeClasses(
23+
state.root.className,
24+
breadcrumbClassNames.root,
25+
getSlotClassNameProp_unstable(state.root),
26+
);
27+
if (state.list) {
28+
state.list.className = mergeClasses(
29+
state.list.className,
30+
listBaseClassName,
31+
breadcrumbClassNames.list,
32+
getSlotClassNameProp_unstable(state.list),
33+
);
34+
}
35+
return state;
36+
};

packages/react-components/semantic-style-hooks-preview/library/src/component-styles/semanticStyleHooks.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ import { useSemanticMenuGroupHeaderStyles } from './Menu';
6262
import { useSemanticRadioStyles } from './Radio';
6363
import { useSemanticPersonaStyles } from './Persona';
6464
import { useSemanticBadgeStyles, useSemanticPresenceBadgeStyles } from './Badge';
65+
import {
66+
useSemanticBreadcrumbStyles,
67+
useSemanticBreadcrumbButtonStyles,
68+
useSemanticBreadcrumbDividerStyles,
69+
useSemanticBreadcrumbItemStyles,
70+
} from './Breadcrumb';
6571

6672
export const SEMANTIC_STYLE_HOOKS: FluentProviderCustomStyleHooks = {
6773
// Accordion styles
@@ -141,4 +147,9 @@ export const SEMANTIC_STYLE_HOOKS: FluentProviderCustomStyleHooks = {
141147
usePersonaStyles_unstable: useSemanticPersonaStyles,
142148
// Checkbox styles
143149
useCheckboxStyles_unstable: useSemanticCheckboxStyles,
150+
// Breadcrumb styles
151+
useBreadcrumbStyles_unstable: useSemanticBreadcrumbStyles,
152+
useBreadcrumbButtonStyles_unstable: useSemanticBreadcrumbButtonStyles,
153+
useBreadcrumbDividerStyles_unstable: useSemanticBreadcrumbDividerStyles,
154+
useBreadcrumbItemStyles_unstable: useSemanticBreadcrumbItemStyles,
144155
};

packages/react-components/semantic-style-hooks-preview/library/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,9 @@ export {
6666
export { useSemanticRadioStyles } from './component-styles/Radio';
6767
export { useSemanticPersonaStyles } from './component-styles/Persona';
6868
export { useSemanticCheckboxStyles } from './component-styles/Checkbox';
69+
export {
70+
useSemanticBreadcrumbStyles,
71+
useSemanticBreadcrumbButtonStyles,
72+
useSemanticBreadcrumbDividerStyles,
73+
useSemanticBreadcrumbItemStyles,
74+
} from './component-styles/Breadcrumb';

packages/semantic-tokens/etc/semantic-tokens.api.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,15 @@ export const ctrlBooleanSelectionHint = "var(--smtc-ctrl-boolean-selection-hint)
994994
// @public (undocumented)
995995
export const ctrlBooleanSelectionHintRaw = "--smtc-ctrl-boolean-selection-hint";
996996

997+
// @public
998+
export const _ctrlBreadcrumbSizeDefault = "var(--smtc-size-ctrl-default, 32px)";
999+
1000+
// @public
1001+
export const _ctrlBreadcrumbSizeLgDefault = "var(--smtc-size-ctrl-lg-default, 40px)";
1002+
1003+
// @public
1004+
export const _ctrlBreadcrumbSizeSmIcon = "var(--smtc-size-ctrl-sm-icon, 16px)";
1005+
9971006
// @public
9981007
export const _ctrlButtonGapInsideDefault = "var(--smtc-gap-inside-ctrl-default, var(--spacingHorizontalSNudge))";
9991008

0 commit comments

Comments
 (0)