71 lines
2.8 KiB
JavaScript
71 lines
2.8 KiB
JavaScript
|
import { tokens } from '@fluentui/react-theme';
|
||
|
import { shorthands } from '@griffel/react';
|
||
|
import { createCustomFocusIndicatorStyle } from './createCustomFocusIndicatorStyle';
|
||
|
import { defaultOptions } from './constants';
|
||
|
/**
|
||
|
* Get the position of the focus outline
|
||
|
*
|
||
|
* @param options - Configures the style of the focus outline
|
||
|
* @param position - The position of the focus outline
|
||
|
* @returns CSS value for the position of the focus outline
|
||
|
*/ function getOutlinePosition({ outlineWidth, outlineOffset }, position) {
|
||
|
const offsetValue = (outlineOffset === null || outlineOffset === void 0 ? void 0 : outlineOffset[position]) || outlineOffset;
|
||
|
if (!outlineOffset) {
|
||
|
return `calc(${outlineWidth} * -1)`;
|
||
|
}
|
||
|
return `calc(0px - ${outlineWidth} - ${offsetValue})`;
|
||
|
}
|
||
|
/**
|
||
|
* NOTE: the element with the focus outline needs to have `position: relative` so that the
|
||
|
* pseudo element can be properly positioned.
|
||
|
*
|
||
|
* @param options - Configures the style of the focus outline
|
||
|
* @returns focus outline styles object
|
||
|
*/ const getFocusOutlineStyles = (options)=>{
|
||
|
const { outlineRadius, outlineColor, outlineWidth } = options;
|
||
|
return {
|
||
|
...shorthands.borderColor('transparent'),
|
||
|
'@media (forced-colors: active)': {
|
||
|
'::after': {
|
||
|
...shorthands.borderColor('Highlight')
|
||
|
}
|
||
|
},
|
||
|
'::after': {
|
||
|
content: '""',
|
||
|
position: 'absolute',
|
||
|
pointerEvents: 'none',
|
||
|
zIndex: 1,
|
||
|
border: `${outlineWidth} solid ${outlineColor}`,
|
||
|
borderRadius: outlineRadius,
|
||
|
top: getOutlinePosition(options, 'top'),
|
||
|
right: getOutlinePosition(options, 'right'),
|
||
|
bottom: getOutlinePosition(options, 'bottom'),
|
||
|
left: getOutlinePosition(options, 'left')
|
||
|
}
|
||
|
};
|
||
|
};
|
||
|
/**
|
||
|
* NOTE: The element with the focus outline needs to have `position: relative` so that the
|
||
|
* pseudo element can be properly positioned.
|
||
|
*
|
||
|
* @param options - Configure the style of the focus outline
|
||
|
* @returns focus outline styles object for @see makeStyles
|
||
|
*/ export const createFocusOutlineStyle = ({ enableOutline = false, selector = defaultOptions.selector, customizeSelector, style = defaultOptions.style } = defaultOptions)=>({
|
||
|
':focus': {
|
||
|
outlineStyle: enableOutline ? undefined : 'none'
|
||
|
},
|
||
|
':focus-visible': {
|
||
|
outlineStyle: enableOutline ? undefined : 'none'
|
||
|
},
|
||
|
...createCustomFocusIndicatorStyle(getFocusOutlineStyles({
|
||
|
outlineColor: tokens.colorStrokeFocus2,
|
||
|
outlineRadius: tokens.borderRadiusMedium,
|
||
|
// FIXME: tokens.strokeWidthThick causes some weird bugs
|
||
|
outlineWidth: '2px',
|
||
|
...style
|
||
|
}), {
|
||
|
selector,
|
||
|
customizeSelector
|
||
|
})
|
||
|
});
|