Skip to content

Commit

Permalink
Add support for overriding id (#158)
Browse files Browse the repository at this point in the history
Co-authored-by: Rogin Farrer <rfarrer@wayfair.com>
  • Loading branch information
roginfarrer and Rogin Farrer committed Oct 16, 2023
1 parent 8979004 commit 3c86a81
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 23 deletions.
5 changes: 5 additions & 0 deletions .changeset/small-pianos-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'react-collapsed': minor
---

Added support for overriding `id`.
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist
node_modules
4 changes: 2 additions & 2 deletions packages/react-collapsed/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}
}
1 change: 1 addition & 0 deletions packages/react-collapsed/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ The following are optional properties passed into `useCollapse({ })`:
| duration | number | `undefined` | The duration of the animation in milliseconds. By default, the duration is programmatically calculated based on the height of the collapsed element |
| onTransitionStateChange | function | no-op | Handler called with at each stage of the transition animation |
| hasDisabledAnimation | boolean | false | If true, will disable the animation |
| id | string \| number | `undefined` | Unique identifier used to for associating elements appropriately for accessibility. |

### What you get

Expand Down
28 changes: 17 additions & 11 deletions packages/react-collapsed/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export interface UseCollapseInput {
| 'collapseEnd'
| 'collapsing'
) => void
/**
* Unique identifier used to for associating elements appropriately for accessibility.
*/
id?: string | number;
}

export function useCollapse({
Expand All @@ -74,10 +78,11 @@ export function useCollapse({
isExpanded: configIsExpanded,
defaultExpanded = false,
hasDisabledAnimation,
id,
...initialConfig
}: UseCollapseInput = {}) {
const onTransitionStateChange = useEvent(propOnTransitionStateChange)
const uniqueId = useId()
const uniqueId = useId(id ? `${id}` : undefined)

const [isExpanded, setExpanded] = useControlledState(
configIsExpanded,
Expand Down Expand Up @@ -220,7 +225,7 @@ export function useCollapse({
},
RefKey extends string | undefined = 'ref'
>(
rest?: Args & {
args?: Args & {
/**
* Sets the key of the prop that the component uses for ref assignment
* @default 'ref'
Expand All @@ -238,16 +243,16 @@ export function useCollapse({
role?: 'button'
tabIndex?: number
} {
const { disabled, onClick, refKey } = {
const { disabled, onClick, refKey, ...rest } = {
refKey: 'ref',
onClick() {},
disabled: false,
...rest,
...args,
}

const isButton = toggleEl ? toggleEl.tagName === 'BUTTON' : undefined

const theirRef: any = rest?.[refKey || 'ref']
const theirRef: any = args?.[refKey || 'ref']

const props: any = {
id: `react-collapsed-toggle-${uniqueId}`,
Expand All @@ -272,14 +277,15 @@ export function useCollapse({
}

if (isButton === false) {
return { ...props, ...fakeButtonProps }
return { ...props, ...fakeButtonProps, ...rest }
} else if (isButton === true) {
return { ...props, ...buttonProps }
return { ...props, ...buttonProps, ...rest }
} else {
return {
...props,
...buttonProps,
...fakeButtonProps,
...rest
}
}
},
Expand All @@ -288,7 +294,7 @@ export function useCollapse({
Args extends { style?: CSSProperties; [k: string]: unknown },
RefKey extends string | undefined = 'ref'
>(
rest?: Args & {
args?: Args & {
/**
* Sets the key of the prop that the component uses for ref assignment
* @default 'ref'
Expand All @@ -303,13 +309,13 @@ export function useCollapse({
role: string
style: CSSProperties
} {
const { style, refKey } = { refKey: 'ref', style: {}, ...rest }
const theirRef: any = rest?.[refKey || 'ref']
const { style, refKey } = { refKey: 'ref', style: {}, ...args }
const theirRef: any = args?.[refKey || 'ref']
return {
id: `react-collapsed-panel-${uniqueId}`,
'aria-hidden': !isExpanded,
role: 'region',
...rest,
...args,
[refKey || 'ref']: mergeRefs(collapseElRef, theirRef),
style: {
boxSizing: 'border-box',
Expand Down
14 changes: 14 additions & 0 deletions packages/react-collapsed/tests/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,17 @@ test('permits access to the collapse ref', () => {
const { queryByTestId } = render(<Collapse collapseProps={{ ref: cb }} />)
expect(cb).toHaveBeenCalledWith(queryByTestId('collapse'))
})

test('id argument modifies all rendered elements', () => {
const {container} = render(<Collapse id="foo" />)
expect(container.querySelector('#react-collapsed-toggle-foo')).toBeInTheDocument()
expect(container.querySelector('#react-collapsed-panel-foo')).toBeInTheDocument()
})

test('id will be overridden by prop getters', () => {
const {container} = render(<Collapse id="foo" collapseProps={{id: 'bar'}} toggleProps={{id: 'baz'}} />)
expect(container.querySelector('#react-collapsed-toggle-foo')).not.toBeInTheDocument()
expect(container.querySelector('#react-collapsed-panel-foo')).not.toBeInTheDocument()
expect(container.querySelector('#baz')).toBeInTheDocument()
expect(container.querySelector('#bar')).toBeInTheDocument()
})
13 changes: 5 additions & 8 deletions packages/react/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.@(js|jsx|ts|tsx)"
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-a11y',
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-a11y"
]
}
4 changes: 2 additions & 2 deletions packages/react/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}
}

0 comments on commit 3c86a81

Please sign in to comment.