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,13 @@
'use client';
import * as React from 'react';
import { useAriaLive_unstable } from './useAriaLive';
import { renderAriaLive_unstable } from './renderAriaLive';
import { useAriaLiveStyles_unstable } from './useAriaLiveStyles.styles';
/**
* A component that manages aria live announcements imperatively
*/ export const AriaLive = (props)=>{
const state = useAriaLive_unstable(props);
useAriaLiveStyles_unstable(state);
return renderAriaLive_unstable(state);
};
AriaLive.displayName = 'AriaLive';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/AriaLive/AriaLive.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useAriaLive_unstable } from './useAriaLive';\nimport { renderAriaLive_unstable } from './renderAriaLive';\nimport { useAriaLiveStyles_unstable } from './useAriaLiveStyles.styles';\nimport type { AriaLiveProps } from './AriaLive.types';\n\n/**\n * A component that manages aria live announcements imperatively\n */\nexport const AriaLive: React.FC<AriaLiveProps> = props => {\n const state = useAriaLive_unstable(props);\n\n useAriaLiveStyles_unstable(state);\n return renderAriaLive_unstable(state);\n};\n\nAriaLive.displayName = 'AriaLive';\n"],"names":["React","useAriaLive_unstable","renderAriaLive_unstable","useAriaLiveStyles_unstable","AriaLive","props","state","displayName"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,oBAAoB,QAAQ,gBAAgB;AACrD,SAASC,uBAAuB,QAAQ,mBAAmB;AAC3D,SAASC,0BAA0B,QAAQ,6BAA6B;AAGxE;;CAEC,GACD,OAAO,MAAMC,WAAoCC,CAAAA;IAC/C,MAAMC,QAAQL,qBAAqBI;IAEnCF,2BAA2BG;IAC3B,OAAOJ,wBAAwBI;AACjC,EAAE;AAEFF,SAASG,WAAW,GAAG"}

View File

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

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/AriaLive/AriaLive.types.ts"],"sourcesContent":["import * as React from 'react';\nimport type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';\n\nexport type AriaLiveSlots = {\n assertive: NonNullable<Slot<'div'>>;\n polite: NonNullable<Slot<'div'>>;\n};\n\nexport type AriaLivePoliteness = 'polite' | 'assertive';\n\n/**\n * AriaLive Props\n */\nexport type AriaLiveProps = ComponentProps<Partial<AriaLiveSlots>> & {\n announceRef: React.Ref<Announce>;\n children?: React.ReactNode;\n};\n\n/**\n * State used in rendering AriaLive\n */\nexport type AriaLiveState = ComponentState<AriaLiveSlots>;\n\nexport type Announce = (message: string, options: AnnounceOptions) => void;\n\nexport type LiveMessage = {\n message: string;\n createdAt: number;\n politeness: AriaLivePoliteness;\n};\n\nexport type AnnounceOptions = {\n politeness: AriaLivePoliteness;\n};\n"],"names":["React"],"mappings":"AAAA,YAAYA,WAAW,QAAQ"}

View File

@@ -0,0 +1,4 @@
export { AriaLive } from './AriaLive';
export { renderAriaLive_unstable } from './renderAriaLive';
export { useAriaLive_unstable } from './useAriaLive';
export { ariaLiveClassNames, useAriaLiveStyles_unstable } from './useAriaLiveStyles.styles';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/AriaLive/index.ts"],"sourcesContent":["export { AriaLive } from './AriaLive';\nexport type {\n Announce,\n AnnounceOptions,\n AriaLivePoliteness,\n AriaLiveProps,\n AriaLiveSlots,\n AriaLiveState,\n LiveMessage,\n} from './AriaLive.types';\nexport { renderAriaLive_unstable } from './renderAriaLive';\nexport { useAriaLive_unstable } from './useAriaLive';\nexport { ariaLiveClassNames, useAriaLiveStyles_unstable } from './useAriaLiveStyles.styles';\n"],"names":["AriaLive","renderAriaLive_unstable","useAriaLive_unstable","ariaLiveClassNames","useAriaLiveStyles_unstable"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,aAAa;AAUtC,SAASC,uBAAuB,QAAQ,mBAAmB;AAC3D,SAASC,oBAAoB,QAAQ,gBAAgB;AACrD,SAASC,kBAAkB,EAAEC,0BAA0B,QAAQ,6BAA6B"}

