160 lines
5.8 KiB
JavaScript
160 lines
5.8 KiB
JavaScript
'use client';
|
|
import { makeStyles, mergeClasses } from '@griffel/react';
|
|
import { createCustomFocusIndicatorStyle } from '@fluentui/react-tabster';
|
|
import { tokens } from '@fluentui/react-theme';
|
|
export const splitButtonClassNames = {
|
|
root: 'fui-SplitButton',
|
|
menuButton: 'fui-SplitButton__menuButton',
|
|
primaryActionButton: 'fui-SplitButton__primaryActionButton'
|
|
};
|
|
// WCAG minimum target size for pointer targets that are immediately adjacent to other targets:
|
|
// https://w3c.github.io/wcag/guidelines/22/#target-size-minimum
|
|
const MIN_TARGET_SIZE = '24px';
|
|
const useFocusStyles = makeStyles({
|
|
primaryActionButton: createCustomFocusIndicatorStyle({
|
|
borderTopRightRadius: 0,
|
|
borderBottomRightRadius: 0
|
|
}),
|
|
menuButton: createCustomFocusIndicatorStyle({
|
|
borderLeftWidth: 0,
|
|
borderTopLeftRadius: 0,
|
|
borderBottomLeftRadius: 0
|
|
})
|
|
});
|
|
const useRootStyles = makeStyles({
|
|
// Base styles
|
|
base: {
|
|
display: 'inline-flex',
|
|
justifyContent: 'stretch',
|
|
position: 'relative',
|
|
verticalAlign: 'middle',
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderTopRightRadius: 0,
|
|
borderBottomRightRadius: 0
|
|
},
|
|
[`& .${splitButtonClassNames.menuButton}`]: {
|
|
borderLeftWidth: 0,
|
|
borderTopLeftRadius: 0,
|
|
borderBottomLeftRadius: 0,
|
|
minWidth: MIN_TARGET_SIZE
|
|
}
|
|
},
|
|
// Appearance variations
|
|
outline: {
|
|
},
|
|
primary: {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: tokens.colorNeutralStrokeOnBrand
|
|
},
|
|
':hover': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: tokens.colorNeutralStrokeOnBrand
|
|
}
|
|
},
|
|
':hover:active,:active:focus-visible': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: tokens.colorNeutralStrokeOnBrand
|
|
}
|
|
},
|
|
'@media (forced-colors: active)': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: 'HighlightText'
|
|
},
|
|
':hover': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: 'Highlight'
|
|
}
|
|
},
|
|
':hover:active,:active:focus-visible': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: 'Highlight'
|
|
}
|
|
}
|
|
}
|
|
},
|
|
secondary: {
|
|
},
|
|
subtle: {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: tokens.colorTransparentBackground
|
|
},
|
|
':hover': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: tokens.colorTransparentBackgroundHover
|
|
}
|
|
},
|
|
':hover:active,:active:focus-visible': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: tokens.colorTransparentBackgroundPressed
|
|
}
|
|
}
|
|
},
|
|
transparent: {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: tokens.colorTransparentBackground
|
|
},
|
|
':hover': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: tokens.colorTransparentBackgroundHover
|
|
}
|
|
},
|
|
':hover:active,:active:focus-visible': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: tokens.colorTransparentBackgroundPressed
|
|
}
|
|
}
|
|
},
|
|
// Shape variations
|
|
circular: {},
|
|
rounded: {},
|
|
square: {},
|
|
// Disabled styles
|
|
disabled: {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: tokens.colorNeutralStrokeDisabled
|
|
},
|
|
':hover': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: tokens.colorNeutralStrokeDisabled
|
|
}
|
|
},
|
|
':hover:active,:active:focus-visible': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: tokens.colorNeutralStrokeDisabled
|
|
}
|
|
}
|
|
},
|
|
// Disabled high contrast styles
|
|
disabledHighContrast: {
|
|
'@media (forced-colors: active)': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: 'GrayText'
|
|
},
|
|
':hover': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: 'GrayText'
|
|
}
|
|
},
|
|
':hover:active,:active:focus-visible': {
|
|
[`& .${splitButtonClassNames.primaryActionButton}`]: {
|
|
borderRightColor: 'GrayText'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
export const useSplitButtonStyles_unstable = (state)=>{
|
|
'use no memo';
|
|
const rootStyles = useRootStyles();
|
|
const focusStyles = useFocusStyles();
|
|
const { appearance, disabled, disabledFocusable } = state;
|
|
state.root.className = mergeClasses(splitButtonClassNames.root, rootStyles.base, appearance && rootStyles[appearance], (disabled || disabledFocusable) && rootStyles.disabled, (disabled || disabledFocusable) && rootStyles.disabledHighContrast, state.root.className);
|
|
if (state.menuButton) {
|
|
state.menuButton.className = mergeClasses(splitButtonClassNames.menuButton, focusStyles.menuButton, state.menuButton.className);
|
|
}
|
|
if (state.primaryActionButton) {
|
|
state.primaryActionButton.className = mergeClasses(splitButtonClassNames.primaryActionButton, focusStyles.primaryActionButton, state.primaryActionButton.className);
|
|
}
|
|
return state;
|
|
};
|