From 92906f55ce5c4e82654962f712d709757e263c15 Mon Sep 17 00:00:00 2001 From: "Lin Jiang (SHE/HER)" Date: Tue, 24 Oct 2023 11:18:23 +0800 Subject: [PATCH 1/3] add v9 shim for v8 checkbox --- .../src/components/Checkbox/CheckboxShim.tsx | 61 +++++++++++++ .../src/components/Checkbox/index.ts | 1 + .../components/Checkbox/shimCheckboxProps.ts | 86 +++++++++++++++++++ .../src/components/utils.ts | 10 +++ .../src/stories/CheckboxShim/Description.md | 1 + .../stories/CheckboxShim/index.stories.tsx | 62 +++++++++++++ 6 files changed, 221 insertions(+) create mode 100644 packages/react-components/react-migration-v8-v9/src/components/Checkbox/CheckboxShim.tsx create mode 100644 packages/react-components/react-migration-v8-v9/src/components/Checkbox/index.ts create mode 100644 packages/react-components/react-migration-v8-v9/src/components/Checkbox/shimCheckboxProps.ts create mode 100644 packages/react-components/react-migration-v8-v9/src/components/utils.ts create mode 100644 packages/react-components/react-migration-v8-v9/src/stories/CheckboxShim/Description.md create mode 100644 packages/react-components/react-migration-v8-v9/src/stories/CheckboxShim/index.stories.tsx diff --git a/packages/react-components/react-migration-v8-v9/src/components/Checkbox/CheckboxShim.tsx b/packages/react-components/react-migration-v8-v9/src/components/Checkbox/CheckboxShim.tsx new file mode 100644 index 00000000000000..55672d2efc1b0c --- /dev/null +++ b/packages/react-components/react-migration-v8-v9/src/components/Checkbox/CheckboxShim.tsx @@ -0,0 +1,61 @@ +import * as React from 'react'; +import { classNamesFunction, ICheckboxProps, ICheckboxStyles, ICheckboxStyleProps } from '@fluentui/react'; +import { Checkbox, makeStyles, mergeClasses } from '@fluentui/react-components'; +import { useControllableValue } from '@fluentui/react-hooks'; + +import { shimCheckboxProps } from './shimCheckboxProps'; + +const useCheckboxStyles = makeStyles({ + root: { + display: 'flex', + }, +}); + +const getClassNames = classNamesFunction({ + useStaticStyles: true, +}); + +export const CheckboxShim = (props: ICheckboxProps) => { + const { className, styles: stylesV8, onRenderLabel, label } = props; + const shimProps = shimCheckboxProps(props); + const styles = getClassNames(stylesV8); + const stylesV9 = useCheckboxStyles(); + const [isChecked, setIsChecked] = useControllableValue(props.checked, props.defaultChecked, props.onChange); + + const onChange = React.useCallback( + (event: React.ChangeEvent): void => { + setIsChecked(!isChecked, event); + }, + [setIsChecked, isChecked], + ); + + shimProps.checked = isChecked; + shimProps.onChange = onChange; + + const defaultLabelRendderer = (checkboxProps?: ICheckboxProps): JSX.Element | null => { + if (!checkboxProps) { + return null; + } + const { label, title } = checkboxProps; + return label ? ( + + {label} + + ) : null; + }; + + if (label || onRenderLabel) { + shimProps.label = { + className: mergeClasses('ms-Checkbox-text', styles.label, styles.text), + children: onRenderLabel ? onRenderLabel(props, defaultLabelRendderer) : label, + }; + } + + return ( + + ); +}; diff --git a/packages/react-components/react-migration-v8-v9/src/components/Checkbox/index.ts b/packages/react-components/react-migration-v8-v9/src/components/Checkbox/index.ts new file mode 100644 index 00000000000000..e0d1e00dc397b0 --- /dev/null +++ b/packages/react-components/react-migration-v8-v9/src/components/Checkbox/index.ts @@ -0,0 +1 @@ +export * from './CheckboxShim'; diff --git a/packages/react-components/react-migration-v8-v9/src/components/Checkbox/shimCheckboxProps.ts b/packages/react-components/react-migration-v8-v9/src/components/Checkbox/shimCheckboxProps.ts new file mode 100644 index 00000000000000..1f52678d65421d --- /dev/null +++ b/packages/react-components/react-migration-v8-v9/src/components/Checkbox/shimCheckboxProps.ts @@ -0,0 +1,86 @@ +import { ICheckboxProps } from '@fluentui/react'; +import { CheckboxOnChangeData, CheckboxProps } from '@fluentui/react-components'; + +import { getHTMLAttributes } from '../utils'; + +// https://react.fluentui.dev/?path=/docs/concepts-migration-from-v8-components-checkbox-migration--page +// https://github.com/microsoft/fluentui/blob/master/packages/react/src/components/Checkbox/Checkbox.types.ts +// https://github.com/microsoft/fluentui/blob/103b8977f8d5f8dd8c430bab46ff5308a2c76371/packages/react-components/react-checkbox/src/components/Checkbox/Checkbox.types.ts + +export const shimCheckboxProps = (props: ICheckboxProps): CheckboxProps => { + const { + ariaDescribedBy, + ariaLabel, + ariaLabelledBy, + ariaPositionInSet, + ariaSetSize, + boxSide, + checked, + componentRef, + defaultChecked, + defaultIndeterminate, + disabled, + indeterminate, + inputProps, + name, + onChange: onChangeV8, + required, + title, + } = props; + + const onChange = + onChangeV8 && + ((ev: React.ChangeEvent, data: CheckboxOnChangeData) => { + return onChangeV8(ev, data.checked as boolean); + }); + + const V9Props: Partial = { + ref: componentRef, + checked: checked || indeterminate, + defaultChecked: defaultChecked || defaultIndeterminate, + + labelPosition: boxSide === 'end' ? 'before' : 'after', + onChange, + } as Partial; + + return { + ...inputProps, // This inputProps is specific for the input element, and the html attributes are also used here instead of props. + 'aria-describedby': ariaDescribedBy, + 'aria-label': ariaLabel, + 'aria-labelledby': ariaLabelledBy, + 'aria-posinset': ariaPositionInSet, + 'aria-setsize': ariaSetSize, + disabled, + required, + title, + name, + ...V9Props, + ...getHTMLAttributes(props, CHECKBOX_PROPS_V8), + } as CheckboxProps; +}; + +const CHECKBOX_PROPS_V8: Set = new Set([ + 'ariaDescribedBy', + 'ariaLabel', + 'ariaLabelledBy', + 'ariaPositionInSet', + 'ariaSetSize', + 'boxSide', + 'checked', + 'checkmarkIconProps', // one case used this + 'className', + 'componentRef', + 'defaultChecked', + 'defaultIndeterminate', + 'disabled', + 'indeterminate', + 'inputProps', + 'label', + 'name', + 'onChange', + 'onRenderLabel', + 'required', + 'styles', + 'theme', + 'title', +]); diff --git a/packages/react-components/react-migration-v8-v9/src/components/utils.ts b/packages/react-components/react-migration-v8-v9/src/components/utils.ts new file mode 100644 index 00000000000000..3a30834f385cb3 --- /dev/null +++ b/packages/react-components/react-migration-v8-v9/src/components/utils.ts @@ -0,0 +1,10 @@ +export function getHTMLAttributes(props: T, allV8PropsSet: Set): T { + const v8Props: T = { ...props }; + const propsKeys: string[] = Object.keys(v8Props); + propsKeys.forEach(key => { + if (allV8PropsSet.has(key)) { + delete v8Props[key as keyof typeof v8Props]; + } + }); + return v8Props; +} diff --git a/packages/react-components/react-migration-v8-v9/src/stories/CheckboxShim/Description.md b/packages/react-components/react-migration-v8-v9/src/stories/CheckboxShim/Description.md new file mode 100644 index 00000000000000..43f27d7b172102 --- /dev/null +++ b/packages/react-components/react-migration-v8-v9/src/stories/CheckboxShim/Description.md @@ -0,0 +1 @@ +The CheckboxShim component accepts the same props as a v8 Checkbox and renders a v9 Checkbox. diff --git a/packages/react-components/react-migration-v8-v9/src/stories/CheckboxShim/index.stories.tsx b/packages/react-components/react-migration-v8-v9/src/stories/CheckboxShim/index.stories.tsx new file mode 100644 index 00000000000000..6eb2fedfb76f2f --- /dev/null +++ b/packages/react-components/react-migration-v8-v9/src/stories/CheckboxShim/index.stories.tsx @@ -0,0 +1,62 @@ +import * as React from 'react'; + +import descriptionMd from './Description.md'; + +import { Checkbox } from '@fluentui/react'; +import { + FluentProvider, + Checkbox as CheckboxV9, + webLightTheme, + makeStyles, + shorthands, +} from '@fluentui/react-components'; +import { CheckboxShim } from '../../components/Checkbox/index'; + +const useStyles = makeStyles({ + root: { + display: 'grid', + gridTemplateColumns: 'auto auto auto', + gridTemplateRows: '1fr', + width: 'fit-content', + alignContent: 'center', + alignItems: 'center', + justifyItems: 'center', + columnGap: '10px', + rowGap: '10px', + }, + componentName: { + justifySelf: 'end', + ...shorthands.margin(0, '10px', 0, 0), + }, +}); + +export const Default = () => { + const styles = useStyles(); + + return ( +
+

