Accordion

Sections that open and close to show or hide their content.

Default
Is it accessible?
Yes. Each section is a native details element, so the keyboard and screen readers work with no script.
Does it need JavaScript?
No. Sections open and close on their own.
Can I style it?
It is plain CSS on plain elements, so yes.
{ui accordion,
	items: [
		[
			'title' => 'Is it accessible?',
			'content' => 'Yes. Each section is a native details element, so the keyboard and screen readers work with no script.',
			'open' => true,
		],
		[
			'title' => 'Does it need JavaScript?',
			'content' => 'No. Sections open and close on their own.',
		],
		[
			'title' => 'Can I style it?',
			'content' => 'It is plain CSS on plain elements, so yes.',
		],
	],
/}

Each section is a native details with a summary, so it opens with the keyboard and is announced by a screen reader, and works with no script. An item is a title and its content, and open starts it open. Any number can be open at once. The content is escaped, so text from a page field is safe to pass.

One at a time
Shipping
Orders leave in three working days.
Returns
Send anything back within thirty days.
Warranty
Two years on every product.
{ui accordion,
	exclusive: true,
	items: [
		[
			'title' => 'Shipping',
			'content' => 'Orders leave in three working days.',
			'open' => true,
		],
		[
			'title' => 'Returns',
			'content' => 'Send anything back within thirty days.',
		],
		[
			'title' => 'Warranty',
			'content' => 'Two years on every product.',
		],
	],
/}

exclusive: true closes the other sections when one opens. That is the one thing the shared ui.js does for it. The name attribute would do it natively, but it is newer than the browsers the UI supports. Without the script the sections still open and close, they just do not close each other.

From pages
Tabs
Links that swap a panel loaded from the server.
Pagination
Links to the pages of a long list.
Modal
A dialog that opens over the page, loaded from the server.
Toast
A short message that appears in the corner and goes away on its own.
{ui accordion, items: p('ui/components')->children() /}

items takes pages through the shared items() function, with a page's description as its content. That suits a list of questions kept as pages.

Params

Param Default Description
items [] the sections: pages or arrays like ['title' => 'Shipping', 'content' => 'Three days.', 'open' => true]; a page's description is its content
exclusive false opening one section closes the others
class '' added to accordion
attrs [] any other attributes, e.g. ['id' => 'faq']