Private
Public Access
1
0

feat: Fluent UI Outlook Lite + connections mockup

This commit is contained in:
2026-04-14 18:52:25 +00:00
parent 1199eff6c3
commit dfa4010406
34820 changed files with 1003813 additions and 205 deletions

View File

@@ -0,0 +1,15 @@
'use client';
import * as React from 'react';
import { useOption_unstable } from './useOption';
import { renderOption_unstable } from './renderOption';
import { useOptionStyles_unstable } from './useOptionStyles.styles';
import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';
/**
* Option component: a styled child option of a Combobox
*/ export const Option = /*#__PURE__*/ React.forwardRef((props, ref)=>{
const state = useOption_unstable(props, ref);
useOptionStyles_unstable(state);
useCustomStyleHook_unstable('useOptionStyles_unstable')(state);
return renderOption_unstable(state);
});
Option.displayName = 'Option';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Option/Option.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useOption_unstable } from './useOption';\nimport { renderOption_unstable } from './renderOption';\nimport { useOptionStyles_unstable } from './useOptionStyles.styles';\nimport type { OptionProps } from './Option.types';\nimport type { ForwardRefComponent } from '@fluentui/react-utilities';\nimport { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';\n\n/**\n * Option component: a styled child option of a Combobox\n */\nexport const Option: ForwardRefComponent<OptionProps> = React.forwardRef((props, ref) => {\n const state = useOption_unstable(props, ref);\n\n useOptionStyles_unstable(state);\n\n useCustomStyleHook_unstable('useOptionStyles_unstable')(state);\n\n return renderOption_unstable(state);\n});\n\nOption.displayName = 'Option';\n"],"names":["React","useOption_unstable","renderOption_unstable","useOptionStyles_unstable","useCustomStyleHook_unstable","Option","forwardRef","props","ref","state","displayName"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,kBAAkB,QAAQ,cAAc;AACjD,SAASC,qBAAqB,QAAQ,iBAAiB;AACvD,SAASC,wBAAwB,QAAQ,2BAA2B;AAGpE,SAASC,2BAA2B,QAAQ,kCAAkC;AAE9E;;CAEC,GACD,OAAO,MAAMC,uBAA2CL,MAAMM,UAAU,CAAC,CAACC,OAAOC;IAC/E,MAAMC,QAAQR,mBAAmBM,OAAOC;IAExCL,yBAAyBM;IAEzBL,4BAA4B,4BAA4BK;IAExD,OAAOP,sBAAsBO;AAC/B,GAAG;AAEHJ,OAAOK,WAAW,GAAG"}

View File

@@ -0,0 +1 @@
import * as React from 'react';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Option/Option.types.ts"],"sourcesContent":["import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nexport type OptionSlots = {\n /** The root option slot, with role=\"option\" */\n root: NonNullable<Slot<'div'>>;\n\n /** The check icon that is visible for selected options */\n checkIcon: Slot<'span'>;\n};\n\n/**\n * Option Props\n */\nexport type OptionProps = ComponentProps<Partial<OptionSlots>> & {\n /**\n * Sets an option to the `disabled` state.\n * Disabled options cannot be selected, but are still keyboard navigable\n */\n disabled?: boolean;\n\n /**\n * Defines a unique identifier for the option.\n * Use this to control selectedOptions, or to get the option value in the onOptionSelect callback.\n * Defaults to `text` if not provided.\n */\n value?: string;\n} & (\n | {\n /**\n * An optional override the string value of the Option's display text,\n * defaulting to the Option's child content.\n * This is used as the Dropdown button's or Combobox input's value when the option is selected,\n * and as the comparison for type-to-find keyboard functionality.\n */\n text?: string;\n children: string;\n }\n | {\n /**\n * The string value of the Option's display text when the Option's children are not a string.\n * This is used as the Dropdown button's or Combobox input's value when the option is selected,\n * and as the comparison for type-to-find keyboard functionality.\n */\n text: string;\n children?: React.ReactNode;\n }\n );\n\n/**\n * State used in rendering Option\n */\nexport type OptionState = ComponentState<OptionSlots> &\n Pick<OptionProps, 'disabled'> & {\n /**\n * @deprecated - no longer used internally\n */\n active: boolean;\n\n /**\n * @deprecated - no longer used internally\n */\n focusVisible: boolean;\n\n /** If true, the option is part of a multiselect combobox or listbox */\n multiselect?: boolean;\n\n /** If true, the option is selected */\n selected: boolean;\n };\n"],"names":["React"],"mappings":"AACA,YAAYA,WAAW,QAAQ"}

View File

@@ -0,0 +1,4 @@
export { Option } from './Option';
export { renderOption_unstable } from './renderOption';
export { useOption_unstable, useOptionBase_unstable } from './useOption';
export { optionClassNames, useOptionStyles_unstable } from './useOptionStyles.styles';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Option/index.ts"],"sourcesContent":["export { Option } from './Option';\nexport type { OptionProps, OptionSlots, OptionState } from './Option.types';\nexport { renderOption_unstable } from './renderOption';\nexport { useOption_unstable, useOptionBase_unstable } from './useOption';\nexport { optionClassNames, useOptionStyles_unstable } from './useOptionStyles.styles';\n"],"names":["Option","renderOption_unstable","useOption_unstable","useOptionBase_unstable","optionClassNames","useOptionStyles_unstable"],"mappings":"AAAA,SAASA,MAAM,QAAQ,WAAW;AAElC,SAASC,qBAAqB,QAAQ,iBAAiB;AACvD,SAASC,kBAAkB,EAAEC,sBAAsB,QAAQ,cAAc;AACzE,SAASC,gBAAgB,EAAEC,wBAAwB,QAAQ,2BAA2B"}

View File

@@ -0,0 +1,13 @@
import { jsx as _jsx, jsxs as _jsxs } from "@fluentui/react-jsx-runtime/jsx-runtime";
import { assertSlots } from '@fluentui/react-utilities';
/**
* Render the final JSX of Option
*/ export const renderOption_unstable = (state)=>{
assertSlots(state);
return /*#__PURE__*/ _jsxs(state.root, {
children: [
state.checkIcon && /*#__PURE__*/ _jsx(state.checkIcon, {}),
state.root.children
]
});
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/Option/renderOption.tsx"],"sourcesContent":["/** @jsxRuntime automatic */\n/** @jsxImportSource @fluentui/react-jsx-runtime */\n\nimport { assertSlots } from '@fluentui/react-utilities';\nimport type { JSXElement } from '@fluentui/react-utilities';\nimport type { OptionState, OptionSlots } from './Option.types';\n\n/**\n * Render the final JSX of Option\n */\nexport const renderOption_unstable = (state: OptionState): JSXElement => {\n assertSlots<OptionSlots>(state);\n\n return (\n <state.root>\n {state.checkIcon && <state.checkIcon />}\n {state.root.children}\n </state.root>\n );\n};\n"],"names":["assertSlots","renderOption_unstable","state","root","checkIcon","children"],"mappings":"AAAA,0BAA0B,GAC1B,iDAAiD;AAEjD,SAASA,WAAW,QAAQ,4BAA4B;AAIxD;;CAEC,GACD,OAAO,MAAMC,wBAAwB,CAACC;IACpCF,YAAyBE;IAEzB,qBACE,MAACA,MAAMC,IAAI;;YACRD,MAAME,SAAS,kBAAI,KAACF,MAAME,SAAS;YACnCF,MAAMC,IAAI,CAACE,QAAQ;;;AAG1B,EAAE"}

View File

@@ -0,0 +1,145 @@
'use client';
import * as React from 'react';
import { getIntrinsicElementProps, useId, useMergedRefs, slot } from '@fluentui/react-utilities';
import { useActiveDescendantContext } from '@fluentui/react-aria';
import { CheckmarkFilled, Checkmark12Filled } from '@fluentui/react-icons';
import { useListboxContext_unstable } from '../../contexts/ListboxContext';
function getTextString(text, children) {
if (text !== undefined) {
return text;
}
let textString = '';
let hasNonStringChild = false;
React.Children.forEach(children, (child)=>{
if (typeof child === 'string') {
textString += child;
} else {
hasNonStringChild = true;
}
});
// warn if an Option has non-string children and no text prop
if (hasNonStringChild) {
// eslint-disable-next-line no-console
console.warn('Provide a `text` prop to Option components when they contain non-string children.');
}
return textString;
}
/**
* Create the state required to render Option.
*
* The returned state can be modified with hooks such as useOptionStyles_unstable,
* before being passed to renderOption_unstable.
*
* @param props - props from this instance of Option
* @param ref - reference to root HTMLElement of Option
*/ export const useOption_unstable = (props, ref)=>{
'use no memo';
const state = useOptionBase_unstable(props, ref);
// check icon
let CheckIcon = /*#__PURE__*/ React.createElement(CheckmarkFilled, null);
if (state.multiselect) {
CheckIcon = state.selected ? /*#__PURE__*/ React.createElement(Checkmark12Filled, null) : '';
}
if (state.checkIcon) {
var _state_checkIcon;
var _children;
(_children = (_state_checkIcon = state.checkIcon).children) !== null && _children !== void 0 ? _children : _state_checkIcon.children = CheckIcon;
}
return state;
};
/**
* Create the base state required to render Option.
*
* @param props - props from this instance of Option
* @param ref - reference to root HTMLElement of Option
*/ export const useOptionBase_unstable = (props, ref)=>{
const { children, disabled, text, value } = props;
const optionRef = React.useRef(null);
const optionText = getTextString(text, children);
const optionValue = value !== null && value !== void 0 ? value : optionText;
// use the id if provided, otherwise use a generated id
const id = useId('fluent-option', props.id);
// data used for context registration & events
const optionData = React.useMemo(()=>({
id,
disabled,
text: optionText,
value: optionValue
}), [
id,
disabled,
optionText,
optionValue
]);
// context values
const { controller: activeDescendantController } = useActiveDescendantContext();
const multiselect = useListboxContext_unstable((ctx)=>ctx.multiselect);
const registerOption = useListboxContext_unstable((ctx)=>ctx.registerOption);
const selected = useListboxContext_unstable((ctx)=>{
const selectedOptions = ctx.selectedOptions;
return optionValue !== undefined && selectedOptions.find((o)=>o === optionValue) !== undefined;
});
const selectOption = useListboxContext_unstable((ctx)=>ctx.selectOption);
const onOptionClick = useListboxContext_unstable((ctx)=>ctx.onOptionClick);
const onClick = (event)=>{
var _props_onClick;
if (disabled) {
event.preventDefault();
return;
}
activeDescendantController.focus(id);
// handle selection change
selectOption(event, optionData);
onOptionClick(event);
(_props_onClick = props.onClick) === null || _props_onClick === void 0 ? void 0 : _props_onClick.call(props, event);
};
// register option data with context
React.useEffect(()=>{
if (id && optionRef.current) {
return registerOption(optionData, optionRef.current);
}
}, [
id,
optionData,
registerOption
]);
const semanticProps = multiselect ? {
role: 'menuitemcheckbox',
'aria-checked': selected
} : {
role: 'option',
'aria-selected': selected
};
return {
components: {
root: 'div',
checkIcon: 'span'
},
root: slot.always(getIntrinsicElementProps('div', {
// FIXME:
// `ref` is wrongly assigned to be `HTMLElement` instead of `HTMLDivElement`
// but since it would be a breaking change to fix it, we are casting ref to it's proper type
ref: useMergedRefs(ref, optionRef),
'aria-disabled': disabled ? 'true' : undefined,
id,
...semanticProps,
...props,
onClick
}), {
elementType: 'div'
}),
checkIcon: slot.optional(props.checkIcon, {
renderByDefault: true,
defaultProps: {
'aria-hidden': 'true'
},
elementType: 'span'
}),
disabled,
multiselect,
selected,
// no longer used
focusVisible: false,
active: false
};
};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,195 @@
'use client';
import { tokens } from '@fluentui/react-theme';
import { ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE } from '@fluentui/react-aria';
import { __styles, mergeClasses, shorthands } from '@griffel/react';
export const optionClassNames = {
root: 'fui-Option',
checkIcon: 'fui-Option__checkIcon'
};
/**
* Styles for the root slot
*/
const useStyles = /*#__PURE__*/__styles({
root: {
Bt984gj: "f122n59",
Beyfa6y: 0,
Bbmb7ep: 0,
Btl43ni: 0,
B7oj6ja: 0,
Dimara: "ft85np5",
sj55zd: "f19n0e5",
i8kkvl: "f1ufnopg",
Bceei9c: "f1k6fduh",
mc9l5x: "f22iagw",
Bahqtrf: "fk6fouc",
Be2twd7: "fkhj508",
Bg96gwp: "f1i3iumi",
Byoj8tv: 0,
uwmqm3: 0,
z189sj: 0,
z8tnut: 0,
B0ocmuz: "fm5eomj",
qhf8xq: "f10pi13n",
Jwef8y: "f1knas48",
Bi91k9c: "feu1g3u",
zqbkvg: "fo79ri9",
h82x05: ["f1osiabc", "f1e8le25"],
cqj998: "f1yusjty",
j3hlsh: ["f1e8le25", "f1osiabc"],
ecr2s2: "fb40n2d",
lj723h: "f1g4hkjv",
Btxx2vb: "f1lnr2zp",
sltcwy: ["f1ogfk9z", "f1g7j8ec"],
dnwvvm: "fiuf46r",
Blyvkvs: ["f1g7j8ec", "f1ogfk9z"]
},
active: {
Bowz1zl: "f11vrvdw",
oxogb1: "f17hxjb7",
Ix2sn8: "f1dha69c",
q7v32p: "f1lm7500",
B7cbj04: 0,
Bewtojm: 0,
b50fsz: 0,
B1wzb3v: 0,
Bqwk70n: 0,
B37u8z8: 0,
avt0cx: 0,
f0sref: 0,
B9fkznv: 0,
Be3o27t: 0,
Bertapg: 0,
B53xpsf: 0,
Bsv72rj: 0,
B39dzdd: 0,
Btq9bd3: 0,
Bqfxd14: 0,
atup0s: "fo7xqb",
Fffuxt: 0,
Bttcd12: 0,
Beitzug: 0,
Bqougee: 0,
B86i8pi: "f1kurthe",
Bhijsxg: "fwq15dy",
kktds4: "f1pb3wry",
Bmau3bo: ["ftjv2f4", "f1flhb1f"],
npektv: ["f1flhb1f", "ftjv2f4"]
},
disabled: {
sj55zd: "f1s2aq7o",
Jwef8y: "f9ql6rf",
Bi91k9c: "fvgxktp",
zqbkvg: "f185j3qj",
h82x05: ["f1dligi3", "f1vydzie"],
cqj998: "fjw1di3",
j3hlsh: ["f1vydzie", "f1dligi3"],
ecr2s2: "fgj9um3",
lj723h: "f19wldhg",
Btxx2vb: "f1ss0kt2",
sltcwy: ["f1t6oli3", "fjy9ci8"],
dnwvvm: "fresaxk",
Blyvkvs: ["fjy9ci8", "f1t6oli3"],
B7iucu3: "f1cyfu5x"
},
selected: {},
checkIcon: {
Bnnss6s: "fi64zpg",
Be2twd7: "fod5ikn",
Frg6f3: ["f18b9hdq", "fn6qj8t"],
t21cq0: ["f1xk557c", "f1h9en5y"],
Bcdw1i0: "fd7fpy0",
Bo70h7d: "fvc9v3g"
},
selectedCheck: {
Bcdw1i0: "f1022m68"
},
multiselectCheck: {
Bgfg5da: 0,
B9xav0g: 0,
oivjwe: 0,
Bn0qgzm: 0,
B4g9neb: 0,
zhjwy3: 0,
wvpqe5: 0,
ibv6hh: 0,
u1mtju: 0,
h3c5rm: 0,
vrafjx: 0,
Bekrc4i: 0,
i8vvqc: 0,
g2u3we: 0,
icvyot: 0,
B4j52fo: 0,
irswps: "f1l3cf7o",
Beyfa6y: 0,
Bbmb7ep: 0,
Btl43ni: 0,
B7oj6ja: 0,
Dimara: "fq9zq91",
B7ck84d: "f1ewtqcl",
mc9l5x: "f22iagw",
Bt984gj: "f122n59",
Brf1p80: "f4d9j23",
Bkfmm31: "f1w9h62z",
Be2twd7: "f1ugzwwg",
Bqenvij: "fd461yt",
a9b677: "fjw5fx7",
Bcdw1i0: "f1022m68"
},
selectedMultiselectCheck: {
De3pzq: "ftywsgz",
sj55zd: "fqpbvvt",
g2u3we: "f3xi7mh",
h3c5rm: ["ftovhe4", "f1wczvin"],
B9xav0g: "f68vbr6",
zhjwy3: ["f1wczvin", "ftovhe4"]
},
checkDisabled: {
sj55zd: "f1s2aq7o",
B7iucu3: "f1cyfu5x"
},
multiselectCheckDisabled: {
g2u3we: "f1r1t4y1",
h3c5rm: ["fmj8ijw", "figx54m"],
B9xav0g: "f360ss8",
zhjwy3: ["figx54m", "fmj8ijw"]
}
}, {
d: [".f122n59{align-items:center;}", [".ft85np5{border-radius:var(--borderRadiusMedium);}", {
p: -1
}], ".f19n0e5{color:var(--colorNeutralForeground1);}", ".f1ufnopg{column-gap:var(--spacingHorizontalXS);}", ".f1k6fduh{cursor:pointer;}", ".f22iagw{display:flex;}", ".fk6fouc{font-family:var(--fontFamilyBase);}", ".fkhj508{font-size:var(--fontSizeBase300);}", ".f1i3iumi{line-height:var(--lineHeightBase300);}", [".fm5eomj{padding:var(--spacingVerticalSNudge) var(--spacingHorizontalS);}", {
p: -1
}], ".f10pi13n{position:relative;}", ".f11vrvdw[data-activedescendant-focusvisible]::after{content:\"\";}", ".f17hxjb7[data-activedescendant-focusvisible]::after{position:absolute;}", ".f1dha69c[data-activedescendant-focusvisible]::after{pointer-events:none;}", ".f1lm7500[data-activedescendant-focusvisible]::after{z-index:1;}", [".fo7xqb[data-activedescendant-focusvisible]::after{border:2px solid var(--colorStrokeFocus2);}", {
p: -2
}], [".f1kurthe[data-activedescendant-focusvisible]::after{border-radius:var(--borderRadiusMedium);}", {
p: -1
}], ".fwq15dy[data-activedescendant-focusvisible]::after{top:-2px;}", ".f1pb3wry[data-activedescendant-focusvisible]::after{bottom:-2px;}", ".ftjv2f4[data-activedescendant-focusvisible]::after{left:-2px;}", ".f1flhb1f[data-activedescendant-focusvisible]::after{right:-2px;}", ".f1s2aq7o{color:var(--colorNeutralForegroundDisabled);}", ".fi64zpg{flex-shrink:0;}", ".fod5ikn{font-size:var(--fontSizeBase400);}", ".f18b9hdq{margin-left:calc(var(--spacingHorizontalXXS) * -1);}", ".fn6qj8t{margin-right:calc(var(--spacingHorizontalXXS) * -1);}", ".f1xk557c{margin-right:var(--spacingHorizontalXXS);}", ".f1h9en5y{margin-left:var(--spacingHorizontalXXS);}", ".fd7fpy0{visibility:hidden;}", ".fvc9v3g svg{display:block;}", ".f1022m68{visibility:visible;}", [".f1l3cf7o{border:var(--strokeWidthThin) solid var(--colorNeutralStrokeAccessible);}", {
p: -2
}], [".fq9zq91{border-radius:var(--borderRadiusSmall);}", {
p: -1
}], ".f1ewtqcl{box-sizing:border-box;}", ".f4d9j23{justify-content:center;}", ".f1w9h62z{fill:currentColor;}", ".f1ugzwwg{font-size:12px;}", ".fd461yt{height:16px;}", ".fjw5fx7{width:16px;}", ".ftywsgz{background-color:var(--colorCompoundBrandBackground);}", ".fqpbvvt{color:var(--colorNeutralForegroundInverted);}", ".f3xi7mh{border-top-color:var(--colorCompoundBrandBackground);}", ".ftovhe4{border-right-color:var(--colorCompoundBrandBackground);}", ".f1wczvin{border-left-color:var(--colorCompoundBrandBackground);}", ".f68vbr6{border-bottom-color:var(--colorCompoundBrandBackground);}", ".f1r1t4y1{border-top-color:var(--colorNeutralForegroundDisabled);}", ".fmj8ijw{border-right-color:var(--colorNeutralForegroundDisabled);}", ".figx54m{border-left-color:var(--colorNeutralForegroundDisabled);}", ".f360ss8{border-bottom-color:var(--colorNeutralForegroundDisabled);}"],
h: [".f1knas48:hover{background-color:var(--colorNeutralBackground1Hover);}", ".feu1g3u:hover{color:var(--colorNeutralForeground1Hover);}", ".fo79ri9:hover .fui-Option__checkIcon{border-top-color:var(--colorNeutralForeground1Hover);}", ".f1osiabc:hover .fui-Option__checkIcon{border-right-color:var(--colorNeutralForeground1Hover);}", ".f1e8le25:hover .fui-Option__checkIcon{border-left-color:var(--colorNeutralForeground1Hover);}", ".f1yusjty:hover .fui-Option__checkIcon{border-bottom-color:var(--colorNeutralForeground1Hover);}", ".f9ql6rf:hover{background-color:var(--colorTransparentBackground);}", ".fvgxktp:hover{color:var(--colorNeutralForegroundDisabled);}", ".f185j3qj:hover .fui-Option__checkIcon{border-top-color:var(--colorNeutralForegroundDisabled);}", ".f1dligi3:hover .fui-Option__checkIcon{border-right-color:var(--colorNeutralForegroundDisabled);}", ".f1vydzie:hover .fui-Option__checkIcon{border-left-color:var(--colorNeutralForegroundDisabled);}", ".fjw1di3:hover .fui-Option__checkIcon{border-bottom-color:var(--colorNeutralForegroundDisabled);}"],
a: [".fb40n2d:active{background-color:var(--colorNeutralBackground1Pressed);}", ".f1g4hkjv:active{color:var(--colorNeutralForeground1Pressed);}", ".f1lnr2zp:active .fui-Option__checkIcon{border-top-color:var(--colorNeutralForeground1Hover);}", ".f1ogfk9z:active .fui-Option__checkIcon{border-right-color:var(--colorNeutralForeground1Hover);}", ".f1g7j8ec:active .fui-Option__checkIcon{border-left-color:var(--colorNeutralForeground1Hover);}", ".fiuf46r:active .fui-Option__checkIcon{border-bottom-color:var(--colorNeutralForeground1Hover);}", ".fgj9um3:active{background-color:var(--colorTransparentBackground);}", ".f19wldhg:active{color:var(--colorNeutralForegroundDisabled);}", ".f1ss0kt2:active .fui-Option__checkIcon{border-top-color:var(--colorNeutralForegroundDisabled);}", ".f1t6oli3:active .fui-Option__checkIcon{border-right-color:var(--colorNeutralForegroundDisabled);}", ".fjy9ci8:active .fui-Option__checkIcon{border-left-color:var(--colorNeutralForegroundDisabled);}", ".fresaxk:active .fui-Option__checkIcon{border-bottom-color:var(--colorNeutralForegroundDisabled);}"],
m: [["@media (forced-colors: active){.f1cyfu5x{color:GrayText;}}", {
m: "(forced-colors: active)"
}]]
});
/**
* Apply styling to the Option slots based on the state
*/
export const useOptionStyles_unstable = state => {
'use no memo';
const {
disabled,
multiselect,
selected
} = state;
const styles = useStyles();
state.root.className = mergeClasses(optionClassNames.root, styles.root, styles.active, disabled && styles.disabled, selected && styles.selected, state.root.className);
if (state.checkIcon) {
state.checkIcon.className = mergeClasses(optionClassNames.checkIcon, styles.checkIcon, multiselect && styles.multiselectCheck, selected && styles.selectedCheck, selected && multiselect && styles.selectedMultiselectCheck, disabled && styles.checkDisabled, disabled && multiselect && styles.multiselectCheckDisabled, state.checkIcon.className);
}
return state;
};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,118 @@
'use client';
import { tokens } from '@fluentui/react-theme';
import { ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE } from '@fluentui/react-aria';
import { makeStyles, mergeClasses, shorthands } from '@griffel/react';
export const optionClassNames = {
root: 'fui-Option',
checkIcon: 'fui-Option__checkIcon'
};
/**
* Styles for the root slot
*/ const useStyles = makeStyles({
root: {
alignItems: 'center',
borderRadius: tokens.borderRadiusMedium,
color: tokens.colorNeutralForeground1,
columnGap: tokens.spacingHorizontalXS,
cursor: 'pointer',
display: 'flex',
fontFamily: tokens.fontFamilyBase,
fontSize: tokens.fontSizeBase300,
lineHeight: tokens.lineHeightBase300,
padding: `${tokens.spacingVerticalSNudge} ${tokens.spacingHorizontalS}`,
position: 'relative',
':hover': {
backgroundColor: tokens.colorNeutralBackground1Hover,
color: tokens.colorNeutralForeground1Hover,
[`& .${optionClassNames.checkIcon}`]: shorthands.borderColor(tokens.colorNeutralForeground1Hover)
},
':active': {
backgroundColor: tokens.colorNeutralBackground1Pressed,
color: tokens.colorNeutralForeground1Pressed,
[`& .${optionClassNames.checkIcon}`]: shorthands.borderColor(tokens.colorNeutralForeground1Hover)
}
},
active: {
[`[${ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE}]::after`]: {
content: '""',
position: 'absolute',
pointerEvents: 'none',
zIndex: 1,
border: `2px solid ${tokens.colorStrokeFocus2}`,
borderRadius: tokens.borderRadiusMedium,
top: '-2px',
bottom: '-2px',
left: '-2px',
right: '-2px'
}
},
disabled: {
color: tokens.colorNeutralForegroundDisabled,
':hover': {
backgroundColor: tokens.colorTransparentBackground,
color: tokens.colorNeutralForegroundDisabled,
[`& .${optionClassNames.checkIcon}`]: shorthands.borderColor(tokens.colorNeutralForegroundDisabled)
},
':active': {
backgroundColor: tokens.colorTransparentBackground,
color: tokens.colorNeutralForegroundDisabled,
[`& .${optionClassNames.checkIcon}`]: shorthands.borderColor(tokens.colorNeutralForegroundDisabled)
},
'@media (forced-colors: active)': {
color: 'GrayText'
}
},
selected: {},
checkIcon: {
flexShrink: 0,
fontSize: tokens.fontSizeBase400,
// Shift icon(s) to the left to give text content extra spacing without needing an extra node
// This is done instead of gap since the extra space only exists between icon > content, not icon > icon
marginLeft: `calc(${tokens.spacingHorizontalXXS} * -1)`,
marginRight: tokens.spacingHorizontalXXS,
visibility: 'hidden',
'& svg': {
display: 'block'
}
},
selectedCheck: {
visibility: 'visible'
},
multiselectCheck: {
border: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStrokeAccessible}`,
borderRadius: tokens.borderRadiusSmall,
boxSizing: 'border-box',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fill: 'currentColor',
fontSize: '12px',
height: '16px',
width: '16px',
visibility: 'visible'
},
selectedMultiselectCheck: {
backgroundColor: tokens.colorCompoundBrandBackground,
color: tokens.colorNeutralForegroundInverted,
...shorthands.borderColor(tokens.colorCompoundBrandBackground)
},
checkDisabled: {
color: tokens.colorNeutralForegroundDisabled,
'@media (forced-colors: active)': {
color: 'GrayText'
}
},
multiselectCheckDisabled: shorthands.borderColor(tokens.colorNeutralForegroundDisabled)
});
/**
* Apply styling to the Option slots based on the state
*/ export const useOptionStyles_unstable = (state)=>{
'use no memo';
const { disabled, multiselect, selected } = state;
const styles = useStyles();
state.root.className = mergeClasses(optionClassNames.root, styles.root, styles.active, disabled && styles.disabled, selected && styles.selected, state.root.className);
if (state.checkIcon) {
state.checkIcon.className = mergeClasses(optionClassNames.checkIcon, styles.checkIcon, multiselect && styles.multiselectCheck, selected && styles.selectedCheck, selected && multiselect && styles.selectedMultiselectCheck, disabled && styles.checkDisabled, disabled && multiselect && styles.multiselectCheckDisabled, state.checkIcon.className);
}
return state;
};

File diff suppressed because one or more lines are too long