Esc

Components

All components Every component, with search. Accordion Sections that expand and collapse, one at a time or several. Alert A highlighted message, optionally dismissible. Avatar A person's picture, with initials when there is none. Avatar group Overlapping avatars with a "+N" count for the rest. Badge A small status label. Banner A dismissible strip across the top of a page. Breadcrumb The path to the current page, collapsing long trails. Button Buttons in every variant and size, with icons and a loading state. Button to A button that submits a one-off form, like Rails' button_to. Card A bordered container with header, content and footer. Checkbox A checkbox with label, standalone or bound to a form builder. Collapsible A section that opens and closes under its trigger, like a branch of a nav tree. Data grid A sortable, filterable, server-paged table on AG Grid. Date picker A typed date field with a calendar, on Cally. Dialog A modal dialog on the native <dialog> element. Divider A horizontal or vertical rule, optionally labelled. Form field A label, hint and error message wired to any form control. Icon A Lucide icon. Image An image with consistent sizing and corner radius. Input A text field with label, hint and error message, standalone or with a form builder. Input group A text field with addons before or after it. Label A form label with a required marker. Link A link styled as text or as a button. Menu A dropdown menu with keyboard navigation. Pagination Page links for a long list, from a Pagy object. Password input A password field with a show/hide toggle. Popover Floating content anchored to a trigger. Radio group A set of radio buttons. Native select The browser's own select, styled closed; best for phones' system pickers. Select A styled dropdown with keyboard navigation and type-ahead, posting like a native select. Sheet A panel that slides in from an edge of the screen. Sidebar A collapsible application sidebar with groups and menus. Spinner A loading indicator. Switch An on/off toggle. Table A styled table with header, rows and caption. Table of contents An "On this page" list that follows the reader's scroll. Tabs Tabbed panels with keyboard navigation. Text Body text in set sizes, weights and tones. Textarea A multi-line text field with label, hint and error, that can grow with its text. Theme toggle A light/dark/system theme switcher. Tooltip A hint shown on hover and focus. Typography Headings, lead, muted, code and blockquote text styles.

Table of contents

UI::TableOfContents

An "On this page" list that follows the reader's scroll.

bin/rails generate velvetkit:add table_of_contents
Also adds
Nothing else
Stimulus
ui--table-of-contents
Installs
Nothing

Examples

Nested sections

Contribution process

Every change goes through the same four steps.

1. Create an issue or open a merge request

Describe the change and why it matters. Link related issues, add screenshots for visual changes, and note anything reviewers should try by hand.

Keep each change focused on one thing, so it is quick to review and easy to revert.

2. Classify as core or extended

Describe the change and why it matters. Link related issues, add screenshots for visual changes, and note anything reviewers should try by hand.

Keep each change focused on one thing, so it is quick to review and easy to revert.

3. Define level of support

Describe the change and why it matters. Link related issues, add screenshots for visual changes, and note anything reviewers should try by hand.

Keep each change focused on one thing, so it is quick to review and easy to revert.

4. Merge your changes

Describe the change and why it matters. Link related issues, add screenshots for visual changes, and note anything reviewers should try by hand.

Keep each change focused on one thing, so it is quick to review and easy to revert.

Resources

Guides, design files and the component checklist.

Ask in the discussion board when something is unclear.

Code of conduct

Be kind, assume good intent, and keep feedback about the work.

Flat

Install

Each section starts with what you need and ends with how to check it worked.

Commands run from the root of your Rails app.

Configure

Each section starts with what you need and ends with how to check it worked.

Commands run from the root of your Rails app.

Theme

Each section starts with what you need and ends with how to check it worked.

Commands run from the root of your Rails app.

Deploy

Each section starts with what you need and ends with how to check it worked.

Commands run from the root of your Rails app.

API

Arguments
UI::TableOfContents.new(title: nil, label: nil, offset: 80, container: nil, class: nil, **html_attrs)
Slots: with_item

Notes

"On this page" navigation with scrollspy. As the reader scrolls, the link to the section they are reading is marked current (aria-current="location") and an indicator slides beside it. A link jumps to its section like any anchor. Each item links to an element id on the page, and items nest: <%= render(UI::TableOfContents.new(title: "On this page")) do |toc| %> <% toc.with_item(href: "#install", text: "Install") do |item| %> <% item.with_item(href: "#requirements", text: "Requirements") %> <% end %> <% toc.with_item(href: "#usage", text: "Usage") %> <% end %> A section counts as reached once its top passes `offset:` pixels below the top of the scroll area; raise it to clear a sticky header. When the content scrolls inside an element rather than the window, pass that element's CSS selector as `container:`.