Disclosure
An interactive component which expands/collapses content.
Jasmin starred 3 repositories
import { CaretUpDown, X } from '@examples/primitives/disclosure/icons'
import Disclosure from '@corvu/disclosure'
import type { VoidComponent } from 'solid-js'
const DisclosureExample: VoidComponent = () => {
return (
<div class="mt-8">
<Disclosure collapseBehavior="hide">
{(props) => (
<>
<div class="mb-2 flex items-center justify-between space-x-4">
<p class="font-medium text-corvu-text-dark">
Jasmin starred 3 repositories
</p>
<Disclosure.Trigger class="rounded-lg bg-corvu-100 p-1 transition-all duration-100 hover:bg-corvu-200 active:translate-y-0.5">
{props.expanded && (
<>
<X size="20" />
<span class="sr-only">Collapse</span>
</>
)}
{!props.expanded && (
<>
<CaretUpDown size="20" />
<span class="sr-only">Expand</span>
</>
)}
</Disclosure.Trigger>
</div>
<div class="rounded-lg bg-corvu-100 px-3 py-2">corvudev/corvu</div>
<Disclosure.Content class="mt-1 space-y-1 overflow-hidden corvu-expanded:animate-expand corvu-collapsed:animate-collapse">
<div class="rounded-lg bg-corvu-100 px-3 py-2">solidjs/solid</div>
<div class="rounded-lg bg-corvu-100 px-3 py-2">
nitropage/nitropage
</div>
</Disclosure.Content>
</>
)}
</Disclosure>
</div>
)
}
export default DisclosureExample
import corvuPlugin from '@corvu/tailwind'
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{ts,tsx}'],
theme: {
extend: {
colors: {
corvu: {
bg: '#f3f1fe',
100: '#e6e2fd',
200: '#d4cbfb',
300: '#bcacf6',
400: '#a888f1',
text: '#180f24',
},
},
animation: {
expand: 'expand 250ms cubic-bezier(0.32,0.72,0,0.75)',
collapse: 'collapse 250ms cubic-bezier(0.32,0.72,0,0.75)',
},
keyframes: {
expand: {
'0%': {
height: '0px',
},
'100%': {
height: 'var(--corvu-disclosure-content-height)',
},
},
collapse: {
'0%': {
height: 'var(--corvu-disclosure-content-height)',
},
'100%': {
height: '0px',
},
},
},
},
},
plugins: [corvuPlugin],
}
import './index.css'
import { CaretUpDown, X } from '@examples/primitives/disclosure/icons'
import Disclosure from '@corvu/disclosure'
import type { VoidComponent } from 'solid-js'
const DisclosureExample: VoidComponent = () => {
return (
<div>
<Disclosure collapseBehavior="hide">
{(props) => (
<>
<div class="header">
<p class="header_title">Jasmin starred 3 repositories</p>
<Disclosure.Trigger>
{props.expanded && (
<>
<X size="20" />
<span class="sr-only">Collapse</span>
</>
)}
{!props.expanded && (
<>
<CaretUpDown size="20" />
<span class="sr-only">Expand</span>
</>
)}
</Disclosure.Trigger>
</div>
<div class="repository_card">corvudev/corvu</div>
<Disclosure.Content>
<div class="repository_card">solidjs/solid</div>
<div class="repository_card">nitropage/nitropage</div>
</Disclosure.Content>
</>
)}
</Disclosure>
</div>
)
}
export default DisclosureExample
.header {
margin-bottom: 0.5rem;
display: flex;
align-items: center;
justify-content: space-between;
}
.header> :not([hidden])~ :not([hidden]) {
margin-left: 1rem;
}
.header_title {
font-weight: 500;
}
[data-corvu-disclosure-trigger] {
border-radius: 0.5rem;
background-color: hsl(249, 87%, 94%);
padding: 0.25rem;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 100ms;
}
[data-corvu-disclosure-trigger]:active {
transform: translate(0, 0.125rem);
}
[data-corvu-disclosure-trigger]:hover {
background-color: hsl(251, 86%, 89%);
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.repository_card {
border-radius: 0.5rem;
background-color: hsl(249, 87%, 94%);
padding-left: 0.75rem;
padding-right: 0.75rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
[data-corvu-disclosure-content] {
margin-top: 0.25rem;
overflow: hidden;
}
.space-y-1 > :not([hidden]) ~ :not([hidden]){
margin-top: 0.25rem;
}
[data-corvu-disclosure-content][data-collapsed] {
animation: collapse 200ms linear;
}
[data-corvu-disclosure-content][data-expanded] {
animation: expand 200ms linear;
}
@keyframes expand {
0% {
height: 0px;
}
100% {
height: var(--corvu-disclosure-content-height);
}
}
@keyframes collapse {
0% {
height: var(--corvu-disclosure-content-height);
}
100% {
height: 0px;
}
}
Features Section titled Features
- Option to hide the content when collapsed instead of unmounting it for better SEO
- CSS variables to animate the height/width of the content
- Full keyboard navigation
Installation Section titled Installation
npm install @corvu/disclosure
The disclosure is also included in the main corvu
package under corvu/disclosure
.
Usage Section titled Usage
import Disclosure from '@corvu/disclosure' // 'corvu/disclosure'
// or
// import { Root, Trigger, Content } from '@corvu/disclosure'
Anatomy Section titled Anatomy
<Disclosure>
<Disclosure.Trigger />
<Disclosure.Content />
</Disclosure>
Animation Section titled Animation
corvu sets the --corvu-disclosure-content-height
and --corvu-disclosure-content-width
CSS properties on the disclosure content that make it possible to animate the height/width.
[data-corvu-disclosure-content][data-collapsed] {
animation: collapse 200ms linear;
}
[data-corvu-disclosure-content][data-expanded] {
animation: expand 200ms linear;
}
@keyframes collapse {
0% {
height: var(--corvu-disclosure-content-height);
}
100% {
height: 0px;
}
}
@keyframes expand {
0% {
height: 0px;
}
100% {
height: var(--corvu-disclosure-content-height);
}
}
Accessibility Section titled Accessibility
Adheres to the Disclosure WAI-ARIA design pattern.
Keyboard navigation Section titled Keyboard navigation
Key | Behavior |
---|---|
Space | Activates the trigger and toggles the disclosure. |
Enter | Activates the trigger and toggles the disclosure. |
API reference Section titled API reference
Context wrapper for the disclosure. Is required for every disclosure you create.
Props
Property | Default | Type/Description |
---|---|---|
expanded | - | boolean Whether the disclosure is expanded. |
onExpandedChange | - | (expanded: boolean) => void Callback fired when the expanded state changes. |
initialExpanded | false | boolean Whether the disclosure is expanded initially. |
collapseBehavior | remove | 'remove' | 'hide' Whether the disclosure content should be removed or hidden when collapsed. Useful if you want to always render the content for SEO reasons. |
disclosureId | createUniqueId() | string The id attribute of the disclosure content element. |
contextId | - | string The id of the disclosure context. Useful if you have nested disclosures and want to create components that belong to a disclosure higher up in the tree. |
Button that changes the open state of the disclosure when clicked.
Props
Property | Default | Type/Description |
---|---|---|
as | button | ValidComponent Component to render the dynamic component as. |
contextId | - | string The id of the disclosure context to use. |
Data attributes
Data attributes present on <Trigger />
components.
Property | Description |
---|---|
data-corvu-disclosure-trigger | Present on every disclosure trigger element. |
data-expanded | Present when the disclosure is expanded. |
data-collapsed | Present when the disclosure is collapsed. |
Content of a disclosure. Can be animated.
Props
Property | Default | Type/Description |
---|---|---|
as | div | ValidComponent Component to render the dynamic component as. |
forceMount | false | boolean Whether the disclosure content should be forced to render. Useful when using third-party animation libraries. |
contextId | - | string The id of the disclosure context to use. |
Data attributes
Data attributes present on <Content />
components.
Property | Description |
---|---|
data-corvu-disclosure-content | Present on every disclosure content element. |
data-expanded | Present when the disclosure is expanded. |
data-collapsed | Present when the disclosure is collapsed. |
CSS properties
CSS properties present on <Content />
components.
Property | Description |
---|---|
--corvu-disclosure-content-width | The width of the disclosure content. Useful if you want to animate its width. |
--corvu-disclosure-content-height | The height of the disclosure content. Useful if you want to animate its height. |
Context which exposes various properties to interact with the disclosure. Optionally provide a contextId to access a keyed context.
Returns
Property | Type/Description |
---|---|
expanded | Accessor<boolean> Whether the disclosure is expanded. |
setExpanded | Setter<boolean> Callback fired when the expanded state changes. |
collapseBehavior | Accessor<'remove' | 'hide'> Whether the disclosure content should be removed or hidden when collapsed. |
disclosureId | Accessor<string> The id attribute of the disclosure content element. |
contentPresent | Accessor<boolean> Whether the disclosure content is present. This differes from expanded as it tracks pending animations. |
contentRef | Accessor<HTMLElement | null> The disclosure content element. |
contentSize | Accessor<[number, number] | null> The current size of the disclosure content. Useful if you want to animate width or height. [width, height] |
Props that are passed to the Root component children callback.
Props
Property | Type/Description |
---|---|
expanded | boolean Whether the disclosure is expanded. |
setExpanded | Setter<boolean> Callback fired when the expanded state changes. |
collapseBehavior | 'remove' | 'hide' Whether the disclosure content should be removed or hidden when collapsed. |
disclosureId | string The id attribute of the disclosure content element. |
contentPresent | boolean Whether the disclosure content is present. This differes from expanded as it tracks pending animations. |
contentRef | HTMLElement | null The disclosure content element. |
contentSize | [number, number] | null The current size of the disclosure content. Useful if you want to animate width or height. [width, height] |
Developed and designed by Jasmin