From 3f4cd10e777495ec604f93f0c7c0b710a9524937 Mon Sep 17 00:00:00 2001 From: Lawrence Win Date: Thu, 21 Mar 2024 13:54:28 -0500 Subject: [PATCH 1/3] Allow passing view props into divider --- .../components/Divider/src/Divider.styling.ts | 21 +++++++++++-------- packages/components/Divider/src/Divider.tsx | 17 ++++++--------- .../components/Divider/src/Divider.types.ts | 4 ++-- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/packages/components/Divider/src/Divider.styling.ts b/packages/components/Divider/src/Divider.styling.ts index 0aa99048ff..9ca88c823c 100644 --- a/packages/components/Divider/src/Divider.styling.ts +++ b/packages/components/Divider/src/Divider.styling.ts @@ -2,7 +2,7 @@ import { useMemo } from 'react'; import type { ViewProps, ColorValue, StyleProp, ViewStyle } from 'react-native'; import { Platform } from 'react-native'; -import { memoize, mergeStyles } from '@fluentui-react-native/framework'; +import { memoize, mergeProps, mergeStyles } from '@fluentui-react-native/framework'; import type { Theme } from '@fluentui-react-native/framework'; import type { IconPropsV1 as IconProps } from '@fluentui-react-native/icon'; import type { TextProps } from '@fluentui-react-native/text'; @@ -174,23 +174,26 @@ export const colorsFromAppearance = ( * At the second render stage, if the minHeight token isn't set, we calculate and memoize a default value based on whether the * Divider is vertical and has content. */ -export const getRootStyle = memoize(getRootStyleWorker); -function getRootStyleWorker(rootStyle: StyleProp, isVertical: boolean, hasContent: boolean): StyleProp { +export const getRootSlotProps = memoize(rootSlotPropsWorker); +function rootSlotPropsWorker(dividerProps: DividerProps, rootProps: ViewProps, hasContent: boolean): ViewProps { + const { vertical, ...props } = dividerProps; let minHeight = 0; - if (isVertical) { + if (vertical) { minHeight = hasContent ? 84 : globalTokens.size200; } - return mergeStyles(rootStyle, { minHeight }); + return mergeProps(props, rootProps, { + style: mergeStyles(rootProps.style, props.style, { minHeight }), + }); } /** * At the second render stage, if there is not content passed, we override the existing beforeLine style to make the line take up * the entirity of root. */ -export const getBeforeLineStyle = memoize(getBeforeLineStyleWorker); -function getBeforeLineStyleWorker(beforeLineStyle: StyleProp, hasContent: boolean): StyleProp { +export const getBeforeLineSlotProps = memoize(beforeLineSlotPropsWorker); +function beforeLineSlotPropsWorker(beforeLineProps: ViewProps, hasContent: boolean) { if (!hasContent) { - return mergeStyles(beforeLineStyle, { flex: 1 }); + return mergeProps(beforeLineProps, { style: mergeStyles(beforeLineProps.style, { flex: 1 }) }); } - return beforeLineStyle; + return beforeLineProps; } diff --git a/packages/components/Divider/src/Divider.tsx b/packages/components/Divider/src/Divider.tsx index 962318ab07..4f4f8d3f09 100644 --- a/packages/components/Divider/src/Divider.tsx +++ b/packages/components/Divider/src/Divider.tsx @@ -5,14 +5,14 @@ import React from 'react'; import { View } from 'react-native'; import type { ViewProps } from 'react-native'; -import { withSlots, compressible, useSlot, useFluentTheme, patchTokens } from '@fluentui-react-native/framework'; +import { withSlots, compressible, useSlot, useFluentTheme, patchTokens, mergeProps } from '@fluentui-react-native/framework'; import type { UseTokens } from '@fluentui-react-native/framework'; import { IconV1 as Icon } from '@fluentui-react-native/icon'; import type { IconPropsV1 as IconProps } from '@fluentui-react-native/icon'; import { TextV1 as Text } from '@fluentui-react-native/text'; import type { TextProps } from '@fluentui-react-native/text'; -import { colorsFromAppearance, getBeforeLineStyle, getRootStyle, useDividerSlotProps } from './Divider.styling'; +import { colorsFromAppearance, getBeforeLineSlotProps, getRootSlotProps, useDividerSlotProps } from './Divider.styling'; import { dividerName } from './Divider.types'; import type { DividerProps, DividerTokens } from './Divider.types'; import { useDividerTokens } from './DividerTokens'; @@ -50,7 +50,7 @@ export const Divider = compressible((props: Divider const IconSlot = useSlot(Icon, iconProps); return (final: DividerProps, ...children: React.ReactNode[]) => { - final = { ...props, ...final }; + final = mergeProps(props, final); // change root style if there is a text child let textContent: string; React.Children.forEach(children, (child) => { @@ -61,14 +61,9 @@ export const Divider = compressible((props: Divider const hasContent = textContent !== undefined || props.icon !== undefined; - // This style must be set here because we need to know if text content is passed in the final render to set the height correctly - let finalRootProps = rootProps; - if (!tokens.minHeight) { - finalRootProps = { ...rootProps, style: getRootStyle(rootProps.style, final.vertical, hasContent) }; - } - - // We patch the beforeLine styling if no content is passed because it should always take up the full width / height of the root container (afterLine is not rendered). - const finalBeforeLineProps = { ...beforeLineProps, style: getBeforeLineStyle(beforeLineProps.style, hasContent) }; + // Patch styling / props of root and beforeLine slots if there's content + const finalRootProps = getRootSlotProps(final, rootProps, hasContent); + const finalBeforeLineProps = getBeforeLineSlotProps(beforeLineProps, hasContent); return ( diff --git a/packages/components/Divider/src/Divider.types.ts b/packages/components/Divider/src/Divider.types.ts index b367f022d3..cad7c72021 100644 --- a/packages/components/Divider/src/Divider.types.ts +++ b/packages/components/Divider/src/Divider.types.ts @@ -11,7 +11,7 @@ export type DividerInsetSize = (typeof DividerInsetSizes)[number]; export type DividerAlignment = 'start' | 'center' | 'end'; export type DividerAppearance = 'default' | 'subtle' | 'brand' | 'strong'; -export type DividerProps = React.PropsWithChildren<{ +export interface DividerProps extends ViewProps { /** * If a text or icon is passed, this dictates where content appears in the divider: at the start, centered, or towards the end. * @default 'center' @@ -41,7 +41,7 @@ export type DividerProps = React.PropsWithChildren<{ * Note: This prop is not supported on mobile platforms(Android & iOS). */ vertical?: boolean; -}>; +} export interface DividerTokens extends LayoutTokens, Omit { /** From 5df7386626666327a5306f651088ea70cb75694a Mon Sep 17 00:00:00 2001 From: Lawrence Win Date: Thu, 21 Mar 2024 14:42:33 -0500 Subject: [PATCH 2/3] Change files --- ...ative-divider-bba36b4e-1708-40ec-b633-f9154ad2f781.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@fluentui-react-native-divider-bba36b4e-1708-40ec-b633-f9154ad2f781.json diff --git a/change/@fluentui-react-native-divider-bba36b4e-1708-40ec-b633-f9154ad2f781.json b/change/@fluentui-react-native-divider-bba36b4e-1708-40ec-b633-f9154ad2f781.json new file mode 100644 index 0000000000..99a0d6047a --- /dev/null +++ b/change/@fluentui-react-native-divider-bba36b4e-1708-40ec-b633-f9154ad2f781.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "Enable passing view props into the Divider", + "packageName": "@fluentui-react-native/divider", + "email": "winlarry@microsoft.com", + "dependentChangeType": "patch" +} From 69bf5b78a0eb589703a70ad2d8e7183898d3fb87 Mon Sep 17 00:00:00 2001 From: Lawrence Win Date: Thu, 21 Mar 2024 15:27:02 -0500 Subject: [PATCH 3/3] Fix snapshots / type errors --- .../components/Divider/src/Divider.styling.ts | 2 +- .../Divider/src/__tests__/Divider.test.tsx | 5 -- .../__snapshots__/Divider.test.tsx.snap | 53 ++++++++++++++++++- 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/packages/components/Divider/src/Divider.styling.ts b/packages/components/Divider/src/Divider.styling.ts index 9ca88c823c..800a19b37d 100644 --- a/packages/components/Divider/src/Divider.styling.ts +++ b/packages/components/Divider/src/Divider.styling.ts @@ -1,5 +1,5 @@ import { useMemo } from 'react'; -import type { ViewProps, ColorValue, StyleProp, ViewStyle } from 'react-native'; +import type { ViewProps, ColorValue } from 'react-native'; import { Platform } from 'react-native'; import { memoize, mergeProps, mergeStyles } from '@fluentui-react-native/framework'; diff --git a/packages/components/Divider/src/__tests__/Divider.test.tsx b/packages/components/Divider/src/__tests__/Divider.test.tsx index b964801024..f8fab53302 100644 --- a/packages/components/Divider/src/__tests__/Divider.test.tsx +++ b/packages/components/Divider/src/__tests__/Divider.test.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; -import { checkReRender } from '@fluentui-react-native/test-tools'; import * as renderer from 'react-test-renderer'; import { Divider } from '../Divider'; @@ -95,8 +94,4 @@ describe('Divider component tests', () => { const tree = renderer.create(Hello).toJSON(); expect(tree).toMatchSnapshot(); }); - - it('Divider re-renders correctly', () => { - checkReRender(() => , 2); - }); }); diff --git a/packages/components/Divider/src/__tests__/__snapshots__/Divider.test.tsx.snap b/packages/components/Divider/src/__tests__/__snapshots__/Divider.test.tsx.snap index bca753fb65..d3cfda2363 100644 --- a/packages/components/Divider/src/__tests__/__snapshots__/Divider.test.tsx.snap +++ b/packages/components/Divider/src/__tests__/__snapshots__/Divider.test.tsx.snap @@ -2,6 +2,9 @@ exports[`Divider component tests Branded Divider 1`] = `