Private
Public Access
1
0
Files

275 lines
11 KiB
JavaScript

'use client';
import { iconFilledClassName, iconRegularClassName } from '@fluentui/react-icons';
import { createCustomFocusIndicatorStyle } from '@fluentui/react-tabster';
import { tokens } from '@fluentui/react-theme';
import { shorthands, mergeClasses, makeStyles } from '@griffel/react';
import { useButtonStyles_unstable } from '../Button/useButtonStyles.styles';
export const toggleButtonClassNames = {
root: 'fui-ToggleButton',
icon: 'fui-ToggleButton__icon'
};
const useRootCheckedStyles = makeStyles({
// Base styles
base: {
backgroundColor: tokens.colorNeutralBackground1Selected,
...shorthands.borderColor(tokens.colorNeutralStroke1),
color: tokens.colorNeutralForeground1Selected,
...shorthands.borderWidth(tokens.strokeWidthThin),
[`& .${iconFilledClassName}`]: {
display: 'inline'
},
[`& .${iconRegularClassName}`]: {
display: 'none'
},
':hover': {
backgroundColor: tokens.colorNeutralBackground1Hover,
...shorthands.borderColor(tokens.colorNeutralStroke1Hover),
color: tokens.colorNeutralForeground1Hover
},
':hover:active,:active:focus-visible': {
backgroundColor: tokens.colorNeutralBackground1Pressed,
...shorthands.borderColor(tokens.colorNeutralStroke1Pressed),
color: tokens.colorNeutralForeground1Pressed
}
},
// High contrast styles
highContrast: {
'@media (forced-colors: active)': {
backgroundColor: 'Highlight',
...shorthands.borderColor('Highlight'),
color: 'HighlightText',
forcedColorAdjust: 'none',
':hover': {
backgroundColor: 'HighlightText',
...shorthands.borderColor('Highlight'),
color: 'Highlight'
},
':hover:active,:active:focus-visible': {
backgroundColor: 'HighlightText',
...shorthands.borderColor('Highlight'),
color: 'Highlight'
},
':focus': {
border: '1px solid HighlightText',
outlineColor: 'Highlight'
}
}
},
// Appearance variations
outline: {
backgroundColor: tokens.colorTransparentBackgroundSelected,
...shorthands.borderColor(tokens.colorNeutralStroke1),
...shorthands.borderWidth(tokens.strokeWidthThicker),
':hover': {
backgroundColor: tokens.colorTransparentBackgroundHover
},
':hover:active,:active:focus-visible': {
backgroundColor: tokens.colorTransparentBackgroundPressed
},
...createCustomFocusIndicatorStyle({
...shorthands.borderColor(tokens.colorNeutralStroke1)
})
},
primary: {
backgroundColor: tokens.colorBrandBackgroundSelected,
...shorthands.borderColor('transparent'),
color: tokens.colorNeutralForegroundOnBrand,
':hover': {
backgroundColor: tokens.colorBrandBackgroundHover,
...shorthands.borderColor('transparent'),
color: tokens.colorNeutralForegroundOnBrand
},
':hover:active,:active:focus-visible': {
backgroundColor: tokens.colorBrandBackgroundPressed,
...shorthands.borderColor('transparent'),
color: tokens.colorNeutralForegroundOnBrand
}
},
secondary: {
},
subtle: {
backgroundColor: tokens.colorSubtleBackgroundSelected,
...shorthands.borderColor('transparent'),
color: tokens.colorNeutralForeground2Selected,
':hover': {
backgroundColor: tokens.colorSubtleBackgroundHover,
...shorthands.borderColor('transparent'),
color: tokens.colorNeutralForeground2Hover
},
':hover:active,:active:focus-visible': {
backgroundColor: tokens.colorSubtleBackgroundPressed,
...shorthands.borderColor('transparent'),
color: tokens.colorNeutralForeground2Pressed
}
},
transparent: {
backgroundColor: tokens.colorTransparentBackgroundSelected,
...shorthands.borderColor('transparent'),
color: tokens.colorNeutralForeground2BrandSelected,
':hover': {
backgroundColor: tokens.colorTransparentBackgroundHover,
...shorthands.borderColor('transparent'),
color: tokens.colorNeutralForeground2BrandHover
},
':hover:active,:active:focus-visible': {
backgroundColor: tokens.colorTransparentBackgroundPressed,
...shorthands.borderColor('transparent'),
color: tokens.colorNeutralForeground2BrandPressed
}
}
});
const useCheckedAccessibleStyles = makeStyles({
// Base styles
base: {
backgroundColor: tokens.colorBrandBackground,
...shorthands.borderColor('transparent'),
color: tokens.colorNeutralForegroundOnBrand,
':hover': {
backgroundColor: tokens.colorBrandBackgroundHover,
...shorthands.borderColor('transparent'),
color: tokens.colorNeutralForegroundOnBrand
},
':hover:active,:active:focus-visible': {
backgroundColor: tokens.colorBrandBackgroundPressed,
...shorthands.borderColor('transparent'),
color: tokens.colorNeutralForegroundOnBrand
}
},
// Appearance variations
outline: {
// There's no longer a reason to thicken the outline variant's border
...shorthands.borderWidth(tokens.strokeWidthThin)
},
primary: {
// primary has an inner stroke for the checked style
outline: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralForegroundOnBrand}`,
outlineOffset: `calc(${tokens.strokeWidthThicker} * -1)`,
// need to not have the default focus style that removes the outline
...createCustomFocusIndicatorStyle({
outline: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralForegroundOnBrand}`,
outlineOffset: `calc(${tokens.strokeWidthThickest} * -1)`
})
},
subtle: {
// override subtle-appearance-specific icon color on hover
':hover': {
[`& .${toggleButtonClassNames.icon}`]: {
color: tokens.colorNeutralForegroundOnBrand
}
}
},
transparent: {
},
secondary: {
}
});
const useRootDisabledStyles = makeStyles({
// Base styles
base: {
backgroundColor: tokens.colorNeutralBackgroundDisabled,
...shorthands.borderColor(tokens.colorNeutralStrokeDisabled),
color: tokens.colorNeutralForegroundDisabled,
':hover': {
backgroundColor: tokens.colorNeutralBackgroundDisabled,
...shorthands.borderColor(tokens.colorNeutralStrokeDisabled),
color: tokens.colorNeutralForegroundDisabled
},
':hover:active,:active:focus-visible': {
backgroundColor: tokens.colorNeutralBackgroundDisabled,
...shorthands.borderColor(tokens.colorNeutralStrokeDisabled),
color: tokens.colorNeutralForegroundDisabled
}
},
// Appearance variations
outline: {
},
primary: {
...shorthands.borderColor('transparent'),
':hover': {
...shorthands.borderColor('transparent')
},
':hover:active,:active:focus-visible': {
...shorthands.borderColor('transparent')
}
},
secondary: {
},
subtle: {
backgroundColor: tokens.colorTransparentBackground,
...shorthands.borderColor('transparent'),
':hover': {
backgroundColor: tokens.colorTransparentBackgroundHover,
...shorthands.borderColor('transparent')
},
':hover:active,:active:focus-visible': {
backgroundColor: tokens.colorTransparentBackgroundPressed,
...shorthands.borderColor('transparent')
}
},
transparent: {
backgroundColor: tokens.colorTransparentBackground,
...shorthands.borderColor('transparent'),
':hover': {
backgroundColor: tokens.colorTransparentBackgroundHover,
...shorthands.borderColor('transparent')
},
':hover:active,:active:focus-visible': {
backgroundColor: tokens.colorTransparentBackgroundPressed,
...shorthands.borderColor('transparent')
}
}
});
const useIconCheckedStyles = makeStyles({
// Appearance variations with isAccessible=false
subtleOrTransparent: {
color: tokens.colorNeutralForeground2BrandSelected
},
// High contrast styles
highContrast: {
'@media (forced-colors: active)': {
forcedColorAdjust: 'auto'
}
}
});
const usePrimaryHighContrastStyles = makeStyles({
// Do not use primary variant high contrast styles for toggle buttons
// otherwise there isn't enough difference between on/off states
base: {
'@media (forced-colors: active)': {
backgroundColor: 'ButtonFace',
...shorthands.borderColor('ButtonBorder'),
color: 'ButtonText',
forcedColorAdjust: 'auto'
}
},
disabled: {
'@media (forced-colors: active)': {
...shorthands.borderColor('GrayText'),
color: 'GrayText',
':focus': {
...shorthands.borderColor('GrayText')
}
}
}
});
export const useToggleButtonStyles_unstable = (state)=>{
'use no memo';
const rootCheckedStyles = useRootCheckedStyles();
const accessibleCheckedStyles = useCheckedAccessibleStyles();
const rootDisabledStyles = useRootDisabledStyles();
const iconCheckedStyles = useIconCheckedStyles();
const primaryHighContrastStyles = usePrimaryHighContrastStyles();
const { appearance, checked, disabled, disabledFocusable, isAccessible } = state;
state.root.className = mergeClasses(toggleButtonClassNames.root, // Primary high contrast styles
appearance === 'primary' && primaryHighContrastStyles.base, appearance === 'primary' && (disabled || disabledFocusable) && primaryHighContrastStyles.disabled, // Checked styles
checked && rootCheckedStyles.base, checked && rootCheckedStyles.highContrast, appearance && checked && rootCheckedStyles[appearance], // Opt-in accessible checked styles
isAccessible && checked && accessibleCheckedStyles.base, isAccessible && appearance && checked && accessibleCheckedStyles[appearance], // Disabled styles
(disabled || disabledFocusable) && rootDisabledStyles.base, appearance && (disabled || disabledFocusable) && rootDisabledStyles[appearance], // User provided class name
state.root.className);
if (state.icon) {
state.icon.className = mergeClasses(toggleButtonClassNames.icon, checked && !isAccessible && (appearance === 'subtle' || appearance === 'transparent') && iconCheckedStyles.subtleOrTransparent, iconCheckedStyles.highContrast, state.icon.className);
}
useButtonStyles_unstable(state);
return state;
};