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,2 @@
export { useDisableBodyScroll } from './useDisableBodyScroll';
export { useFocusFirstElement } from './useFocusFirstElement';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/index.ts"],"sourcesContent":["export { useDisableBodyScroll } from './useDisableBodyScroll';\nexport { useFocusFirstElement } from './useFocusFirstElement';\n"],"names":["useDisableBodyScroll","useFocusFirstElement"],"mappings":"AAAA,SAASA,oBAAoB,QAAQ,yBAAyB;AAC9D,SAASC,oBAAoB,QAAQ,yBAAyB"}

View File

@@ -0,0 +1,48 @@
'use client';
import * as React from 'react';
import { useFluent_unstable } from '@fluentui/react-shared-contexts';
import { useBodyNoScrollStyles, useHTMLNoScrollStyles } from './useDisableBodyScroll.styles';
/**
* A React *hook* that disables body scrolling through `overflowY: hidden` CSS property
*
* @internal
*/ export function useDisableBodyScroll() {
const htmlNoScrollStyles = useHTMLNoScrollStyles();
const bodyNoScrollStyles = useBodyNoScrollStyles();
const { targetDocument } = useFluent_unstable();
const disableBodyScroll = React.useCallback(()=>{
var _targetDocument_defaultView;
if (!targetDocument) {
return;
}
var _targetDocument_defaultView_innerHeight;
const isHorizontalScrollbarVisible = // When the window is a fractional height, `innerHeight` always rounds down but `clientHeight` rounds either up or down depending on the value.
// To properly compare the body clientHeight to the window innerHeight, manually round down the fractional value to match innerHeight's calculation.
Math.floor(targetDocument.body.getBoundingClientRect().height) > ((_targetDocument_defaultView_innerHeight = (_targetDocument_defaultView = targetDocument.defaultView) === null || _targetDocument_defaultView === void 0 ? void 0 : _targetDocument_defaultView.innerHeight) !== null && _targetDocument_defaultView_innerHeight !== void 0 ? _targetDocument_defaultView_innerHeight : 0);
if (!isHorizontalScrollbarVisible) {
return;
}
targetDocument.documentElement.classList.add(htmlNoScrollStyles);
targetDocument.body.classList.add(bodyNoScrollStyles);
return;
}, [
targetDocument,
htmlNoScrollStyles,
bodyNoScrollStyles
]);
const enableBodyScroll = React.useCallback(()=>{
if (!targetDocument) {
return;
}
targetDocument.documentElement.classList.remove(htmlNoScrollStyles);
targetDocument.body.classList.remove(bodyNoScrollStyles);
}, [
targetDocument,
htmlNoScrollStyles,
bodyNoScrollStyles
]);
return {
disableBodyScroll,
enableBodyScroll
};
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/useDisableBodyScroll.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useFluent_unstable } from '@fluentui/react-shared-contexts';\n\nimport { useBodyNoScrollStyles, useHTMLNoScrollStyles } from './useDisableBodyScroll.styles';\n\n/**\n * A React *hook* that disables body scrolling through `overflowY: hidden` CSS property\n *\n * @internal\n */\nexport function useDisableBodyScroll(): {\n disableBodyScroll: () => void;\n enableBodyScroll: () => void;\n} {\n const htmlNoScrollStyles = useHTMLNoScrollStyles();\n const bodyNoScrollStyles = useBodyNoScrollStyles();\n const { targetDocument } = useFluent_unstable();\n\n const disableBodyScroll = React.useCallback(() => {\n if (!targetDocument) {\n return;\n }\n const isHorizontalScrollbarVisible =\n // When the window is a fractional height, `innerHeight` always rounds down but `clientHeight` rounds either up or down depending on the value.\n // To properly compare the body clientHeight to the window innerHeight, manually round down the fractional value to match innerHeight's calculation.\n Math.floor(targetDocument.body.getBoundingClientRect().height) > (targetDocument.defaultView?.innerHeight ?? 0);\n if (!isHorizontalScrollbarVisible) {\n return;\n }\n targetDocument.documentElement.classList.add(htmlNoScrollStyles);\n targetDocument.body.classList.add(bodyNoScrollStyles);\n return;\n }, [targetDocument, htmlNoScrollStyles, bodyNoScrollStyles]);\n\n const enableBodyScroll = React.useCallback(() => {\n if (!targetDocument) {\n return;\n }\n targetDocument.documentElement.classList.remove(htmlNoScrollStyles);\n targetDocument.body.classList.remove(bodyNoScrollStyles);\n }, [targetDocument, htmlNoScrollStyles, bodyNoScrollStyles]);\n\n return {\n disableBodyScroll,\n enableBodyScroll,\n };\n}\n"],"names":["React","useFluent_unstable","useBodyNoScrollStyles","useHTMLNoScrollStyles","useDisableBodyScroll","htmlNoScrollStyles","bodyNoScrollStyles","targetDocument","disableBodyScroll","useCallback","isHorizontalScrollbarVisible","Math","floor","body","getBoundingClientRect","height","defaultView","innerHeight","documentElement","classList","add","enableBodyScroll","remove"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,kBAAkB,QAAQ,kCAAkC;AAErE,SAASC,qBAAqB,EAAEC,qBAAqB,QAAQ,gCAAgC;AAE7F;;;;CAIC,GACD,OAAO,SAASC;IAId,MAAMC,qBAAqBF;IAC3B,MAAMG,qBAAqBJ;IAC3B,MAAM,EAAEK,cAAc,EAAE,GAAGN;IAE3B,MAAMO,oBAAoBR,MAAMS,WAAW,CAAC;YAO0BF;QANpE,IAAI,CAACA,gBAAgB;YACnB;QACF;YAIoEA;QAHpE,MAAMG,+BACJ,+IAA+I;QAC/I,oJAAoJ;QACpJC,KAAKC,KAAK,CAACL,eAAeM,IAAI,CAACC,qBAAqB,GAAGC,MAAM,IAAKR,CAAAA,CAAAA,2CAAAA,8BAAAA,eAAeS,WAAW,cAA1BT,kDAAAA,4BAA4BU,WAAW,cAAvCV,qDAAAA,0CAA2C,CAAA;QAC/G,IAAI,CAACG,8BAA8B;YACjC;QACF;QACAH,eAAeW,eAAe,CAACC,SAAS,CAACC,GAAG,CAACf;QAC7CE,eAAeM,IAAI,CAACM,SAAS,CAACC,GAAG,CAACd;QAClC;IACF,GAAG;QAACC;QAAgBF;QAAoBC;KAAmB;IAE3D,MAAMe,mBAAmBrB,MAAMS,WAAW,CAAC;QACzC,IAAI,CAACF,gBAAgB;YACnB;QACF;QACAA,eAAeW,eAAe,CAACC,SAAS,CAACG,MAAM,CAACjB;QAChDE,eAAeM,IAAI,CAACM,SAAS,CAACG,MAAM,CAAChB;IACvC,GAAG;QAACC;QAAgBF;QAAoBC;KAAmB;IAE3D,OAAO;QACLE;QACAa;IACF;AACF"}

View File

@@ -0,0 +1,6 @@
'use client';
import { __resetStyles } from '@griffel/react';
// this style must be applied to the html element to disable scrolling
export const useHTMLNoScrollStyles = /*#__PURE__*/__resetStyles("r6pzz3z", null, [".r6pzz3z{overflow-y:hidden;overflow-y:clip;scrollbar-gutter:stable;}"]);
export const useBodyNoScrollStyles = /*#__PURE__*/__resetStyles("r144vlu9", null, [".r144vlu9{overflow-y:hidden;}"]);

View File

@@ -0,0 +1 @@
{"version":3,"names":["__resetStyles","useHTMLNoScrollStyles","useBodyNoScrollStyles"],"sources":["useDisableBodyScroll.styles.js"],"sourcesContent":["'use client';\nimport { makeResetStyles } from '@griffel/react';\n// this style must be applied to the html element to disable scrolling\nexport const useHTMLNoScrollStyles = makeResetStyles({\n overflowY: [\n 'hidden',\n 'clip'\n ],\n scrollbarGutter: 'stable'\n});\nexport const useBodyNoScrollStyles = makeResetStyles({\n overflowY: 'hidden'\n});\n"],"mappings":"AAAA,YAAY;;AACZ,SAAAA,aAAA,QAAgC,gBAAgB;AAChD;AACA,OAAO,MAAMC,qBAAqB,gBAAGD,aAAA,0FAMpC,CAAC;AACF,OAAO,MAAME,qBAAqB,gBAAGF,aAAA,oDAEpC,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,13 @@
'use client';
import { makeResetStyles } from '@griffel/react';
// this style must be applied to the html element to disable scrolling
export const useHTMLNoScrollStyles = makeResetStyles({
overflowY: [
'hidden',
'clip'
],
scrollbarGutter: 'stable'
});
export const useBodyNoScrollStyles = makeResetStyles({
overflowY: 'hidden'
});

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/useDisableBodyScroll.styles.ts"],"sourcesContent":["'use client';\n\nimport { makeResetStyles } from '@griffel/react';\n\n// this style must be applied to the html element to disable scrolling\nexport const useHTMLNoScrollStyles = makeResetStyles({\n overflowY: ['hidden', 'clip'],\n scrollbarGutter: 'stable',\n});\n\nexport const useBodyNoScrollStyles = makeResetStyles({\n overflowY: 'hidden',\n});\n"],"names":["makeResetStyles","useHTMLNoScrollStyles","overflowY","scrollbarGutter","useBodyNoScrollStyles"],"mappings":"AAAA;AAEA,SAASA,eAAe,QAAQ,iBAAiB;AAEjD,sEAAsE;AACtE,OAAO,MAAMC,wBAAwBD,gBAAgB;IACnDE,WAAW;QAAC;QAAU;KAAO;IAC7BC,iBAAiB;AACnB,GAAG;AAEH,OAAO,MAAMC,wBAAwBJ,gBAAgB;IACnDE,WAAW;AACb,GAAG"}

View File

@@ -0,0 +1,35 @@
'use client';
import * as React from 'react';
import { useFocusFinders } from '@fluentui/react-tabster';
import { useFluent_unstable } from '@fluentui/react-shared-contexts';
/**
* Focus first element on content when dialog is opened,
*/ export function useFocusFirstElement(open, modalType) {
const { findFirstFocusable } = useFocusFinders();
const { targetDocument } = useFluent_unstable();
const dialogRef = React.useRef(null);
React.useEffect(()=>{
if (!open) {
return;
}
const element = dialogRef.current && findFirstFocusable(dialogRef.current);
if (element) {
element.focus();
} else {
var _dialogRef_current;
(_dialogRef_current = dialogRef.current) === null || _dialogRef_current === void 0 ? void 0 : _dialogRef_current.focus(); // https://github.com/microsoft/fluentui/issues/25150
if (process.env.NODE_ENV === 'development') {
// eslint-disable-next-line no-console
console.warn(`@fluentui/react-dialog [useFocusFirstElement]:
A Dialog should have at least one focusable element inside DialogSurface.
Please add at least a close button either on \`DialogTitle\` action slot or inside \`DialogActions\``);
}
}
}, [
findFirstFocusable,
open,
modalType,
targetDocument
]);
return dialogRef;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/useFocusFirstElement.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useFocusFinders } from '@fluentui/react-tabster';\nimport { useFluent_unstable } from '@fluentui/react-shared-contexts';\nimport type { DialogSurfaceElement } from '../DialogSurface';\nimport type { DialogModalType } from '../Dialog';\n\n/**\n * Focus first element on content when dialog is opened,\n */\nexport function useFocusFirstElement(\n open: boolean,\n modalType: DialogModalType,\n): React.RefObject<DialogSurfaceElement | null> {\n const { findFirstFocusable } = useFocusFinders();\n const { targetDocument } = useFluent_unstable();\n const dialogRef = React.useRef<DialogSurfaceElement | null>(null);\n\n React.useEffect(() => {\n if (!open) {\n return;\n }\n const element = dialogRef.current && findFirstFocusable(dialogRef.current);\n if (element) {\n element.focus();\n } else {\n dialogRef.current?.focus(); // https://github.com/microsoft/fluentui/issues/25150\n if (process.env.NODE_ENV === 'development') {\n // eslint-disable-next-line no-console\n console.warn(/** #__DE-INDENT__ */ `\n @fluentui/react-dialog [useFocusFirstElement]:\n A Dialog should have at least one focusable element inside DialogSurface.\n Please add at least a close button either on \\`DialogTitle\\` action slot or inside \\`DialogActions\\`\n `);\n }\n }\n }, [findFirstFocusable, open, modalType, targetDocument]);\n\n return dialogRef;\n}\n"],"names":["React","useFocusFinders","useFluent_unstable","useFocusFirstElement","open","modalType","findFirstFocusable","targetDocument","dialogRef","useRef","useEffect","element","current","focus","process","env","NODE_ENV","console","warn"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,eAAe,QAAQ,0BAA0B;AAC1D,SAASC,kBAAkB,QAAQ,kCAAkC;AAIrE;;CAEC,GACD,OAAO,SAASC,qBACdC,IAAa,EACbC,SAA0B;IAE1B,MAAM,EAAEC,kBAAkB,EAAE,GAAGL;IAC/B,MAAM,EAAEM,cAAc,EAAE,GAAGL;IAC3B,MAAMM,YAAYR,MAAMS,MAAM,CAA8B;IAE5DT,MAAMU,SAAS,CAAC;QACd,IAAI,CAACN,MAAM;YACT;QACF;QACA,MAAMO,UAAUH,UAAUI,OAAO,IAAIN,mBAAmBE,UAAUI,OAAO;QACzE,IAAID,SAAS;YACXA,QAAQE,KAAK;QACf,OAAO;gBACLL;aAAAA,qBAAAA,UAAUI,OAAO,cAAjBJ,yCAAAA,mBAAmBK,KAAK,IAAI,qDAAqD;YACjF,IAAIC,QAAQC,GAAG,CAACC,QAAQ,KAAK,eAAe;gBAC1C,sCAAsC;gBACtCC,QAAQC,IAAI,CAAuB,CAAC;;oGAIpC,CAAC;YACH;QACF;IACF,GAAG;QAACZ;QAAoBF;QAAMC;QAAWE;KAAe;IAExD,OAAOC;AACT"}