Spoiler
Content that stays covered until somebody asks for it. The cover is a blur rather than a hidden box, so a reader can see that there is something there and how much of it, without reading it by accident.
import { Spoiler } from 'neba';
<Spoiler locale="ko">
<p>로즈버드는 썰매의 이름이었습니다.</p>
</Spoiler>;Props
| Prop | Type | Default | Description |
|---|---|---|---|
| revealed | boolean | — | Whether the content is uncovered. Pass it to drive the Spoiler yourself |
| defaultRevealed | boolean | false | Where an uncontrolled Spoiler starts |
| onRevealedChange | (revealed: boolean) => void | — | Called when the reveal or hide button is pressed |
| locale | string | 'en' | Which language the default label and notice are written in: a BCP 47 tag. Unsupported tags fall back to English |
| label | ReactNode | — | The reveal button’s label. Defaults to the locale’s word for it |
| hideLabel | ReactNode | — | The hide button’s label, when reversible is on |
| description | ReactNode | false | — | The line above the button. Defaults to the locale’s wording; false writes nothing at all |
| action | ReactNode | — | Replaces the default reveal button entirely. The replacement is yours to wire up through revealed and onRevealedChange |
| reversible | boolean | false | Keeps the content coverable: a hide button under the content, whose row is held open while it is still covered so the box does not change height |
| maxHeight | number | string | — | Clamps the covered box to this height: a CSS length, or a number in pixels. Revealing releases it |
| blur | number | 10 | How hard the content is blurred, in pixels |
| padded | boolean | true | Inner padding around the content. Turn it off for something that should reach the edges |
| variantshared | 'solid' | 'outline' | 'text' | 'outline' | Weight of the box’s surface. text draws no box at all |
| sizeshared | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | The sheet’s radius, and the size of the button on it |
| colorshared | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'primary' | Semantic colour role. Arbitrary colour values are not accepted |
| densityshared | 'default' | 'compact' | 'default' | Padding around the cover’s own text and button, and nothing else |
| elevationshared | 0 | 1 | 2 | 3 | 0 | Drop shadow depth. 0 means no shadow at all |
| children | ReactNode | — | What is being covered |
Every other <div> attribute passes through to the root, except onChange: the change worth listening for is onRevealedChange.
The shared axes (variant size color density elevation) are defined in prop conventions.
Examples
maxHeight
Left out, the box is exactly as tall as what it holds: right for a paragraph or a picture. The cover keeps its place once the content is out, so a notice and a button taller than the line they were covering do not shrink the box on the press, and nothing on the page below moves.
maxHeight is the one thing that does change the height. It clamps the covered box, and revealing lets go of the clamp so the content takes whatever height it needs; a clamp that stayed on would leave the reader a scrollbar instead. It takes a CSS length or a number in pixels.
reversible puts the cover back on afterwards, with a hide button under the content. Its row is held open while the content is still covered, so the way back costs the box no height either.
locale
The button and the line above it are the only words the component invents, and locale is which language they are in: a BCP 47 tag such as ko, pt-BR or zh-Hant. Tags with no translation fall back to English, and a regional tag resolves to its language: ko-KR is ko, zh-TW is Traditional.
label, description and action
label changes the button's words and description changes the line above it; description={false} leaves the cover with nothing written on it. blur decides how hard the content is blurred, in pixels.
action replaces the button entirely, and that replacement is yours to wire up, through revealed and onRevealedChange.
padded
The box pads its content on Box's own scale. Turn it off for something that should reach the edges: the corners then crop the picture the way they do on any other sheet.
variant
text draws no box at all, which is what a spoiler in the middle of running prose usually wants. solid is the filled sheet, for one that is meant to stop the reader.
Controlled
Pass revealed and the Spoiler stops keeping state of its own. Use it to reveal several at once, to remember what a reader has already uncovered, or to put the control somewhere else on the page.
const [revealed, setRevealed] = useState(false);
<Spoiler revealed={revealed} onRevealedChange={setRevealed}>
<p>The butler did it.</p>
</Spoiler>;Accessibility
- While it is covered the content is
inert: out of the tab order, off the accessibility tree, and out of a select-all. A spoiler that could be defeated by a select-all is not a spoiler. - The reveal button carries
aria-expandedandaria-controls, pointing at the content it uncovers. - Set
localeso the button and the notice are read out in the page's own language, or write them out inlabelanddescription.