From 4eacf7b83b40bcb8fc350ed3c28aef58d1fb6d85 Mon Sep 17 00:00:00 2001 From: vicky-comeau Date: Mon, 4 Nov 2024 14:17:57 -0500 Subject: [PATCH] [DS-432] Added description prop to Switch --- .changeset/pink-weeks-decide.md | 5 ++ .../src/switch/docs/SwitchField.stories.tsx | 9 +-- .../src/switch/docs/switchfield/disabled.tsx | 5 +- .../src/switch/docs/switchfield/sizes.tsx | 8 +-- .../components/src/switch/src/SwitchField.tsx | 37 +++++++----- .../tests/chromatic/SwitchField.stories.tsx | 56 ++++++++----------- .../switch/tests/jest/SwitchField.test.tsx | 50 ++++++++--------- 7 files changed, 84 insertions(+), 86 deletions(-) create mode 100644 .changeset/pink-weeks-decide.md diff --git a/.changeset/pink-weeks-decide.md b/.changeset/pink-weeks-decide.md new file mode 100644 index 000000000..1558fa7c0 --- /dev/null +++ b/.changeset/pink-weeks-decide.md @@ -0,0 +1,5 @@ +--- +"@hopper-ui/components": patch +--- + +Added a `description` prop to SwitchField and removed the description slot. diff --git a/packages/components/src/switch/docs/SwitchField.stories.tsx b/packages/components/src/switch/docs/SwitchField.stories.tsx index 044661306..a468251ed 100644 --- a/packages/components/src/switch/docs/SwitchField.stories.tsx +++ b/packages/components/src/switch/docs/SwitchField.stories.tsx @@ -46,11 +46,10 @@ export const Default: Story = { */ export const Description: Story = { render: props => ( - + Option 1 - Description ) }; @@ -71,17 +70,15 @@ export const Disabled: Story = { export const Sizes: Story = { render: props => ( - + Option 1 - Description - + Option 1 - Description ) diff --git a/packages/components/src/switch/docs/switchfield/disabled.tsx b/packages/components/src/switch/docs/switchfield/disabled.tsx index 78f3f2a62..e68caf6dc 100644 --- a/packages/components/src/switch/docs/switchfield/disabled.tsx +++ b/packages/components/src/switch/docs/switchfield/disabled.tsx @@ -1,10 +1,9 @@ -import { Switch, SwitchField, Text } from "@hopper-ui/components"; +import { Switch, SwitchField } from "@hopper-ui/components"; export default function Example() { return ( - + Save - This will override your changes. ); } diff --git a/packages/components/src/switch/docs/switchfield/sizes.tsx b/packages/components/src/switch/docs/switchfield/sizes.tsx index 5bad48fe5..b6070e21a 100644 --- a/packages/components/src/switch/docs/switchfield/sizes.tsx +++ b/packages/components/src/switch/docs/switchfield/sizes.tsx @@ -1,15 +1,13 @@ -import { Inline, Switch, SwitchField, Text } from "@hopper-ui/components"; +import { Inline, Switch, SwitchField } from "@hopper-ui/components"; export default function Example() { return ( - + Save - This will override your changes. - + Save - This will override your changes. ); diff --git a/packages/components/src/switch/src/SwitchField.tsx b/packages/components/src/switch/src/SwitchField.tsx index 4ced4315d..6497377da 100644 --- a/packages/components/src/switch/src/SwitchField.tsx +++ b/packages/components/src/switch/src/SwitchField.tsx @@ -4,11 +4,12 @@ import { type ResponsiveProp, type StyledSystemProps } from "@hopper-ui/styled-system"; -import { forwardRef, type ForwardedRef } from "react"; -import { mergeProps, useId } from "react-aria"; +import { useSlotId } from "@react-aria/utils"; +import { forwardRef, type ForwardedRef, type ReactNode } from "react"; +import { mergeProps } from "react-aria"; import { composeRenderProps, useContextProps } from "react-aria-components"; -import { TextContext, type TextSize } from "../../typography/Text/index.ts"; +import { Text, type TextSize } from "../../typography/Text/index.ts"; import { composeClassnameRenderProps, cssModule, SlotProvider, useRenderProps, type AccessibleSlotProps, type FieldSize, type RenderProps, type SizeAdapter } from "../../utils/index.ts"; import { SwitchContext } from "./SwitchContext.ts"; @@ -32,14 +33,18 @@ interface SwitchFieldRenderProps { export interface SwitchFieldProps extends RenderProps, StyledSystemProps, AccessibleSlotProps { /** - * A switch field can vary in size. - * @default "md" + * The description of the switch field. */ - size?: ResponsiveProp; + description?: ReactNode; /** * Whether the switch field is disabled. */ isDisabled?: boolean; + /** + * A switch field can vary in size. + * @default "md" + */ + size?: ResponsiveProp; } function SwitchField(props: SwitchFieldProps, ref: ForwardedRef) { @@ -49,16 +54,17 @@ function SwitchField(props: SwitchFieldProps, ref: ForwardedRef) const { className, - style, + description, isDisabled, size: sizeProp = "md", slot, + style, ...otherProps } = ownProps; const size = useResponsiveValue(sizeProp) ?? "md"; - const descriptionId = useId(); + const descriptionId = useSlotId([Boolean(description)]); const classNames = composeClassnameRenderProps( className, @@ -90,11 +96,6 @@ function SwitchField(props: SwitchFieldProps, ref: ForwardedRef) return ( ) {...mergeProps(renderProps, otherProps)} > {renderProps.children} + {description && ( + + {description} + + )} ); diff --git a/packages/components/src/switch/tests/chromatic/SwitchField.stories.tsx b/packages/components/src/switch/tests/chromatic/SwitchField.stories.tsx index 2a7d7af0f..c98cd0921 100644 --- a/packages/components/src/switch/tests/chromatic/SwitchField.stories.tsx +++ b/packages/components/src/switch/tests/chromatic/SwitchField.stories.tsx @@ -1,7 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Inline, Stack } from "../../../layout/index.ts"; -import { Text } from "../../../typography/Text/index.ts"; import { Switch } from "../../src/Switch.tsx"; import { SwitchField } from "../../src/SwitchField.tsx"; @@ -17,17 +16,15 @@ type Story = StoryObj; export const Default: Story = { render: props => ( - + - Option 1 + Option 1 - Description - + - Option 1 + Option 1 - Description ) @@ -36,17 +33,15 @@ export const Default: Story = { export const Disabled: Story = { render: props => ( - + - Option 1 + Option 1 - Description - + - Option 1 + Option 1 - Description ) @@ -56,31 +51,27 @@ export const Zoom: Story = { render: props => ( - + - Option 1 + Option 1 - Description - + - Option 1 + Option 1 - Description - + - Option 1 + Option 1 - Description - + - Option 1 + Option 1 - Description @@ -90,14 +81,11 @@ export const Zoom: Story = { export const AccessToDisabledState: Story = { render: props => ( - + {({ isDisabled }) => ( - <> - - Should be true - - Is disabled: {String(isDisabled)} - + + Is disabled: {String(isDisabled)} + )} isDisabled ? { border: "1px solid red" } : {}} + description="Border should be red" > - Disable and red border + Disable and red border - Border should be red ) diff --git a/packages/components/src/switch/tests/jest/SwitchField.test.tsx b/packages/components/src/switch/tests/jest/SwitchField.test.tsx index baf4549d7..da485e27d 100644 --- a/packages/components/src/switch/tests/jest/SwitchField.test.tsx +++ b/packages/components/src/switch/tests/jest/SwitchField.test.tsx @@ -3,7 +3,6 @@ import { render, screen } from "@hopper-ui/test-utils"; import { createRef } from "react"; -import { Text } from "../../../typography/Text/src/Text.tsx"; import { Switch } from "../../src/Switch.tsx"; import { SwitchField } from "../../src/SwitchField.tsx"; import { SwitchFieldContext } from "../../src/SwitchFieldContext.ts"; @@ -13,18 +12,18 @@ describe("Switch", () => { const testId = "switch-field"; it("should render with default class", () => { - render(option 1description); + render( + option 1 + ); const element = screen.getByTestId(testId); expect(element).toHaveClass("hop-SwitchField"); }); it("should support custom class", () => { - render(option 1description); + render( + option 1 + ); const element = screen.getByTestId(testId); expect(element).toHaveClass("hop-SwitchField"); @@ -32,17 +31,18 @@ describe("Switch", () => { }); it("should support custom style", () => { - render(option - 1description); + render( + option 1 + ); const element = screen.getByTestId(testId); expect(element).toHaveStyle({ marginTop: "var(--hop-space-stack-sm)", marginBottom: "13px" }); }); it("should support DOM props", () => { - render(option 1description); + render( + option 1 + ); const element = screen.getByTestId(testId); expect(element).toHaveAttribute("data-foo", "bar"); @@ -51,9 +51,9 @@ describe("Switch", () => { it("should support slots", () => { render( - option 1description + + option 1 + ); @@ -65,18 +65,18 @@ describe("Switch", () => { it("should support refs", () => { const ref = createRef(); - render(option 1description); + render( + option 1 + ); expect(ref.current).not.toBeNull(); expect(ref.current instanceof HTMLDivElement).toBeTruthy(); }); it("should set the size class name and pass the size to the switch", () => { - render(option 1description); + render( + option 1 + ); const element = screen.getByTestId(testId); const switchElem = screen.getByRole("switch").closest("label"); @@ -85,9 +85,9 @@ describe("Switch", () => { }); it("should set an id on the description and aria-describedby on the switch", () => { - render(option 1description); + render( + option 1 + ); const switchElem = screen.getByRole("switch"); const descriptionElement = screen.getByText("description"); @@ -103,9 +103,9 @@ describe("Switch", () => { data-testid={testId} isDisabled className={({ isDisabled }) => (isDisabled ? "disabled" : "")} + description="description" > option 1 - description ); const element = screen.getByTestId(testId);