Skip to content

Commit a6b1512

Browse files
authored
add defaultOpen prop to Disclosure component (#447)
* add defaultOpen prop to Disclosure component * update changelog
1 parent 43d5270 commit a6b1512

File tree

5 files changed

+59
-6
lines changed

5 files changed

+59
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616
### Added
1717

1818
- Add `disabled` prop to `RadioGroup` and `RadioGroup.Option` ([#401](https://github.com/tailwindlabs/headlessui/pull/401))
19+
- Add `defaultOpen` prop to the `Disclosure` component ([#447](https://github.com/tailwindlabs/headlessui/pull/447))
1920

2021
## [Unreleased - Vue]
2122

@@ -29,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2930
### Added
3031

3132
- Add `disabled` prop to `RadioGroup` and `RadioGroupOption` ([#401](https://github.com/tailwindlabs/headlessui/pull/401))
33+
- Add `defaultOpen` prop to the `Disclosure` component ([#447](https://github.com/tailwindlabs/headlessui/pull/447))
3234

3335
## [@headlessui/react@v1.0.0] - 2021-04-14
3436

packages/@headlessui-react/src/components/disclosure/disclosure.test.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,29 @@ describe('Rendering', () => {
7979
assertDisclosurePanel({ state: DisclosureState.Visible, textContent: 'Panel is: open' })
8080
})
8181
)
82+
83+
it('should be possible to render a Disclosure in an open state by default', async () => {
84+
render(
85+
<Disclosure defaultOpen>
86+
{({ open }) => (
87+
<>
88+
<Disclosure.Button>Trigger</Disclosure.Button>
89+
<Disclosure.Panel>Panel is: {open ? 'open' : 'closed'}</Disclosure.Panel>
90+
</>
91+
)}
92+
</Disclosure>
93+
)
94+
95+
assertDisclosureButton({
96+
state: DisclosureState.Visible,
97+
attributes: { id: 'headlessui-disclosure-button-1' },
98+
})
99+
assertDisclosurePanel({ state: DisclosureState.Visible, textContent: 'Panel is: open' })
100+
101+
await click(getDisclosureButton())
102+
103+
assertDisclosureButton({ state: DisclosureState.InvisibleUnmounted })
104+
})
82105
})
83106

84107
describe('Disclosure.Button', () => {

packages/@headlessui-react/src/components/disclosure/disclosure.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,16 @@ interface DisclosureRenderPropArg {
111111
}
112112

113113
export function Disclosure<TTag extends ElementType = typeof DEFAULT_DISCLOSURE_TAG>(
114-
props: Props<TTag, DisclosureRenderPropArg>
114+
props: Props<TTag, DisclosureRenderPropArg> & {
115+
defaultOpen?: boolean
116+
}
115117
) {
118+
let { defaultOpen = false, ...passthroughProps } = props
116119
let buttonId = `headlessui-disclosure-button-${useId()}`
117120
let panelId = `headlessui-disclosure-panel-${useId()}`
118121

119122
let reducerBag = useReducer(stateReducer, {
120-
disclosureState: DisclosureStates.Closed,
123+
disclosureState: defaultOpen ? DisclosureStates.Open : DisclosureStates.Closed,
121124
linkedPanel: false,
122125
buttonId,
123126
panelId,
@@ -135,7 +138,7 @@ export function Disclosure<TTag extends ElementType = typeof DEFAULT_DISCLOSURE_
135138
return (
136139
<DisclosureContext.Provider value={reducerBag}>
137140
{render({
138-
props,
141+
props: passthroughProps,
139142
slot,
140143
defaultTag: DEFAULT_DISCLOSURE_TAG,
141144
name: 'Disclosure',

packages/@headlessui-vue/src/components/disclosure/disclosure.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,29 @@ describe('Rendering', () => {
100100
assertDisclosurePanel({ state: DisclosureState.Visible, textContent: 'Panel is: open' })
101101
})
102102
)
103+
104+
it('should be possible to render a Disclosure in an open state by default', async () => {
105+
renderTemplate(
106+
html`
107+
<Disclosure v-slot="{ open }" defaultOpen>
108+
<DisclosureButton>Trigger</DisclosureButton>
109+
<DisclosurePanel>Panel is: {{open ? 'open' : 'closed'}}</DisclosurePanel>
110+
</Disclosure>
111+
`
112+
)
113+
114+
await new Promise<void>(nextTick)
115+
116+
assertDisclosureButton({
117+
state: DisclosureState.Visible,
118+
attributes: { id: 'headlessui-disclosure-button-1' },
119+
})
120+
assertDisclosurePanel({ state: DisclosureState.Visible, textContent: 'Panel is: open' })
121+
122+
await click(getDisclosureButton())
123+
124+
assertDisclosureButton({ state: DisclosureState.InvisibleUnmounted })
125+
})
103126
})
104127

105128
describe('DisclosureButton', () => {

packages/@headlessui-vue/src/components/disclosure/disclosure.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,12 @@ export let Disclosure = defineComponent({
4141
name: 'Disclosure',
4242
props: {
4343
as: { type: [Object, String], default: 'template' },
44+
defaultOpen: { type: [Boolean], default: false },
4445
},
4546
setup(props, { slots, attrs }) {
46-
let { ...passThroughProps } = props
47-
48-
let disclosureState = ref<StateDefinition['disclosureState']['value']>(DisclosureStates.Closed)
47+
let disclosureState = ref<StateDefinition['disclosureState']['value']>(
48+
props.defaultOpen ? DisclosureStates.Open : DisclosureStates.Closed
49+
)
4950
let panelRef = ref<StateDefinition['panelRef']['value']>(null)
5051

5152
let api = {
@@ -62,6 +63,7 @@ export let Disclosure = defineComponent({
6263
provide(DisclosureContext, api)
6364

6465
return () => {
66+
let { defaultOpen: _, ...passThroughProps } = props
6567
let slot = { open: disclosureState.value === DisclosureStates.Open }
6668
return render({ props: passThroughProps, slot, slots, attrs, name: 'Disclosure' })
6769
}

0 commit comments

Comments
 (0)