Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass props through to ToggleSwitch wrapper #3520

Merged
merged 4 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/empty-guests-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@primer/react': patch
---

passthrough dom props on toggleswitch

<!-- Changed components: ToggleSwitch -->
10 changes: 4 additions & 6 deletions src/ToggleSwitch/ToggleSwitch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@ import {CellAlignment} from '../DataTable/column'
const TRANSITION_DURATION = '80ms'
const EASE_OUT_QUAD_CURVE = 'cubic-bezier(0.5, 1, 0.89, 1)'

export type ToggleSwitchProps = {
/** The id of the DOM node that describes the switch */
['aria-describedby']?: string
/** The id of the DOM node that labels the switch */
['aria-labelledby']: string
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are included in html attributes

export interface ToggleSwitchProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'>, SxProp {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be narrowed a bit more, but I don't think we need to do that (and i kind of wish we used the dom onchange event type too, but oh well).

We could also use BoxProps here, but I don't think that gets us much since we're already explicitly passing through sx

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a TS perspective, is there a convention we could use to decide when to use interface with extends vs type with intersection? Was curious what your read on this was and if the change here highlights when to best use one over the other 👀

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's any clear guidance, and there aren't many cases where it matters. I think it's a bit clearer to read as an interface extension here instead of x & { ..... }.& y but entirely just a matter of perspective

/** Uncontrolled - whether the switch is turned on */
defaultChecked?: boolean
/** Whether the switch is ready for user input */
Expand All @@ -36,7 +32,7 @@ export type ToggleSwitchProps = {
* **This should only be changed when the switch's alignment needs to be adjusted.** For example: It needs to be left-aligned because the label appears above it and the caption appears below it.
*/
statusLabelPosition?: CellAlignment
} & SxProp
}

const sizeVariants = variant({
prop: 'size',
Expand Down Expand Up @@ -221,6 +217,7 @@ const ToggleSwitch: React.FC<React.PropsWithChildren<ToggleSwitchProps>> = ({
size = 'medium',
statusLabelPosition = 'start',
sx: sxProp,
...props
}) => {
const isControlled = typeof checked !== 'undefined'
const [isOn, setIsOn] = useProvidedStateOrCreate<boolean>(checked, onChange, Boolean(defaultChecked))
Expand All @@ -247,6 +244,7 @@ const ToggleSwitch: React.FC<React.PropsWithChildren<ToggleSwitchProps>> = ({
alignItems="center"
flexDirection={statusLabelPosition === 'start' ? 'row' : 'row-reverse'}
sx={sxProp}
{...props}
>
{loading ? <Spinner size="small" /> : null}
<Text
Expand Down
14 changes: 14 additions & 0 deletions src/__tests__/ToggleSwitch.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,19 @@ it('calls onChange when the switch is toggled', async () => {
await user.click(toggleSwitch)
expect(handleChange).toHaveBeenCalledWith(true)
})
it('can pass data attributes to the rendered component', async () => {
const TEST_ID = 'a test id'
const ControlledSwitchComponent = () => {
return (
<>
<div id="switchLabel">{SWITCH_LABEL_TEXT}</div>
<ToggleSwitch data-testid={TEST_ID} defaultChecked aria-labelledby="switchLabel" />
</>
)
}
const {getByTestId} = render(<ControlledSwitchComponent />)
const toggleSwitch = getByTestId(TEST_ID)
expect(toggleSwitch).toBeInTheDocument()
})

checkStoriesForAxeViolations('ToggleSwitch.features', '../ToggleSwitch/')