Private
Public Access
1
0
Files
power-apps-codeapps-blog-part2/node_modules/@fluentui/react-card/lib/components/Card/useCardStyles.styles.raw.js

405 lines
15 KiB
JavaScript

'use client';
import * as React from 'react';
import { shorthands, makeStyles, mergeClasses, makeResetStyles } from '@griffel/react';
import { tokens } from '@fluentui/react-theme';
import { textClassNames } from '@fluentui/react-text';
import { createFocusOutlineStyle } from '@fluentui/react-tabster';
import { cardPreviewClassNames } from '../CardPreview/useCardPreviewStyles.styles';
import { cardHeaderClassNames } from '../CardHeader/useCardHeaderStyles.styles';
import { cardFooterClassNames } from '../CardFooter/useCardFooterStyles.styles';
/**
* Static CSS class names used internally for the component slots.
*/ export const cardClassNames = {
root: 'fui-Card',
floatingAction: 'fui-Card__floatingAction',
checkbox: 'fui-Card__checkbox'
};
/**
* CSS variable names used internally for uniform styling in Card.
*/ export const cardCSSVars = {
cardSizeVar: '--fui-Card--size',
cardBorderRadiusVar: '--fui-Card--border-radius'
};
const focusOutlineStyle = {
outlineRadius: `var(${cardCSSVars.cardBorderRadiusVar})`,
outlineWidth: tokens.strokeWidthThick,
outlineOffset: '-2px'
};
const useCardResetStyles = makeResetStyles({
overflow: 'hidden',
borderRadius: `var(${cardCSSVars.cardBorderRadiusVar})`,
padding: `var(${cardCSSVars.cardSizeVar})`,
gap: `var(${cardCSSVars.cardSizeVar})`,
display: 'flex',
position: 'relative',
boxSizing: 'border-box',
color: tokens.colorNeutralForeground1,
// Border setting using after pseudo element to allow CardPreview to render behind it.
'::after': {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
content: '""',
pointerEvents: 'none',
...shorthands.borderStyle('solid'),
...shorthands.borderWidth(tokens.strokeWidthThin),
borderRadius: `var(${cardCSSVars.cardBorderRadiusVar})`
},
// Prevents CardHeader and CardFooter from shrinking.
[`> .${cardHeaderClassNames.root}, > .${cardFooterClassNames.root}`]: {
flexShrink: 0
}
});
const disabledStyles = {
cursor: 'not-allowed',
userSelect: 'none',
color: tokens.colorNeutralForegroundDisabled,
backgroundColor: tokens.colorNeutralBackgroundDisabled,
boxShadow: tokens.shadow2,
...shorthands.borderColor(tokens.colorNeutralStrokeDisabled),
'::before': {
content: '""',
position: 'absolute',
inset: 0,
zIndex: `calc(${tokens.zIndexContent} + 1)`
},
'::after': {
...shorthands.borderColor(tokens.colorNeutralStrokeDisabled)
}
};
const useCardStyles = makeStyles({
focused: {
...createFocusOutlineStyle({
style: focusOutlineStyle,
selector: 'focus'
})
},
selectableFocused: createFocusOutlineStyle({
style: focusOutlineStyle,
selector: 'focus-within'
}),
orientationHorizontal: {
flexDirection: 'row',
alignItems: 'center',
// Remove vertical padding to keep CardPreview content flush with Card's borders.
[`> .${cardPreviewClassNames.root}`]: {
marginTop: `calc(var(${cardCSSVars.cardSizeVar}) * -1)`,
marginBottom: `calc(var(${cardCSSVars.cardSizeVar}) * -1)`
},
// Due to Tabster's "Groupper" focus functionality, hidden elements are injected before and after Card's content.
// As such, the code below targets a CardPreview, when it's the first element.
// Since this is on horizontal cards, the left padding is removed to keep the content flush with the border.
[`> :not([aria-hidden="true"]).${cardPreviewClassNames.root}:first-of-type`]: {
marginLeft: `calc(var(${cardCSSVars.cardSizeVar}) * -1)`
},
// Due to Tabster's "Groupper" focus functionality, hidden elements are injected before and after Card's content.
// As such, the code below targets a CardPreview, when it's the last element.
// Since this is on horizontal cards, the right padding is removed to keep the content flush with the border.
[`> :not([aria-hidden="true"]).${cardPreviewClassNames.root}:last-of-type`]: {
marginRight: `calc(var(${cardCSSVars.cardSizeVar}) * -1)`
},
// If the last child is a CardHeader or CardFooter, allow it to grow to fill the available space.
[`> .${cardHeaderClassNames.root}:last-of-type, > .${cardFooterClassNames.root}:last-of-type`]: {
flexGrow: 1
}
},
orientationVertical: {
flexDirection: 'column',
// Remove lateral padding to keep CardPreview content flush with Card's borders.
[`> .${cardPreviewClassNames.root}`]: {
marginLeft: `calc(var(${cardCSSVars.cardSizeVar}) * -1)`,
marginRight: `calc(var(${cardCSSVars.cardSizeVar}) * -1)`
},
// Due to Tabster's "Groupper" focus functionality, hidden elements are injected before and after Card's content.
// As such, the code below targets a CardPreview, when it's the first element.
// Since this is on vertical cards, the top padding is removed to keep the content flush with the border.
[`> :not([aria-hidden="true"]).${cardPreviewClassNames.root}:first-of-type`]: {
marginTop: `calc(var(${cardCSSVars.cardSizeVar}) * -1)`
},
[`> .${cardClassNames.floatingAction} + .${cardPreviewClassNames.root}`]: {
marginTop: `calc(var(${cardCSSVars.cardSizeVar}) * -1)`
},
// Due to Tabster's "Groupper" focus functionality, hidden elements are injected before and after Card's content.
// As such, the code below targets a CardPreview, when it's the first element.
// Since this is on vertical cards, the bottom padding is removed to keep the content flush with the border.
[`> :not([aria-hidden="true"]).${cardPreviewClassNames.root}:last-of-type`]: {
marginBottom: `calc(var(${cardCSSVars.cardSizeVar}) * -1)`
}
},
sizeSmall: {
[cardCSSVars.cardSizeVar]: '8px',
[cardCSSVars.cardBorderRadiusVar]: tokens.borderRadiusSmall
},
sizeMedium: {
[cardCSSVars.cardSizeVar]: '12px',
[cardCSSVars.cardBorderRadiusVar]: tokens.borderRadiusMedium
},
sizeLarge: {
[cardCSSVars.cardSizeVar]: '16px',
[cardCSSVars.cardBorderRadiusVar]: tokens.borderRadiusLarge
},
interactive: {
[`& .${textClassNames.root}`]: {
color: 'currentColor'
}
},
filled: {
backgroundColor: tokens.colorNeutralBackground1,
boxShadow: tokens.shadow4,
'::after': {
...shorthands.borderColor(tokens.colorTransparentStroke)
}
},
filledInteractive: {
cursor: 'pointer',
backgroundColor: tokens.colorNeutralBackground1,
boxShadow: tokens.shadow4,
'::after': {
...shorthands.borderColor(tokens.colorTransparentStroke)
},
':hover': {
color: tokens.colorNeutralForeground1Hover,
backgroundColor: tokens.colorNeutralBackground1Hover,
boxShadow: tokens.shadow8
},
':active': {
backgroundColor: tokens.colorNeutralBackground1Pressed
}
},
filledInteractiveSelected: {
backgroundColor: tokens.colorNeutralBackground1Selected,
'::after': {
...shorthands.borderColor(tokens.colorNeutralStroke1Selected)
},
':hover': {
color: tokens.colorNeutralForeground1Selected,
backgroundColor: tokens.colorNeutralBackground1Selected
}
},
filledAlternative: {
backgroundColor: tokens.colorNeutralBackground2,
boxShadow: tokens.shadow4,
'::after': {
...shorthands.borderColor(tokens.colorTransparentStroke)
}
},
filledAlternativeInteractive: {
cursor: 'pointer',
backgroundColor: tokens.colorNeutralBackground2,
boxShadow: tokens.shadow4,
'::after': {
...shorthands.borderColor(tokens.colorTransparentStroke)
},
':hover': {
color: tokens.colorNeutralForeground2Hover,
backgroundColor: tokens.colorNeutralBackground2Hover,
boxShadow: tokens.shadow8
},
':active': {
backgroundColor: tokens.colorNeutralBackground2Pressed
}
},
filledAlternativeInteractiveSelected: {
backgroundColor: tokens.colorNeutralBackground2Selected,
'::after': {
...shorthands.borderColor(tokens.colorNeutralStroke1Selected)
},
':hover': {
color: tokens.colorNeutralForeground2Selected,
backgroundColor: tokens.colorNeutralBackground2Selected
}
},
outline: {
backgroundColor: tokens.colorTransparentBackground,
boxShadow: 'none',
'::after': {
...shorthands.borderColor(tokens.colorNeutralStroke1)
}
},
outlineInteractive: {
cursor: 'pointer',
backgroundColor: tokens.colorTransparentBackground,
boxShadow: 'none',
'::after': {
...shorthands.borderColor(tokens.colorNeutralStroke1)
},
':hover': {
color: tokens.colorNeutralForeground1Hover,
backgroundColor: tokens.colorTransparentBackgroundHover,
'::after': {
...shorthands.borderColor(tokens.colorNeutralStroke1Hover)
}
},
':active': {
backgroundColor: tokens.colorTransparentBackgroundPressed,
'::after': {
...shorthands.borderColor(tokens.colorNeutralStroke1Pressed)
}
}
},
outlineInteractiveSelected: {
backgroundColor: tokens.colorTransparentBackgroundSelected,
'::after': {
...shorthands.borderColor(tokens.colorNeutralStroke1Selected)
},
':hover': {
color: tokens.colorNeutralForeground1Selected,
backgroundColor: tokens.colorTransparentBackgroundSelected
}
},
outlineDisabled: {
backgroundColor: tokens.colorTransparentBackground,
boxShadow: 'none',
...shorthands.borderColor(tokens.colorNeutralStrokeDisabled),
'&:hover, &:active': {
backgroundColor: tokens.colorTransparentBackground,
boxShadow: 'none'
},
'::after': {
...shorthands.borderColor(tokens.colorNeutralStrokeDisabled)
}
},
subtle: {
backgroundColor: tokens.colorSubtleBackground,
boxShadow: 'none',
'::after': {
...shorthands.borderColor(tokens.colorTransparentStroke)
}
},
subtleInteractive: {
cursor: 'pointer',
backgroundColor: tokens.colorSubtleBackground,
boxShadow: 'none',
'::after': {
...shorthands.borderColor(tokens.colorTransparentStroke)
},
':hover': {
color: tokens.colorNeutralForeground1Hover,
backgroundColor: tokens.colorSubtleBackgroundHover
},
':active': {
backgroundColor: tokens.colorSubtleBackgroundPressed
}
},
subtleInteractiveSelected: {
backgroundColor: tokens.colorSubtleBackgroundSelected,
'::after': {
...shorthands.borderColor(tokens.colorNeutralStroke1Selected)
},
':hover': {
color: tokens.colorNeutralForeground1Selected,
backgroundColor: tokens.colorSubtleBackgroundSelected
}
},
highContrastSelected: {
'@media (forced-colors: active)': {
forcedColorAdjust: 'none',
backgroundColor: 'Highlight',
color: 'HighlightText',
[`& .${cardPreviewClassNames.root}, & .${cardFooterClassNames.root}`]: {
forcedColorAdjust: 'auto'
},
'::after': {
...shorthands.borderColor('Highlight')
}
}
},
highContrastInteractive: {
'@media (forced-colors: active)': {
':hover, :active': {
forcedColorAdjust: 'none',
backgroundColor: 'Highlight',
color: 'HighlightText',
[`& .${cardPreviewClassNames.root}, & .${cardFooterClassNames.root}`]: {
forcedColorAdjust: 'auto'
}
},
'::after': {
...shorthands.borderColor('Highlight')
}
}
},
select: {
position: 'absolute',
top: '4px',
right: '4px',
zIndex: tokens.zIndexContent
},
hiddenCheckbox: {
overflow: 'hidden',
width: '1px',
height: '1px',
position: 'absolute',
clip: 'rect(0 0 0 0)',
clipPath: 'inset(50%)',
whiteSpace: 'nowrap'
},
disabled: {
...disabledStyles,
'&:hover, &:active': disabledStyles
}
});
/**
* Apply styling to the Card slots based on the state.
*/ export const useCardStyles_unstable = (state)=>{
'use no memo';
const resetStyles = useCardResetStyles();
const styles = useCardStyles();
const orientationMap = {
horizontal: styles.orientationHorizontal,
vertical: styles.orientationVertical
};
const sizeMap = {
small: styles.sizeSmall,
medium: styles.sizeMedium,
large: styles.sizeLarge
};
const appearanceMap = {
filled: styles.filled,
'filled-alternative': styles.filledAlternative,
outline: styles.outline,
subtle: styles.subtle
};
const selectedMap = {
filled: styles.filledInteractiveSelected,
'filled-alternative': styles.filledAlternativeInteractiveSelected,
outline: styles.outlineInteractiveSelected,
subtle: styles.subtleInteractiveSelected
};
const interactiveMap = {
filled: styles.filledInteractive,
'filled-alternative': styles.filledAlternativeInteractive,
outline: styles.outlineInteractive,
subtle: styles.subtleInteractive
};
const isSelectableOrInteractive = !state.disabled && (state.interactive || state.selectable);
const focusedClassName = React.useMemo(()=>{
if (state.disabled) {
return '';
}
if (state.selectable) {
if (state.selectFocused) {
return styles.selectableFocused;
}
return '';
}
return styles.focused;
}, [
state.disabled,
state.selectFocused,
state.selectable,
styles.focused,
styles.selectableFocused
]);
state.root.className = mergeClasses(cardClassNames.root, resetStyles, orientationMap[state.orientation], sizeMap[state.size], appearanceMap[state.appearance], isSelectableOrInteractive && styles.interactive, isSelectableOrInteractive && interactiveMap[state.appearance], state.selected && selectedMap[state.appearance], focusedClassName, isSelectableOrInteractive && styles.highContrastInteractive, state.selected && styles.highContrastSelected, state.disabled && styles.disabled, state.disabled && state.appearance === 'outline' && styles.outlineDisabled, state.root.className);
if (state.floatingAction) {
state.floatingAction.className = mergeClasses(cardClassNames.floatingAction, styles.select, state.floatingAction.className);
}
if (state.checkbox) {
state.checkbox.className = mergeClasses(cardClassNames.checkbox, styles.hiddenCheckbox, state.checkbox.className);
}
return state;
};