v8

+

shim

+

v9

+ + + + + + + +
+ ); +}; + +export default { + title: 'Migration Shims/V8/CheckboxShim', + component: CheckboxShim, + parameters: { + docs: { + description: { + component: [descriptionMd].join('\n'), + }, + }, + }, +}; From 3b80c97316dbfebd0f3d0514b4142bf9868dbdf3 Mon Sep 17 00:00:00 2001 From: "Lin Jiang (SHE/HER)" Date: Tue, 24 Oct 2023 11:20:10 +0800 Subject: [PATCH 2/3] add change file --- ...gration-v8-v9-cf095a00-1a81-4b03-ba8f-f7456356393f.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@fluentui-react-migration-v8-v9-cf095a00-1a81-4b03-ba8f-f7456356393f.json diff --git a/change/@fluentui-react-migration-v8-v9-cf095a00-1a81-4b03-ba8f-f7456356393f.json b/change/@fluentui-react-migration-v8-v9-cf095a00-1a81-4b03-ba8f-f7456356393f.json new file mode 100644 index 00000000000000..3cf75aa95298fc --- /dev/null +++ b/change/@fluentui-react-migration-v8-v9-cf095a00-1a81-4b03-ba8f-f7456356393f.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "Add v9 shim for v8 checkbox", + "packageName": "@fluentui/react-migration-v8-v9", + "email": "jianlin@microsoft.com", + "dependentChangeType": "patch" +} From 31c5db26c9a7fa9db7e89e8ceda5be3286e29d7f Mon Sep 17 00:00:00 2001 From: "Lin Jiang (SHE/HER)" Date: Tue, 24 Oct 2023 15:35:17 +0800 Subject: [PATCH 3/3] Remove the local FluentProvider --- .../src/stories/CheckboxShim/index.stories.tsx | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/packages/react-components/react-migration-v8-v9/src/stories/CheckboxShim/index.stories.tsx b/packages/react-components/react-migration-v8-v9/src/stories/CheckboxShim/index.stories.tsx index 6eb2fedfb76f2f..977e4d719062dd 100644 --- a/packages/react-components/react-migration-v8-v9/src/stories/CheckboxShim/index.stories.tsx +++ b/packages/react-components/react-migration-v8-v9/src/stories/CheckboxShim/index.stories.tsx @@ -3,13 +3,7 @@ import * as React from 'react'; import descriptionMd from './Description.md'; import { Checkbox } from '@fluentui/react'; -import { - FluentProvider, - Checkbox as CheckboxV9, - webLightTheme, - makeStyles, - shorthands, -} from '@fluentui/react-components'; +import { Checkbox as CheckboxV9, makeStyles, shorthands } from '@fluentui/react-components'; import { CheckboxShim } from '../../components/Checkbox/index'; const useStyles = makeStyles({ @@ -39,12 +33,8 @@ export const Default = () => {

shim

v9

- - - - - - + + ); };