block-types > Toggle Block
Toggle Block
The Toggle block is used to create collapsible content. It's an interactive element where hidden content expands or collapses when the user clicks on the toggle.
Data Structure
The Notion API data structure for a Toggle block is as follows:
{
"type": "toggle",
"toggle": {
"rich_text": [
{
"type": "text",
"text": {
"content": "Click to toggle",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "Click to toggle",
"href": null
}
],
"color": "default",
"children": [
// Nested blocks...
]
}
}
rich_text
: An array containing the display text and style information of the toggle.color
: Specifies the color of the toggle text.children
: An array of nested blocks that will be displayed when the toggle is expanded.
React Component
The component that renders the Toggle block in Notionpresso is as follows:
import React, { useState, useCallback } from "react";
import type { ToggleArgs } from "../types";
import { getColorCss } from "../utils";
import RichText from "./internal/rich-text";
type ToggleProps = {
children?: React.ReactNode;
} & ToggleArgs;
const Toggle: React.FC<ToggleProps> = ({ children, ...props }) => {
const {
toggle: { color, rich_text: texts },
} = props;
const [open, setOpen] = useState(false);
const toggleOpen = useCallback(() => setOpen((prevOpen) => !prevOpen), []);
return (
<div
className={notion-block notion-toggle ${getColorCss(color)} ${ open ? "notion-toggle-open" : "" }}
aria-expanded={open}
>
<div className="notion-toggle-content">
<button onClick={toggleOpen} className="notion-toggle-button">
<div
className={notion-toggle-button-arrow ${ open ? "notion-toggle-button-arrow-opened" : "" }}
/>
</button>
<p>
<RichText props={texts} />
</p>
</div>
{open && children}
</div>
);
};
export default Toggle;
export default Toggle;
Usage Example
Here's an example of how to use the Toggle block:
import { Notion } from "@notionpresso/react";
function MyNotionPage({ blocks }) {
return (
<Notion>
<Notion.Blocks blocks={blocks} />
</Notion>
);
}
function MyNotionPage({ blocks }) {
return (
<Notion>
<Notion.Blocks blocks={blocks} />
</Notion>
);
}
Here, blocks
is an array of block data received from the Notion API.
State Management
The Toggle block internally uses the useState
hook to manage its open/closed state. The open
state variable represents the current state of the toggle, and the toggleOpen
function switches this state.
Styling
The style of the Toggle block can be customized through the following CSS classes:
.notion-block
: Basic style applied to all Notion blocks.notion-toggle
: Specific style for Toggle blocks.notion-toggle-open
: Style for when the toggle is in the open state.notion-toggle-content
: Style for the toggle content.notion-toggle-button
: Style for the toggle button.notion-toggle-button-arrow
: Style for the toggle arrow
If additional styling is needed, you can write CSS targeting these classes. For example:
.notion-toggle {
margin-bottom: 8px;
}
.notion-toggle-button {
cursor: pointer;
background: none;
border: none;
padding: 0;
margin-right: 4px;
}
.notion-toggle-button-arrow {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #333;
transition: transform 0.3s ease;
}
.notion-toggle-button-arrow-opened {
transform: rotate(180deg);
}
.notion-toggle-button-arrow-opened {
transform: rotate(180deg);
}
Nesting Support
Toggle blocks can contain other blocks. This is handled through the children
prop. The children
are only rendered when the toggle is in the open state.
Accessibility Considerations
- The
aria-expanded
attribute is used to inform screen readers of the toggle's current state. - It's good to add
tabIndex={0}
to the toggle button to support keyboard navigation. - Providing an appropriate
aria-label
to the toggle button is recommended to clearly describe its function.
Notes
- Including too much content inside a toggle can degrade the user experience, so it's best to include only an appropriate amount of content.
- The open/closed state of toggles is not stored on the server, so all toggles will return to their default state (closed) when the page is refreshed.
- Deeply nested toggles can confuse users, so it's best to limit the nesting levels as much as possible.