View File

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

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/AriaLive/renderAriaLive.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 { AriaLiveState, AriaLiveSlots } from './AriaLive.types';\n\n/**\n * Render the final JSX of AriaLive\n */\nexport const renderAriaLive_unstable = (state: AriaLiveState): JSXElement => {\n assertSlots<AriaLiveSlots>(state);\n\n return (\n <>\n <state.assertive />\n <state.polite />\n </>\n );\n};\n"],"names":["assertSlots","renderAriaLive_unstable","state","assertive","polite"],"mappings":"AAAA,0BAA0B,GAC1B,iDAAiD;AAEjD,SAASA,WAAW,QAAQ,4BAA4B;AAIxD;;CAEC,GACD,OAAO,MAAMC,0BAA0B,CAACC;IACtCF,YAA2BE;IAE3B,qBACE;;0BACE,KAACA,MAAMC,SAAS;0BAChB,KAACD,MAAME,MAAM;;;AAGnB,EAAE"}

View File

@@ -0,0 +1,77 @@
'use client';
import * as React from 'react';
import { createPriorityQueue, useEventCallback, slot, useTimeout } from '@fluentui/react-utilities';
/** The duration the message needs to be in present in DOM for screen readers to register a change and announce */ const MESSAGE_DURATION = 500;
/**
* Create the state required to render AriaLive.
*
* The returned state can be modified with hooks such as useAriaLiveStyles_unstable,
* before being passed to renderAriaLive_unstable.
*
* @param props - props from this instance of AriaLive
*/ export const useAriaLive_unstable = (props)=>{
const [currentMessage, setCurrentMessage] = React.useState(undefined);
// Can't rely on Date.now() if user invokes announce more than once in a code block
const order = React.useRef(0);
const [messageQueue] = React.useState(()=>createPriorityQueue((a, b)=>{
if (a.politeness === b.politeness) {
return a.createdAt - b.createdAt;
}
return a.politeness === 'assertive' ? -1 : 1;
}));
const announce = useEventCallback((message, options)=>{
const { politeness } = options;
if (message === (currentMessage === null || currentMessage === void 0 ? void 0 : currentMessage.message)) {
return;
}
const liveMessage = {
message,
politeness,
createdAt: order.current++
};
if (!currentMessage) {
setCurrentMessage(liveMessage);
} else {
messageQueue.enqueue(liveMessage);
}
});
const [setMessageTimeout, clearMessageTimeout] = useTimeout();
React.useEffect(()=>{
setMessageTimeout(()=>{
if (messageQueue.peek()) {
setCurrentMessage(messageQueue.dequeue());
} else {
setCurrentMessage(undefined);
}
}, MESSAGE_DURATION);
return ()=>clearMessageTimeout();
}, [
currentMessage,
messageQueue,
setMessageTimeout,
clearMessageTimeout
]);
React.useImperativeHandle(props.announceRef, ()=>announce);
const politeMessage = (currentMessage === null || currentMessage === void 0 ? void 0 : currentMessage.politeness) === 'polite' ? currentMessage.message : undefined;
const assertiveMessage = (currentMessage === null || currentMessage === void 0 ? void 0 : currentMessage.politeness) === 'assertive' ? currentMessage.message : undefined;
return {
components: {
assertive: 'div',
polite: 'div'
},
assertive: slot.always(props.assertive, {
defaultProps: {
'aria-live': 'assertive',
children: assertiveMessage
},
elementType: 'div'
}),
polite: slot.always(props.polite, {
defaultProps: {
'aria-live': 'polite',
children: politeMessage
},
elementType: 'div'
})
};
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/AriaLive/useAriaLive.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { createPriorityQueue, useEventCallback, slot, useTimeout } from '@fluentui/react-utilities';\nimport type { AnnounceOptions, AriaLiveProps, AriaLiveState, LiveMessage } from './AriaLive.types';\n\n/** The duration the message needs to be in present in DOM for screen readers to register a change and announce */\nconst MESSAGE_DURATION = 500;\n\n/**\n * Create the state required to render AriaLive.\n *\n * The returned state can be modified with hooks such as useAriaLiveStyles_unstable,\n * before being passed to renderAriaLive_unstable.\n *\n * @param props - props from this instance of AriaLive\n */\nexport const useAriaLive_unstable = (props: AriaLiveProps): AriaLiveState => {\n const [currentMessage, setCurrentMessage] = React.useState<LiveMessage | undefined>(undefined);\n // Can't rely on Date.now() if user invokes announce more than once in a code block\n const order = React.useRef(0);\n const [messageQueue] = React.useState(() =>\n createPriorityQueue<LiveMessage>((a, b) => {\n if (a.politeness === b.politeness) {\n return a.createdAt - b.createdAt;\n }\n\n return a.politeness === 'assertive' ? -1 : 1;\n }),\n );\n\n const announce = useEventCallback((message: string, options: AnnounceOptions) => {\n const { politeness } = options;\n if (message === currentMessage?.message) {\n return;\n }\n\n const liveMessage: LiveMessage = {\n message,\n politeness,\n createdAt: order.current++,\n };\n\n if (!currentMessage) {\n setCurrentMessage(liveMessage);\n } else {\n messageQueue.enqueue(liveMessage);\n }\n });\n\n const [setMessageTimeout, clearMessageTimeout] = useTimeout();\n\n React.useEffect(() => {\n setMessageTimeout(() => {\n if (messageQueue.peek()) {\n setCurrentMessage(messageQueue.dequeue());\n } else {\n setCurrentMessage(undefined);\n }\n }, MESSAGE_DURATION);\n\n return () => clearMessageTimeout();\n }, [currentMessage, messageQueue, setMessageTimeout, clearMessageTimeout]);\n\n React.useImperativeHandle(props.announceRef, () => announce);\n\n const politeMessage = currentMessage?.politeness === 'polite' ? currentMessage.message : undefined;\n const assertiveMessage = currentMessage?.politeness === 'assertive' ? currentMessage.message : undefined;\n\n return {\n components: {\n assertive: 'div',\n polite: 'div',\n },\n\n assertive: slot.always(props.assertive, {\n defaultProps: { 'aria-live': 'assertive', children: assertiveMessage },\n elementType: 'div',\n }),\n polite: slot.always(props.polite, {\n defaultProps: { 'aria-live': 'polite', children: politeMessage },\n elementType: 'div',\n }),\n };\n};\n"],"names":["React","createPriorityQueue","useEventCallback","slot","useTimeout","MESSAGE_DURATION","useAriaLive_unstable","props","currentMessage","setCurrentMessage","useState","undefined","order","useRef","messageQueue","a","b","politeness","createdAt","announce","message","options","liveMessage","current","enqueue","setMessageTimeout","clearMessageTimeout","useEffect","peek","dequeue","useImperativeHandle","announceRef","politeMessage","assertiveMessage","components","assertive","polite","always","defaultProps","children","elementType"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,mBAAmB,EAAEC,gBAAgB,EAAEC,IAAI,EAAEC,UAAU,QAAQ,4BAA4B;AAGpG,gHAAgH,GAChH,MAAMC,mBAAmB;AAEzB;;;;;;;CAOC,GACD,OAAO,MAAMC,uBAAuB,CAACC;IACnC,MAAM,CAACC,gBAAgBC,kBAAkB,GAAGT,MAAMU,QAAQ,CAA0BC;IACpF,mFAAmF;IACnF,MAAMC,QAAQZ,MAAMa,MAAM,CAAC;IAC3B,MAAM,CAACC,aAAa,GAAGd,MAAMU,QAAQ,CAAC,IACpCT,oBAAiC,CAACc,GAAGC;YACnC,IAAID,EAAEE,UAAU,KAAKD,EAAEC,UAAU,EAAE;gBACjC,OAAOF,EAAEG,SAAS,GAAGF,EAAEE,SAAS;YAClC;YAEA,OAAOH,EAAEE,UAAU,KAAK,cAAc,CAAC,IAAI;QAC7C;IAGF,MAAME,WAAWjB,iBAAiB,CAACkB,SAAiBC;QAClD,MAAM,EAAEJ,UAAU,EAAE,GAAGI;QACvB,IAAID,aAAYZ,2BAAAA,qCAAAA,eAAgBY,OAAO,GAAE;YACvC;QACF;QAEA,MAAME,cAA2B;YAC/BF;YACAH;YACAC,WAAWN,MAAMW,OAAO;QAC1B;QAEA,IAAI,CAACf,gBAAgB;YACnBC,kBAAkBa;QACpB,OAAO;YACLR,aAAaU,OAAO,CAACF;QACvB;IACF;IAEA,MAAM,CAACG,mBAAmBC,oBAAoB,GAAGtB;IAEjDJ,MAAM2B,SAAS,CAAC;QACdF,kBAAkB;YAChB,IAAIX,aAAac,IAAI,IAAI;gBACvBnB,kBAAkBK,aAAae,OAAO;YACxC,OAAO;gBACLpB,kBAAkBE;YACpB;QACF,GAAGN;QAEH,OAAO,IAAMqB;IACf,GAAG;QAAClB;QAAgBM;QAAcW;QAAmBC;KAAoB;IAEzE1B,MAAM8B,mBAAmB,CAACvB,MAAMwB,WAAW,EAAE,IAAMZ;IAEnD,MAAMa,gBAAgBxB,CAAAA,2BAAAA,qCAAAA,eAAgBS,UAAU,MAAK,WAAWT,eAAeY,OAAO,GAAGT;IACzF,MAAMsB,mBAAmBzB,CAAAA,2BAAAA,qCAAAA,eAAgBS,UAAU,MAAK,cAAcT,eAAeY,OAAO,GAAGT;IAE/F,OAAO;QACLuB,YAAY;YACVC,WAAW;YACXC,QAAQ;QACV;QAEAD,WAAWhC,KAAKkC,MAAM,CAAC9B,MAAM4B,SAAS,EAAE;YACtCG,cAAc;gBAAE,aAAa;gBAAaC,UAAUN;YAAiB;YACrEO,aAAa;QACf;QACAJ,QAAQjC,KAAKkC,MAAM,CAAC9B,MAAM6B,MAAM,EAAE;YAChCE,cAAc;gBAAE,aAAa;gBAAUC,UAAUP;YAAc;YAC/DQ,aAAa;QACf;IACF;AACF,EAAE"}

View File

@@ -0,0 +1,22 @@
'use client';
import { mergeClasses, __resetStyles } from '@griffel/react';
export const ariaLiveClassNames = {
assertive: 'fui-AriaLive__assertive',
polite: 'fui-AriaLive__polite'
};
/**
* Styles for the root slot
*/
const useResetStyles = /*#__PURE__*/__resetStyles("rrd10u0", null, [".rrd10u0{clip:rect(0px, 0px, 0px, 0px);height:1px;margin:-1px;overflow:hidden;padding:0px;width:1px;position:absolute;}"]);
/**
* Apply styling to the AriaLive slots based on the state
*/
export const useAriaLiveStyles_unstable = state => {
'use no memo';
const visuallyHidden = useResetStyles();
state.assertive.className = mergeClasses(visuallyHidden, ariaLiveClassNames.assertive, state.assertive.className);
state.polite.className = mergeClasses(visuallyHidden, ariaLiveClassNames.polite, state.polite.className);
return state;
};

View File

@@ -0,0 +1 @@
{"version":3,"names":["mergeClasses","__resetStyles","ariaLiveClassNames","assertive","polite","useResetStyles","useAriaLiveStyles_unstable","state","visuallyHidden","className"],"sources":["useAriaLiveStyles.styles.js"],"sourcesContent":["'use client';\nimport { mergeClasses, makeResetStyles } from '@griffel/react';\nexport const ariaLiveClassNames = {\n assertive: 'fui-AriaLive__assertive',\n polite: 'fui-AriaLive__polite'\n};\n/**\n * Styles for the root slot\n */ const useResetStyles = makeResetStyles({\n clip: 'rect(0px, 0px, 0px, 0px)',\n height: '1px',\n margin: '-1px',\n overflow: 'hidden',\n padding: '0px',\n width: '1px',\n position: 'absolute'\n});\n/**\n * Apply styling to the AriaLive slots based on the state\n */ export const useAriaLiveStyles_unstable = (state)=>{\n 'use no memo';\n const visuallyHidden = useResetStyles();\n state.assertive.className = mergeClasses(visuallyHidden, ariaLiveClassNames.assertive, state.assertive.className);\n state.polite.className = mergeClasses(visuallyHidden, ariaLiveClassNames.polite, state.polite.className);\n return state;\n};\n"],"mappings":"AAAA,YAAY;;AACZ,SAASA,YAAY,EAAAC,aAAA,QAAyB,gBAAgB;AAC9D,OAAO,MAAMC,kBAAkB,GAAG;EAC9BC,SAAS,EAAE,yBAAyB;EACpCC,MAAM,EAAE;AACZ,CAAC;AACD;AACA;AACA;AAAI,MAAMC,cAAc,gBAAGJ,aAAA,6IAQ1B,CAAC;AACF;AACA;AACA;AAAI,OAAO,MAAMK,0BAA0B,GAAIC,KAAK,IAAG;EACnD,aAAa;;EACb,MAAMC,cAAc,GAAGH,cAAc,CAAC,CAAC;EACvCE,KAAK,CAACJ,SAAS,CAACM,SAAS,GAAGT,YAAY,CAACQ,cAAc,EAAEN,kBAAkB,CAACC,SAAS,EAAEI,KAAK,CAACJ,SAAS,CAACM,SAAS,CAAC;EACjHF,KAAK,CAACH,MAAM,CAACK,SAAS,GAAGT,YAAY,CAACQ,cAAc,EAAEN,kBAAkB,CAACE,MAAM,EAAEG,KAAK,CAACH,MAAM,CAACK,SAAS,CAAC;EACxG,OAAOF,KAAK;AAChB,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,26 @@
'use client';
import { mergeClasses, makeResetStyles } from '@griffel/react';
export const ariaLiveClassNames = {
assertive: 'fui-AriaLive__assertive',
polite: 'fui-AriaLive__polite'
};
/**
* Styles for the root slot
*/ const useResetStyles = makeResetStyles({
clip: 'rect(0px, 0px, 0px, 0px)',
height: '1px',
margin: '-1px',
overflow: 'hidden',
padding: '0px',
width: '1px',
position: 'absolute'
});
/**
* Apply styling to the AriaLive slots based on the state
*/ export const useAriaLiveStyles_unstable = (state)=>{
'use no memo';
const visuallyHidden = useResetStyles();
state.assertive.className = mergeClasses(visuallyHidden, ariaLiveClassNames.assertive, state.assertive.className);
state.polite.className = mergeClasses(visuallyHidden, ariaLiveClassNames.polite, state.polite.className);
return state;
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/AriaLive/useAriaLiveStyles.styles.ts"],"sourcesContent":["'use client';\n\nimport { mergeClasses, makeResetStyles } from '@griffel/react';\nimport type { AriaLiveSlots, AriaLiveState } from './AriaLive.types';\nimport type { SlotClassNames } from '@fluentui/react-utilities';\n\nexport const ariaLiveClassNames: SlotClassNames<AriaLiveSlots> = {\n assertive: 'fui-AriaLive__assertive',\n polite: 'fui-AriaLive__polite',\n};\n\n/**\n * Styles for the root slot\n */\nconst useResetStyles = makeResetStyles({\n clip: 'rect(0px, 0px, 0px, 0px)',\n height: '1px',\n margin: '-1px',\n overflow: 'hidden',\n padding: '0px',\n width: '1px',\n position: 'absolute',\n});\n\n/**\n * Apply styling to the AriaLive slots based on the state\n */\nexport const useAriaLiveStyles_unstable = (state: AriaLiveState): AriaLiveState => {\n 'use no memo';\n\n const visuallyHidden = useResetStyles();\n state.assertive.className = mergeClasses(visuallyHidden, ariaLiveClassNames.assertive, state.assertive.className);\n state.polite.className = mergeClasses(visuallyHidden, ariaLiveClassNames.polite, state.polite.className);\n\n return state;\n};\n"],"names":["mergeClasses","makeResetStyles","ariaLiveClassNames","assertive","polite","useResetStyles","clip","height","margin","overflow","padding","width","position","useAriaLiveStyles_unstable","state","visuallyHidden","className"],"mappings":"AAAA;AAEA,SAASA,YAAY,EAAEC,eAAe,QAAQ,iBAAiB;AAI/D,OAAO,MAAMC,qBAAoD;IAC/DC,WAAW;IACXC,QAAQ;AACV,EAAE;AAEF;;CAEC,GACD,MAAMC,iBAAiBJ,gBAAgB;IACrCK,MAAM;IACNC,QAAQ;IACRC,QAAQ;IACRC,UAAU;IACVC,SAAS;IACTC,OAAO;IACPC,UAAU;AACZ;AAEA;;CAEC,GACD,OAAO,MAAMC,6BAA6B,CAACC;IACzC;IAEA,MAAMC,iBAAiBV;IACvBS,MAAMX,SAAS,CAACa,SAAS,GAAGhB,aAAae,gBAAgBb,mBAAmBC,SAAS,EAAEW,MAAMX,SAAS,CAACa,SAAS;IAChHF,MAAMV,MAAM,CAACY,SAAS,GAAGhB,aAAae,gBAAgBb,mBAAmBE,MAAM,EAAEU,MAAMV,MAAM,CAACY,SAAS;IAEvG,OAAOF;AACT,EAAE"}