diff --git a/AGENTS.md b/AGENTS.md
index bdc68c5..50e8c61 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -25,9 +25,9 @@ Ely GPUI Component. A component library for GPUI, in light and dark.
- `cargo run --example gallery -- --capture
` writes PNGs of every page, light and dark, top to bottom, then each page's scripted states, including windows the demos open. macOS only.
- `cargo run --example gallery -- --narrow 280 --capture ` lays each page, header and body, at that width in a padded card and shoots it without its script, whose aims are measured at full width. Demos that set their own width run past the card.
- `RUSTC_BOOTSTRAP=1 cargo check --lib --target wasm32-unknown-unknown` checks the web build; gpui_web's `wasm_thread` needs the bootstrap, as Zed's web examples do.
-- `ELY_GALLERY_ASSETS= scripts/web.sh ` builds the gallery for the browser, profile `web`, and fails past Cloudflare's 25 MiB. It opens at `?page=&story=&theme=light|dark`; the host page calls `gallery.setTheme(mode)` or posts `{ ely: "theme", theme }` later.
-- `python3 scripts/stories.py` writes `examples/gallery/stories.json`, every page's sections in drawing order with their components, for the site. `scripts/check.sh` refuses a stale one.
-- `cargo test --lib --features test-support`, `cargo clippy --all-targets --features test-support -- -D warnings`, `cargo fmt --check`. `scripts/check.sh` runs them with the house rules.
+- `ELY_GALLERY_ASSETS= scripts/web.sh ` builds the gallery for the browser, profile `web`, and fails past Cloudflare's 25 MiB. It opens at `?page=&story=&theme=light|dark`; the host page calls `gallery.setTheme(mode)` or posts `{ ely: "theme", theme }`, before the wasm runs or after, and the page posts `{ ely: "ready" }` to its parent once it runs.
+- `python3 scripts/stories.py` writes `examples/gallery/stories.json`, every page's sections in drawing order with their components, for the site: the names in a title, and in its `SHOWN` table what a story draws beyond them. It fails on a section opened inside another and on a ticked entry with a home of its own that no story names. `scripts/check.sh` refuses a stale one.
+- `cargo test --lib --features test-support`, `cargo clippy --all-targets --features test-support -- -D warnings`, `cargo fmt --check`. `scripts/check.sh` runs them with the house rules and lints the gallery for wasm32.
- `rm -rf target/debug/incremental` and `cargo clean -p ely-gpui-component` after each task item keep the disk lean. Cargo keeps every old build of the crate and its tests under a new hash; by T25 they had filled the disk.
- `scripts/icons.sh ...` adds icons. Then add a line to `IconName` in `src/primitives/icon.rs`.
- `python3 scripts/countries.py ` writes the bundled world; `python3 scripts/tiles.py ` writes the gallery's map tiles.
@@ -180,9 +180,10 @@ Ely GPUI Component. A component library for GPUI, in light and dark.
- Time reads `web_time::Instant`: std's compiles for wasm32 and panics in the browser. `scripts/check.sh` refuses std's in `src` and the gallery.
- What cannot build for wasm32 is absent there through `cfg(not(target_family = "wasm"))`, never faked: the live terminal, `Terminal` and `Launch` with their grid, keys and search, and the gallery's capture harness.
- A gallery demo a browser cannot run says why on the web through `ui::web_note`, in the blocked style: a second window (`own_window`), files from the dialog or a drop (`NO_FILES`), the menu bar, window moves, a clipboard read.
-- A story is a gallery section: its title is a literal, one per page. Under `ui::Story` the one asked for draws without its title and the rest hide, which skips their prepaint and paint; a story the page lacks fails in the page.
+- A story is a gallery section: its title is a literal, one per page. Under `ui::Story` the one asked for draws without its title; the rest drop their demos (`ui::Section`), so nothing of theirs lays out, loads or moves. A story the page lacks fails in the page.
- The gallery's pictures go through `asset!` and `ui::picture` or `ui::resource`: a file natively, on the web an address under `ELY_GALLERY_ASSETS`, since gpui reads no files there.
-- The first frame wears the host's mode through `Theme::set_mode_now`; `set_mode` fades from the colors on screen.
+- On the web a paste reaches the focused field as the browser's paste event, through `EntityInputHandler::paste`: gpui_web reads no clipboard on demand, so Paste stays unbound there (`TextInput`, `CodeEditor`).
+- The first frame wears the host's mode through `Theme::set_mode_now`, a mode sent before the window opens included; `set_mode` fades from the colors on screen.
- The system time zone comes from `typography::format::system_zone`, which fails loud; jiff's `TimeZone::system()` falls back to UTC in silence.
- A Select with nothing to pick stays shut: disabled, it shows its placeholder; open, it fails (`media::DeviceSelector` says no device was found).
- A list opens with its cursor on the current choice: Select on the chosen row, Combobox on its value, MultiSelect on the first one ticked, SelectableList on its first selected row. A selection the owner makes, not the echo of the list's own pick, moves SelectableList's cursor there.
diff --git a/examples/gallery/index.html b/examples/gallery/index.html
index 5442c2e..e2621bf 100644
--- a/examples/gallery/index.html
+++ b/examples/gallery/index.html
@@ -16,16 +16,22 @@
diff --git a/examples/gallery/pages/i18n/a11y.rs b/examples/gallery/pages/i18n/a11y.rs
index ef0368c..a516a22 100644
--- a/examples/gallery/pages/i18n/a11y.rs
+++ b/examples/gallery/pages/i18n/a11y.rs
@@ -10,7 +10,7 @@ use gpui::{
};
use crate::probe::probe;
-use crate::ui::{blocked, section, specimen, specimens};
+use crate::ui::{UNREAD, blocked, section, specimen, specimens};
const NAV: [&str; 5] = ["Home", "Docs", "Pricing", "Blog", "About"];
@@ -65,7 +65,7 @@ pub fn skip_link(window: &mut Window, cx: &mut App) -> impl IntoElement + use<>
),
)
.child(blocked(
- "LiveRegion / Announcer, AccessibleIcon, AriaLabel, ScreenReaderOnly: not yet shown: gpui builds an AccessKit tree from elements with an id and a role, and no screen reader here reads it.",
+ format!("LiveRegion / Announcer, AccessibleIcon, AriaLabel, ScreenReaderOnly: not yet shown: {UNREAD}."),
cx,
))
}
diff --git a/examples/gallery/pages/interaction/pointer.rs b/examples/gallery/pages/interaction/pointer.rs
index f47861c..dbf1aaa 100644
--- a/examples/gallery/pages/interaction/pointer.rs
+++ b/examples/gallery/pages/interaction/pointer.rs
@@ -193,7 +193,7 @@ pub fn shapes(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
.child(*name),
)
});
- section(
+ let moves = section(
"Resizable · Rotatable · Selectable / SelectionArea · RubberBandSelection · Sortable",
"A box resized from its edges or its grip; a picture turned by its knob, as gpui turns svgs alone; tiles taken by a band drawn on empty space; rows sorted by drag through motion::Reorder.",
cx,
@@ -254,73 +254,72 @@ pub fn shapes(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
})),
cx,
)),
+ );
+ let presses = section(
+ "LongPress · DoubleClick · Gesture · PanZoom",
+ "A long press is primitives::Pressable; a double press is gpui's click_count. The wheel pans and, with Command, zooms layout::Viewport; two fingers swipe lists::SwipeableListItem.",
+ cx,
)
.child(
- section(
- "LongPress · DoubleClick · Gesture · PanZoom",
- "A long press is primitives::Pressable; a double press is gpui's click_count. The wheel pans and, with Command, zooms layout::Viewport; two fingers swipe lists::SwipeableListItem.",
- cx,
- )
- .child(
- specimens()
- .child(specimen(
- "LongPress → primitives::Pressable",
- Pressable::new("interaction-press", move |down, _, cx| {
- let theme = cx.theme();
- div()
- .px_4()
- .py_3()
- .rounded_lg()
- .border_1()
- .border_color(theme.colors.border)
- .bg(if down { theme.colors.active } else { theme.colors.surface })
- .text_size(theme.text_size(TextSize::Sm))
- .child(format!("Pressed {presses} · held {held}"))
- .into_any_element()
- })
- .on_press(move |_, cx| change(&press, cx, |shapes| shapes.presses += 1))
- .on_long_press(move |_, cx| change(&long, cx, |shapes| shapes.held += 1)),
- cx,
- ))
- .child(specimen(
- "DoubleClick",
+ specimens()
+ .child(specimen(
+ "LongPress → primitives::Pressable",
+ Pressable::new("interaction-press", move |down, _, cx| {
+ let theme = cx.theme();
div()
- .id("interaction-double")
.px_4()
.py_3()
.rounded_lg()
.border_1()
.border_color(theme.colors.border)
- .tab_index(0)
- .focus_ring(cx)
+ .bg(if down { theme.colors.active } else { theme.colors.surface })
.text_size(theme.text_size(TextSize::Sm))
- .on_click(move |event, _, cx| {
- if event.click_count() == 2 {
- change(&double, cx, |shapes| shapes.doubles += 1)
- }
- })
- .child(format!("Opened {}", plural(doubles as u64, "time", "times"))),
- cx,
- ))
- .child(specimen(
- "PanZoom → layout::Viewport",
- div().w(px(240.)).h(px(140.)).rounded_lg().border_1().border_color(theme.colors.border).overflow_hidden().child(
- Viewport::new("interaction-viewport", |view: Transform, _, cx| {
- let theme = cx.theme();
- let corner = view.apply(point(px(80.), px(30.)));
- div()
- .absolute()
- .left(corner.x)
- .top(corner.y)
- .size(px(80.) * view.scale)
- .rounded_lg()
- .bg(theme.colors.sunken)
- .into_any_element()
- }),
- ),
- cx,
- )),
- )
- .child(blocked("Pinch: gpui hands a trackpad pinch to on_pinch, and the viewport does not zoom on it yet.", cx)),
+ .child(format!("Pressed {presses} · held {held}"))
+ .into_any_element()
+ })
+ .on_press(move |_, cx| change(&press, cx, |shapes| shapes.presses += 1))
+ .on_long_press(move |_, cx| change(&long, cx, |shapes| shapes.held += 1)),
+ cx,
+ ))
+ .child(specimen(
+ "DoubleClick",
+ div()
+ .id("interaction-double")
+ .px_4()
+ .py_3()
+ .rounded_lg()
+ .border_1()
+ .border_color(theme.colors.border)
+ .tab_index(0)
+ .focus_ring(cx)
+ .text_size(theme.text_size(TextSize::Sm))
+ .on_click(move |event, _, cx| {
+ if event.click_count() == 2 {
+ change(&double, cx, |shapes| shapes.doubles += 1)
+ }
+ })
+ .child(format!("Opened {}", plural(doubles as u64, "time", "times"))),
+ cx,
+ ))
+ .child(specimen(
+ "PanZoom → layout::Viewport",
+ div().w(px(240.)).h(px(140.)).rounded_lg().border_1().border_color(theme.colors.border).overflow_hidden().child(
+ Viewport::new("interaction-viewport", |view: Transform, _, cx| {
+ let theme = cx.theme();
+ let corner = view.apply(point(px(80.), px(30.)));
+ div()
+ .absolute()
+ .left(corner.x)
+ .top(corner.y)
+ .size(px(80.) * view.scale)
+ .rounded_lg()
+ .bg(theme.colors.sunken)
+ .into_any_element()
+ }),
+ ),
+ cx,
+ )),
)
+ .child(blocked("Pinch: gpui hands a trackpad pinch to on_pinch, and the viewport does not zoom on it yet.", cx));
+ div().child(moves).child(presses)
}
diff --git a/examples/gallery/pages/menus/more.rs b/examples/gallery/pages/menus/more.rs
index a4e6c6d..1b7621d 100644
--- a/examples/gallery/pages/menus/more.rs
+++ b/examples/gallery/pages/menus/more.rs
@@ -27,7 +27,7 @@ pub fn menu_bar(cx: &mut App) -> impl IntoElement + use<> {
cx,
)
.children(web_note(
- "A browser page has no menu bar, and gpui on the web keeps no cx.set_menus: this bar draws the gallery's own list of the same menus.",
+ "A browser page has no menu bar, and gpui on the web keeps no cx.set_menus: this bar draws the gallery's own list of the same menus. About Ely would open a second window and Quit would end the app, neither of which a page can, so both only log.",
cx,
))
.child(specimen(
diff --git a/examples/gallery/pages/primitives/parts.rs b/examples/gallery/pages/primitives/parts.rs
index 6060e7f..60de628 100644
--- a/examples/gallery/pages/primitives/parts.rs
+++ b/examples/gallery/pages/primitives/parts.rs
@@ -15,7 +15,7 @@ use gpui::{
use crate::{
probe::probe,
- ui::{blocked, code, picture, row, section, specimen, specimens},
+ ui::{UNREAD, blocked, code, picture, row, section, specimen, specimens},
};
const ATRIUM: &str = asset!("atrium.jpg");
@@ -193,10 +193,8 @@ pub fn backdrop(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
}
pub fn visually_hidden(cx: &App) -> impl IntoElement + use<> {
- section("VisuallyHidden", "Text for screen readers only.", cx).child(blocked(
- "Not yet shown: gpui builds an AccessKit tree from elements with an id and a role, and no screen reader here reads it.",
- cx,
- ))
+ section("VisuallyHidden", "Text for screen readers only.", cx)
+ .child(blocked(format!("Not yet shown: {UNREAD}."), cx))
}
fn chip(id: &'static str, label: &'static str, cx: &App) -> impl IntoElement + use<> {
diff --git a/examples/gallery/pages/tables/grids.rs b/examples/gallery/pages/tables/grids.rs
index 06a2924..c5683da 100644
--- a/examples/gallery/pages/tables/grids.rs
+++ b/examples/gallery/pages/tables/grids.rs
@@ -8,7 +8,7 @@ use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, p
use crate::{
probe::probe,
- ui::{keep, section, set},
+ ui::{keep, section, set, web_note},
};
type Cells = HashMap<(usize, usize), SharedString>;
@@ -35,6 +35,10 @@ pub fn data_grid(window: &mut Window, cx: &mut App) -> impl IntoElement + use<>
"Cells to edit like a spreadsheet's. Arrows walk, Shift stretches a range, typing or a double press edits, Delete clears, and Cmd-C and Cmd-V copy and paste.",
cx,
)
+ .children(web_note(
+ "A browser reads its clipboard only as it pastes into a text field, so Cmd-V pastes no cells here.",
+ cx,
+ ))
.child(probe(
"grid",
div().child(
diff --git a/examples/gallery/pages/terminal/mod.rs b/examples/gallery/pages/terminal/mod.rs
index 3a64c53..0913998 100644
--- a/examples/gallery/pages/terminal/mod.rs
+++ b/examples/gallery/pages/terminal/mod.rs
@@ -50,7 +50,7 @@ fn live(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
{
let _ = window;
section.child(crate::ui::blocked(
- "A browser starts no processes and has no pseudo-terminal, so no shell runs here, and alacritty's grid, which draws the build's output, does not build for the web. The blocks, colored output, logs and processes below draw without one.",
+ "A browser starts no processes and has no pseudo-terminal, so no shell runs here, and alacritty's grid, which draws the build's output, does not build for the web. The page's other stories, command blocks, colored output, logs and processes, draw without one.",
cx,
))
}
diff --git a/examples/gallery/shell.rs b/examples/gallery/shell.rs
index 644b452..2b5405e 100644
--- a/examples/gallery/shell.rs
+++ b/examples/gallery/shell.rs
@@ -288,9 +288,10 @@ impl Render for Gallery {
return self.root(cx).child(
on_axis(div().id(("story", self.pass)))
.size_full()
- .overflow_y_scroll()
+ .overflow_scroll()
.track_scroll(&self.scroll)
- .child(div().p_6().child(body)),
+ // The page column's 848 plus padding; narrower, the story scrolls sideways.
+ .child(div().min_w(px(896.0)).p_6().child(body)),
);
}
let sidebar = self.sidebar(cx);
diff --git a/examples/gallery/stories.json b/examples/gallery/stories.json
index eb1b69e..b53fde6 100644
--- a/examples/gallery/stories.json
+++ b/examples/gallery/stories.json
@@ -2,9 +2,9 @@
{"number": 1, "slug": "primitives", "title": "Primitives", "summary": "The smallest parts. Most are gpui itself; Ely adds the rest.", "stories": [{"title": "Box / View", "slug": "box-view", "components": ["Box", "View"]}, {"title": "Text", "slug": "text", "components": ["Text"]}, {"title": "Icon", "slug": "icon", "components": ["Icon"]}, {"title": "IconSet / IconRegistry", "slug": "iconset-iconregistry", "components": ["IconSet", "IconRegistry"]}, {"title": "Svg", "slug": "svg", "components": ["Svg"]}, {"title": "Image", "slug": "image", "components": ["Image"]}, {"title": "Canvas", "slug": "canvas", "components": ["Canvas"]}, {"title": "Divider / Separator", "slug": "divider-separator", "components": ["Divider", "Separator"]}, {"title": "Spacer", "slug": "spacer", "components": ["Spacer"]}, {"title": "Portal", "slug": "portal", "components": ["Portal"]}, {"title": "Overlay / Backdrop", "slug": "overlay-backdrop", "components": ["Overlay", "Backdrop"]}, {"title": "Slot", "slug": "slot", "components": ["Slot"]}, {"title": "Show / When", "slug": "show-when", "components": ["Show", "When"]}, {"title": "For / Each", "slug": "for-each", "components": ["For", "Each"]}, {"title": "Fragment", "slug": "fragment", "components": ["Fragment"]}, {"title": "VisuallyHidden", "slug": "visuallyhidden", "components": ["VisuallyHidden"]}, {"title": "FocusRing", "slug": "focusring", "components": ["FocusRing"]}, {"title": "FocusScope / FocusTrap", "slug": "focusscope-focustrap", "components": ["FocusScope", "FocusTrap"]}, {"title": "ClickOutside", "slug": "clickoutside", "components": ["ClickOutside"]}, {"title": "HoverArea", "slug": "hoverarea", "components": ["HoverArea"]}, {"title": "Pressable", "slug": "pressable", "components": ["Pressable"]}, {"title": "KeyboardHandler", "slug": "keyboardhandler", "components": ["KeyboardHandler"]}, {"title": "Measure", "slug": "measure", "components": ["Measure"]}, {"title": "IntersectionObserver", "slug": "intersectionobserver", "components": ["IntersectionObserver"]}, {"title": "Clipboard", "slug": "clipboard", "components": ["Clipboard"]}, {"title": "Tooltip Trigger", "slug": "tooltip-trigger", "components": ["Tooltip Trigger"]}]},
{"number": 2, "slug": "typography", "title": "Typography", "summary": "Inter for words, tabular figures for numbers, one ink for everything.", "stories": [{"title": "Heading (H1–H6)", "slug": "heading-h1-h6", "components": ["Heading"]}, {"title": "Title / Subtitle", "slug": "title-subtitle", "components": ["Title", "Subtitle"]}, {"title": "Paragraph", "slug": "paragraph", "components": ["Paragraph"]}, {"title": "Label", "slug": "label", "components": ["Label"]}, {"title": "Caption", "slug": "caption", "components": ["Caption"]}, {"title": "Overline", "slug": "overline", "components": ["Overline"]}, {"title": "Code", "slug": "code", "components": ["Code"]}, {"title": "Kbd", "slug": "kbd", "components": ["Kbd"]}, {"title": "KbdCombo", "slug": "kbdcombo", "components": ["KbdCombo"]}, {"title": "Blockquote", "slug": "blockquote", "components": ["Blockquote"]}, {"title": "Highlight / Mark", "slug": "highlight-mark", "components": ["Highlight", "Mark"]}, {"title": "Truncate / Ellipsis", "slug": "truncate-ellipsis", "components": ["Truncate"]}, {"title": "LineClamp", "slug": "lineclamp", "components": ["LineClamp"]}, {"title": "MiddleEllipsis", "slug": "middleellipsis", "components": ["MiddleEllipsis"]}, {"title": "EllipsisTooltip", "slug": "ellipsistooltip", "components": ["EllipsisTooltip"]}, {"title": "Link", "slug": "link", "components": ["Link"]}, {"title": "ExternalLink", "slug": "externallink", "components": ["ExternalLink"]}, {"title": "RelativeTime", "slug": "relativetime", "components": ["RelativeTime"]}, {"title": "DateTimeText", "slug": "datetimetext", "components": ["DateTimeText"]}, {"title": "NumberText", "slug": "numbertext", "components": ["NumberText"]}, {"title": "CurrencyText", "slug": "currencytext", "components": ["CurrencyText"]}, {"title": "PercentText", "slug": "percenttext", "components": ["PercentText"]}, {"title": "FileSizeText", "slug": "filesizetext", "components": ["FileSizeText"]}, {"title": "DurationText", "slug": "durationtext", "components": ["DurationText"]}, {"title": "PluralText", "slug": "pluraltext", "components": ["PluralText"]}, {"title": "CopyableText", "slug": "copyabletext", "components": ["CopyableText"]}, {"title": "SelectableText", "slug": "selectabletext", "components": ["SelectableText"]}, {"title": "Emoji", "slug": "emoji", "components": ["Emoji"]}, {"title": "Latex / MathInline", "slug": "latex-mathinline", "components": ["Latex", "MathInline"]}, {"title": "AnimatedNumber", "slug": "animatednumber", "components": ["AnimatedNumber"]}, {"title": "Typewriter", "slug": "typewriter", "components": ["Typewriter"]}, {"title": "GradientText", "slug": "gradienttext", "components": ["GradientText"]}, {"title": "ShimmerText", "slug": "shimmertext", "components": ["ShimmerText"]}]},
{"number": 3, "slug": "layout", "title": "Layout", "summary": "Stacks, grids, splits, docks. Structure that stays out of the way.", "stories": [{"title": "Stack / HStack / VStack", "slug": "stack-hstack-vstack", "components": ["Stack", "HStack", "VStack"]}, {"title": "Flex", "slug": "flex", "components": ["Flex"]}, {"title": "Grid / GridItem", "slug": "grid-griditem", "components": ["Grid", "GridItem"]}, {"title": "SimpleGrid", "slug": "simplegrid", "components": ["SimpleGrid"]}, {"title": "Masonry", "slug": "masonry", "components": ["Masonry"]}, {"title": "Center", "slug": "center", "components": ["Center"]}, {"title": "Container", "slug": "container", "components": ["Container"]}, {"title": "AspectRatio", "slug": "aspectratio", "components": ["AspectRatio"]}, {"title": "Inset / Padding", "slug": "inset-padding", "components": ["Inset", "Padding"]}, {"title": "Wrap", "slug": "wrap", "components": ["Wrap"]}, {"title": "Absolute / Positioned", "slug": "absolute-positioned", "components": ["Absolute", "Positioned"]}, {"title": "Layer / ZStack", "slug": "layer-zstack", "components": ["Layer", "ZStack"]}, {"title": "ScrollArea", "slug": "scrollarea", "components": ["ScrollArea"]}, {"title": "Scrollbar", "slug": "scrollbar", "components": ["Scrollbar"]}, {"title": "ScrollShadow", "slug": "scrollshadow", "components": ["ScrollShadow"]}, {"title": "ScrollToTop", "slug": "scrolltotop", "components": ["ScrollToTop"]}, {"title": "StickyHeader", "slug": "stickyheader", "components": ["StickyHeader"]}, {"title": "SplitPane", "slug": "splitpane", "components": ["SplitPane"]}, {"title": "ResizeHandle", "slug": "resizehandle", "components": ["ResizeHandle"]}, {"title": "Collapsible", "slug": "collapsible", "components": ["Collapsible"]}, {"title": "Accordion / AccordionItem", "slug": "accordion-accordionitem", "components": ["Accordion", "AccordionItem"]}, {"title": "Card / CardHeader / CardBody / CardFooter", "slug": "card-cardheader-cardbody-cardfooter", "components": ["Card", "CardHeader", "CardBody", "CardFooter"]}, {"title": "Panel / PanelHeader", "slug": "panel-panelheader", "components": ["Panel", "PanelHeader"]}, {"title": "Section / SectionHeader", "slug": "section-sectionheader", "components": ["Section", "SectionHeader"]}, {"title": "Group / Fieldset", "slug": "group-fieldset", "components": ["Group", "Fieldset"]}, {"title": "Frame", "slug": "frame", "components": ["Frame"]}, {"title": "Well", "slug": "well", "components": ["Well"]}, {"title": "Sidebar", "slug": "sidebar", "components": ["Sidebar"]}, {"title": "Drawer", "slug": "drawer", "components": ["Drawer"]}, {"title": "Sheet", "slug": "sheet", "components": ["Sheet"]}, {"title": "Page / PageHeader / PageContent", "slug": "page-pageheader-pagecontent", "components": ["Page", "PageHeader", "PageContent"]}, {"title": "AppShell", "slug": "appshell", "components": ["AppShell"]}, {"title": "MasterDetail", "slug": "masterdetail", "components": ["MasterDetail"]}, {"title": "Dock / DockPanel", "slug": "dock-dockpanel", "components": ["Dock", "DockPanel"]}, {"title": "DockZone / DropIndicator", "slug": "dockzone-dropindicator", "components": ["DockZone", "DropIndicator"]}, {"title": "FloatingPanel", "slug": "floatingpanel", "components": ["FloatingPanel"]}, {"title": "Pane / PaneGroup", "slug": "pane-panegroup", "components": ["Pane", "PaneGroup"]}, {"title": "Workspace", "slug": "workspace", "components": ["Workspace"]}, {"title": "Viewport", "slug": "viewport", "components": ["Viewport"]}]},
-{"number": 4, "slug": "shell", "title": "Window & Shell", "summary": "Title bars, rails, tabs, and the windows around an app.", "stories": [{"title": "TitleBar", "slug": "titlebar", "components": ["TitleBar"]}, {"title": "WindowControls / TrafficLights", "slug": "windowcontrols-trafficlights", "components": ["WindowControls", "TrafficLights"]}, {"title": "WindowDragRegion", "slug": "windowdragregion", "components": ["WindowDragRegion"]}, {"title": "WindowResizeBorder", "slug": "windowresizeborder", "components": ["WindowResizeBorder"]}, {"title": "NativeMenu / MenuBar / JumpList", "slug": "nativemenu-menubar-jumplist", "components": ["NativeMenu", "MenuBar", "JumpList"]}, {"title": "Toolbar / ToolbarGroup / ToolbarSeparator", "slug": "toolbar-toolbargroup-toolbarseparator", "components": ["Toolbar", "ToolbarGroup", "ToolbarSeparator"]}, {"title": "StatusBar / StatusBarItem", "slug": "statusbar-statusbaritem", "components": ["StatusBar", "StatusBarItem"]}, {"title": "ActivityBar / NavigationRail", "slug": "activitybar-navigationrail", "components": ["ActivityBar", "NavigationRail"]}, {"title": "TabBar", "slug": "tabbar", "components": ["TabBar"]}, {"title": "SplashScreen", "slug": "splashscreen", "components": ["SplashScreen"]}, {"title": "AboutDialog", "slug": "aboutdialog", "components": ["AboutDialog"]}, {"title": "TrayIcon / TrayMenu", "slug": "trayicon-traymenu", "components": ["TrayIcon", "TrayMenu"]}, {"title": "DockBadge", "slug": "dockbadge", "components": ["DockBadge"]}, {"title": "SystemNotification", "slug": "systemnotification", "components": ["SystemNotification"]}, {"title": "MultiWindow Manager", "slug": "multiwindow-manager", "components": ["MultiWindow Manager"]}, {"title": "WindowSwitcher", "slug": "windowswitcher", "components": ["WindowSwitcher"]}, {"title": "QuickLauncher", "slug": "quicklauncher", "components": ["QuickLauncher"]}, {"title": "MiniWindow / CompactMode / PictureInPicture", "slug": "miniwindow-compactmode-pictureinpicture", "components": ["MiniWindow", "CompactMode", "PictureInPicture"]}, {"title": "UpdateBanner", "slug": "updatebanner", "components": ["UpdateBanner"]}, {"title": "UpdateDialog", "slug": "updatedialog", "components": ["UpdateDialog"]}, {"title": "CrashReporter", "slug": "crashreporter", "components": ["CrashReporter"]}, {"title": "OfflineIndicator", "slug": "offlineindicator", "components": ["OfflineIndicator"]}, {"title": "ZoomControl", "slug": "zoomcontrol", "components": ["ZoomControl"]}]},
+{"number": 4, "slug": "shell", "title": "Window & Shell", "summary": "Title bars, rails, tabs, and the windows around an app.", "stories": [{"title": "TitleBar", "slug": "titlebar", "components": ["TitleBar"]}, {"title": "WindowControls / TrafficLights", "slug": "windowcontrols-trafficlights", "components": ["WindowControls", "TrafficLights"]}, {"title": "WindowDragRegion", "slug": "windowdragregion", "components": ["WindowDragRegion"]}, {"title": "WindowResizeBorder", "slug": "windowresizeborder", "components": ["WindowResizeBorder"]}, {"title": "NativeMenu / MenuBar / JumpList", "slug": "nativemenu-menubar-jumplist", "components": ["NativeMenu", "MenuBar", "JumpList"]}, {"title": "Toolbar / ToolbarGroup / ToolbarSeparator", "slug": "toolbar-toolbargroup-toolbarseparator", "components": ["Toolbar", "ToolbarGroup", "ToolbarSeparator"]}, {"title": "StatusBar / StatusBarItem", "slug": "statusbar-statusbaritem", "components": ["StatusBar", "StatusBarItem"]}, {"title": "ActivityBar / NavigationRail", "slug": "activitybar-navigationrail", "components": ["ActivityBar", "NavigationRail"]}, {"title": "TabBar", "slug": "tabbar", "components": ["TabBar"]}, {"title": "SplashScreen", "slug": "splashscreen", "components": ["SplashScreen"]}, {"title": "AboutDialog", "slug": "aboutdialog", "components": ["AboutDialog"]}, {"title": "TrayIcon / TrayMenu", "slug": "trayicon-traymenu", "components": ["TrayIcon", "TrayMenu"]}, {"title": "DockBadge", "slug": "dockbadge", "components": ["DockBadge"]}, {"title": "SystemNotification", "slug": "systemnotification", "components": ["SystemNotification"]}, {"title": "MultiWindow Manager", "slug": "multiwindow-manager", "components": ["MultiWindow Manager"]}, {"title": "WindowSwitcher", "slug": "windowswitcher", "components": ["WindowSwitcher"]}, {"title": "QuickLauncher", "slug": "quicklauncher", "components": ["QuickLauncher"]}, {"title": "MiniWindow / CompactMode / PictureInPicture", "slug": "miniwindow-compactmode-pictureinpicture", "components": ["MiniWindow", "CompactMode", "PictureInPicture", "AlwaysOnTop"]}, {"title": "UpdateBanner", "slug": "updatebanner", "components": ["UpdateBanner"]}, {"title": "UpdateDialog", "slug": "updatedialog", "components": ["UpdateDialog"]}, {"title": "CrashReporter", "slug": "crashreporter", "components": ["CrashReporter"]}, {"title": "OfflineIndicator", "slug": "offlineindicator", "components": ["OfflineIndicator"]}, {"title": "ZoomControl", "slug": "zoomcontrol", "components": ["ZoomControl"]}]},
{"number": 5, "slug": "buttons", "title": "Buttons & Actions", "summary": "Seven variants, three sizes, one focus ring, and the verbs around them.", "stories": [{"title": "Button", "slug": "button", "components": ["Button"]}, {"title": "Sizes", "slug": "sizes", "components": []}, {"title": "With icons", "slug": "with-icons", "components": []}, {"title": "Icon button", "slug": "icon-button", "components": ["IconButton"]}, {"title": "ShortcutHint", "slug": "shortcuthint", "components": ["ShortcutHint"]}, {"title": "ButtonGroup", "slug": "buttongroup", "components": ["ButtonGroup"]}, {"title": "SplitButton / DropdownButton / MenuButton / LoadingButton", "slug": "splitbutton-dropdownbutton-menubutton-loadingbutton", "components": ["SplitButton", "DropdownButton", "MenuButton", "LoadingButton"]}, {"title": "ToggleButton", "slug": "togglebutton", "components": ["ToggleButton"]}, {"title": "ToggleGroup", "slug": "togglegroup", "components": ["ToggleGroup"]}, {"title": "SegmentedControl", "slug": "segmentedcontrol", "components": ["SegmentedControl"]}, {"title": "FloatingActionButton", "slug": "floatingactionbutton", "components": ["FloatingActionButton"]}, {"title": "ConfirmButton / HoldToConfirm", "slug": "confirmbutton-holdtoconfirm", "components": ["ConfirmButton", "HoldToConfirm"]}, {"title": "CopyButton / ShareButton / CloseButton / BackButton / MoreButton", "slug": "copybutton-sharebutton-closebutton-backbutton-morebutton", "components": ["CopyButton", "ShareButton", "CloseButton", "BackButton", "MoreButton"]}, {"title": "ActionBar", "slug": "actionbar", "components": ["ActionBar"]}, {"title": "BulkActionBar", "slug": "bulkactionbar", "components": ["BulkActionBar"]}, {"title": "ActionSheet", "slug": "actionsheet", "components": ["ActionSheet"]}, {"title": "QuickActions", "slug": "quickactions", "components": ["QuickActions"]}]},
-{"number": 6, "slug": "forms", "title": "Forms", "summary": "Text, choices, dates, colors, files: every way to say what you mean.", "stories": [{"title": "Input / TextField / ClearableInput", "slug": "input-textfield-clearableinput", "components": ["Input", "TextField", "ClearableInput"]}, {"title": "TextArea / AutoResizeInput", "slug": "textarea-autoresizeinput", "components": ["TextArea", "AutoResizeInput"]}, {"title": "PasswordInput", "slug": "passwordinput", "components": ["PasswordInput"]}, {"title": "SearchInput", "slug": "searchinput", "components": ["SearchInput"]}, {"title": "NumberInput", "slug": "numberinput", "components": ["NumberInput"]}, {"title": "ScrubInput", "slug": "scrubinput", "components": ["ScrubInput"]}, {"title": "CurrencyInput / PercentInput / UnitInput", "slug": "currencyinput-percentinput-unitinput", "components": ["CurrencyInput", "PercentInput", "UnitInput"]}, {"title": "EmailInput / UrlInput", "slug": "emailinput-urlinput", "components": ["EmailInput", "UrlInput"]}, {"title": "PhoneInput / MaskedInput", "slug": "phoneinput-maskedinput", "components": ["PhoneInput", "MaskedInput"]}, {"title": "PinInput / OTPInput", "slug": "pininput-otpinput", "components": ["PinInput", "OTPInput"]}, {"title": "InlineEdit / EditableText", "slug": "inlineedit-editabletext", "components": ["InlineEdit", "EditableText"]}, {"title": "InputGroup / InputAddon", "slug": "inputgroup-inputaddon", "components": ["InputGroup", "InputAddon"]}, {"title": "MentionInput / HashtagInput", "slug": "mentioninput-hashtaginput", "components": ["MentionInput", "HashtagInput"]}, {"title": "TagInput / TokenInput", "slug": "taginput-tokeninput", "components": ["TagInput", "TokenInput"]}, {"title": "KeyValueInput / ListInput", "slug": "keyvalueinput-listinput", "components": ["KeyValueInput", "ListInput"]}, {"title": "PathInput", "slug": "pathinput", "components": ["PathInput"]}, {"title": "RegexInput", "slug": "regexinput", "components": ["RegexInput"]}, {"title": "ExpressionInput", "slug": "expressioninput", "components": ["ExpressionInput"]}, {"title": "HotkeyInput / ShortcutRecorder", "slug": "hotkeyinput-shortcutrecorder", "components": ["HotkeyInput", "ShortcutRecorder"]}, {"title": "Checkbox / CheckboxGroup", "slug": "checkbox-checkboxgroup", "components": ["Checkbox", "CheckboxGroup"]}, {"title": "Radio / RadioGroup", "slug": "radio-radiogroup", "components": ["Radio", "RadioGroup"]}, {"title": "CheckboxCard / RadioCard", "slug": "checkboxcard-radiocard", "components": ["CheckboxCard", "RadioCard"]}, {"title": "Switch / Toggle", "slug": "switch-toggle", "components": ["Switch", "Toggle"]}, {"title": "Select / NativeSelect", "slug": "select-nativeselect", "components": ["Select", "NativeSelect"]}, {"title": "ListBox", "slug": "listbox", "components": ["ListBox"]}, {"title": "Combobox / Autocomplete", "slug": "combobox-autocomplete", "components": ["Combobox", "Autocomplete"]}, {"title": "MultiSelect", "slug": "multiselect", "components": ["MultiSelect"]}, {"title": "CascadeSelect / Cascader", "slug": "cascadeselect-cascader", "components": ["CascadeSelect", "Cascader"]}, {"title": "TransferList", "slug": "transferlist", "components": ["Transfer List"]}, {"title": "ChoiceChips / FilterChips", "slug": "choicechips-filterchips", "components": ["ChoiceChips", "FilterChips"]}, {"title": "Rating", "slug": "rating", "components": ["Rating"]}, {"title": "Slider / RangeSlider / VerticalSlider", "slug": "slider-rangeslider-verticalslider", "components": ["Slider", "RangeSlider", "VerticalSlider"]}, {"title": "Knob / Dial / Stepper", "slug": "knob-dial-stepper", "components": ["Knob", "Dial", "Stepper"]}, {"title": "Calendar", "slug": "calendar", "components": ["Calendar"]}, {"title": "DatePicker / DateRangePicker / DateTimePicker / TimePicker", "slug": "datepicker-daterangepicker-datetimepicker-timepicker", "components": ["DatePicker", "DateRangePicker", "DateTimePicker", "TimePicker"]}, {"title": "MonthPicker / YearPicker / QuarterPicker / WeekPicker", "slug": "monthpicker-yearpicker-quarterpicker-weekpicker", "components": ["MonthPicker", "YearPicker", "QuarterPicker", "WeekPicker"]}, {"title": "RelativeDatePicker / TimezoneSelect / DurationPicker", "slug": "relativedatepicker-timezoneselect-durationpicker", "components": ["RelativeDatePicker", "TimezoneSelect", "DurationPicker"]}, {"title": "CronEditor", "slug": "croneditor", "components": ["CronEditor"]}, {"title": "ColorPicker", "slug": "colorpicker", "components": ["ColorPicker"]}, {"title": "ColorSwatch / ColorPalette / EyeDropper", "slug": "colorswatch-colorpalette-eyedropper", "components": ["ColorSwatch", "ColorPalette", "EyeDropper"]}, {"title": "GradientEditor", "slug": "gradienteditor", "components": ["GradientEditor"]}, {"title": "FileInput / DropZone", "slug": "fileinput-dropzone", "components": ["FileInput", "DropZone"]}, {"title": "SignaturePad", "slug": "signaturepad", "components": ["SignaturePad"]}, {"title": "CodeInput / JsonInput", "slug": "codeinput-jsoninput", "components": ["CodeInput", "JsonInput"]}, {"title": "FontPicker", "slug": "fontpicker", "components": ["FontPicker"]}, {"title": "IconPicker / EmojiPicker", "slug": "iconpicker-emojipicker", "components": ["IconPicker", "EmojiPicker"]}, {"title": "LanguageSelect / CountrySelect / CurrencySelect", "slug": "languageselect-countryselect-currencyselect", "components": ["LanguageSelect", "CountrySelect", "CurrencySelect"]}, {"title": "Form / FormSection / FormField / FieldArray / DirtyIndicator", "slug": "form-formsection-formfield-fieldarray-dirtyindicator", "components": ["Form", "FormSection", "FormField", "FieldArray", "DirtyIndicator"]}, {"title": "InlineForm", "slug": "inlineform", "components": ["InlineForm"]}]},
+{"number": 6, "slug": "forms", "title": "Forms", "summary": "Text, choices, dates, colors, files: every way to say what you mean.", "stories": [{"title": "Input / TextField / ClearableInput", "slug": "input-textfield-clearableinput", "components": ["Input", "TextField", "ClearableInput"]}, {"title": "TextArea / AutoResizeInput", "slug": "textarea-autoresizeinput", "components": ["TextArea", "AutoResizeInput"]}, {"title": "PasswordInput", "slug": "passwordinput", "components": ["PasswordInput"]}, {"title": "SearchInput", "slug": "searchinput", "components": ["SearchInput"]}, {"title": "NumberInput", "slug": "numberinput", "components": ["NumberInput"]}, {"title": "ScrubInput", "slug": "scrubinput", "components": ["ScrubInput"]}, {"title": "CurrencyInput / PercentInput / UnitInput", "slug": "currencyinput-percentinput-unitinput", "components": ["CurrencyInput", "PercentInput", "UnitInput"]}, {"title": "EmailInput / UrlInput", "slug": "emailinput-urlinput", "components": ["EmailInput", "UrlInput"]}, {"title": "PhoneInput / MaskedInput", "slug": "phoneinput-maskedinput", "components": ["PhoneInput", "MaskedInput"]}, {"title": "PinInput / OTPInput", "slug": "pininput-otpinput", "components": ["PinInput", "OTPInput"]}, {"title": "InlineEdit / EditableText", "slug": "inlineedit-editabletext", "components": ["InlineEdit", "EditableText"]}, {"title": "InputGroup / InputAddon", "slug": "inputgroup-inputaddon", "components": ["InputGroup", "InputAddon"]}, {"title": "MentionInput / HashtagInput", "slug": "mentioninput-hashtaginput", "components": ["MentionInput", "HashtagInput"]}, {"title": "TagInput / TokenInput", "slug": "taginput-tokeninput", "components": ["TagInput", "TokenInput"]}, {"title": "KeyValueInput / ListInput", "slug": "keyvalueinput-listinput", "components": ["KeyValueInput", "ListInput"]}, {"title": "PathInput", "slug": "pathinput", "components": ["PathInput"]}, {"title": "RegexInput", "slug": "regexinput", "components": ["RegexInput"]}, {"title": "ExpressionInput", "slug": "expressioninput", "components": ["ExpressionInput"]}, {"title": "HotkeyInput / ShortcutRecorder", "slug": "hotkeyinput-shortcutrecorder", "components": ["HotkeyInput", "ShortcutRecorder"]}, {"title": "Checkbox / CheckboxGroup", "slug": "checkbox-checkboxgroup", "components": ["Checkbox", "CheckboxGroup"]}, {"title": "Radio / RadioGroup", "slug": "radio-radiogroup", "components": ["Radio", "RadioGroup"]}, {"title": "CheckboxCard / RadioCard", "slug": "checkboxcard-radiocard", "components": ["CheckboxCard", "RadioCard"]}, {"title": "Switch / Toggle", "slug": "switch-toggle", "components": ["Switch", "Toggle"]}, {"title": "Select / NativeSelect", "slug": "select-nativeselect", "components": ["Select", "NativeSelect"]}, {"title": "ListBox", "slug": "listbox", "components": ["ListBox"]}, {"title": "Combobox / Autocomplete", "slug": "combobox-autocomplete", "components": ["Combobox", "Autocomplete"]}, {"title": "MultiSelect", "slug": "multiselect", "components": ["MultiSelect"]}, {"title": "CascadeSelect / Cascader", "slug": "cascadeselect-cascader", "components": ["CascadeSelect", "Cascader"]}, {"title": "TransferList", "slug": "transferlist", "components": ["Transfer List"]}, {"title": "ChoiceChips / FilterChips", "slug": "choicechips-filterchips", "components": ["ChoiceChips", "FilterChips"]}, {"title": "Rating", "slug": "rating", "components": ["Rating"]}, {"title": "Slider / RangeSlider / VerticalSlider", "slug": "slider-rangeslider-verticalslider", "components": ["Slider", "RangeSlider", "VerticalSlider"]}, {"title": "Knob / Dial / Stepper", "slug": "knob-dial-stepper", "components": ["Knob", "Dial", "Stepper"]}, {"title": "Calendar", "slug": "calendar", "components": ["Calendar"]}, {"title": "DatePicker / DateRangePicker / DateTimePicker / TimePicker", "slug": "datepicker-daterangepicker-datetimepicker-timepicker", "components": ["DatePicker", "DateRangePicker", "DateTimePicker", "TimePicker"]}, {"title": "MonthPicker / YearPicker / QuarterPicker / WeekPicker", "slug": "monthpicker-yearpicker-quarterpicker-weekpicker", "components": ["MonthPicker", "YearPicker", "QuarterPicker", "WeekPicker"]}, {"title": "RelativeDatePicker / TimezoneSelect / DurationPicker", "slug": "relativedatepicker-timezoneselect-durationpicker", "components": ["RelativeDatePicker", "TimezoneSelect", "DurationPicker"]}, {"title": "CronEditor", "slug": "croneditor", "components": ["CronEditor"]}, {"title": "ColorPicker", "slug": "colorpicker", "components": ["ColorPicker"]}, {"title": "ColorSwatch / ColorPalette / EyeDropper", "slug": "colorswatch-colorpalette-eyedropper", "components": ["ColorSwatch", "ColorPalette", "EyeDropper"]}, {"title": "GradientEditor", "slug": "gradienteditor", "components": ["GradientEditor"]}, {"title": "FileInput / DropZone", "slug": "fileinput-dropzone", "components": ["FileInput", "DropZone"]}, {"title": "SignaturePad", "slug": "signaturepad", "components": ["SignaturePad"]}, {"title": "CodeInput / JsonInput", "slug": "codeinput-jsoninput", "components": ["CodeInput", "JsonInput"]}, {"title": "FontPicker", "slug": "fontpicker", "components": ["FontPicker"]}, {"title": "IconPicker / EmojiPicker", "slug": "iconpicker-emojipicker", "components": ["IconPicker", "EmojiPicker"]}, {"title": "LanguageSelect / CountrySelect / CurrencySelect", "slug": "languageselect-countryselect-currencyselect", "components": ["LanguageSelect", "CountrySelect", "CurrencySelect"]}, {"title": "Form / FormSection / FormField / FieldArray / DirtyIndicator", "slug": "form-formsection-formfield-fieldarray-dirtyindicator", "components": ["Form", "FormSection", "FormField", "FieldArray", "DirtyIndicator", "FormLabel", "FormError"]}, {"title": "InlineForm", "slug": "inlineform", "components": ["InlineForm"]}]},
{"number": 7, "slug": "navigation", "title": "Navigation", "summary": "Tabs, paths, places and palettes: where you are, and the ways out.", "stories": [{"title": "Tabs", "slug": "tabs", "components": ["Tabs"]}, {"title": "EditorTabs / TabOverflowMenu", "slug": "editortabs-taboverflowmenu", "components": ["EditorTabs", "TabOverflowMenu"]}, {"title": "Breadcrumb", "slug": "breadcrumb", "components": ["Breadcrumb"]}, {"title": "Pagination", "slug": "pagination", "components": ["Pagination"]}, {"title": "Steps / Wizard", "slug": "steps-wizard", "components": ["Steps", "Wizard"]}, {"title": "Sidebar Navigation / NavItem / NavGroup", "slug": "sidebar-navigation-navitem-navgroup", "components": ["Sidebar Navigation", "NavItem", "NavGroup"]}, {"title": "NavigationMenu", "slug": "navigationmenu", "components": ["NavigationMenu"]}, {"title": "BackForwardNavigation / History", "slug": "backforwardnavigation-history", "components": ["BackForwardNavigation"]}, {"title": "Anchor / TableOfContents", "slug": "anchor-tableofcontents", "components": ["Anchor", "TableOfContents"]}, {"title": "JumpTo / GoToLine", "slug": "jumpto-gotoline", "components": ["JumpTo", "GoToLine"]}, {"title": "CommandPalette", "slug": "commandpalette", "components": ["CommandPalette"]}, {"title": "QuickOpen", "slug": "quickopen", "components": ["QuickOpen"]}, {"title": "QuickSwitcher", "slug": "quickswitcher", "components": ["QuickSwitcher"]}, {"title": "SearchPalette / SpotlightSearch / QuickLauncher", "slug": "searchpalette-spotlightsearch-quicklauncher", "components": ["SearchPalette", "SpotlightSearch", "QuickLauncher"]}]},
{"number": 8, "slug": "menus", "title": "Menus", "summary": "Rows of actions that open from a button, a right click or an arrow, and nest.", "stories": [{"title": "Menu / MenuItem / MenuGroup / MenuSeparator / SubMenu / MenuItemShortcut / MenuItemIcon", "slug": "menu-menuitem-menugroup-menuseparator-submenu-menuitemshortcut-menuitemicon", "components": ["Menu", "MenuItem", "MenuGroup", "MenuSeparator", "SubMenu", "MenuItemShortcut", "MenuItemIcon"]}, {"title": "CheckboxMenuItem / RadioMenuItem", "slug": "checkboxmenuitem-radiomenuitem", "components": ["CheckboxMenuItem", "RadioMenuItem"]}, {"title": "DropdownMenu / SplitButton / OverflowMenu", "slug": "dropdownmenu-splitbutton-overflowmenu", "components": ["DropdownMenu", "SplitButton", "OverflowMenu"]}, {"title": "ContextMenu", "slug": "contextmenu", "components": ["ContextMenu"]}, {"title": "MenuBar Menu", "slug": "menubar-menu", "components": ["MenuBar Menu"]}, {"title": "MegaMenu", "slug": "megamenu", "components": ["MegaMenu"]}, {"title": "SearchableMenu", "slug": "searchablemenu", "components": ["SearchableMenu"]}, {"title": "PieMenu / RadialMenu", "slug": "piemenu-radialmenu", "components": ["PieMenu", "RadialMenu"]}]},
{"number": 9, "slug": "overlays", "title": "Overlays", "summary": "Panels over the page: anchored to a control, over a scrim, or over everything.", "stories": [{"title": "Popover / DropdownPanel / InlinePopup", "slug": "popover-dropdownpanel-inlinepopup", "components": ["Popover", "DropdownPanel", "InlinePopup"]}, {"title": "HoverCard", "slug": "hovercard", "components": ["HoverCard"]}, {"title": "Dialog / Modal / AlertDialog / ConfirmDialog / PromptDialog / FullscreenDialog", "slug": "dialog-modal-alertdialog-confirmdialog-promptdialog-fullscreendialog", "components": ["Dialog", "Modal", "AlertDialog", "ConfirmDialog", "PromptDialog", "FullscreenDialog"]}, {"title": "Lightbox", "slug": "lightbox", "components": ["Lightbox"]}, {"title": "Spotlight / Coachmark / Tour", "slug": "spotlight-coachmark-tour", "components": ["Spotlight", "Coachmark", "Tour"]}, {"title": "FloatingToolbar", "slug": "floatingtoolbar", "components": ["FloatingToolbar"]}, {"title": "Callout / Peek", "slug": "callout-peek", "components": ["Callout", "Peek"]}, {"title": "Tooltip / Sheet / Drawer / DropdownPanel / InlinePopup / ToastViewport", "slug": "tooltip-sheet-drawer-dropdownpanel-inlinepopup-toastviewport", "components": ["Tooltip", "Sheet", "Drawer", "DropdownPanel", "InlinePopup", "ToastViewport"]}]},
@@ -12,7 +12,7 @@
{"number": 11, "slug": "motion", "title": "Loading & Motion", "summary": "Waiting, shown honestly, and the motion everything else moves with.", "stories": [{"title": "Spinner / DotsLoader / BarsLoader / PulseLoader / RingLoader / OrbitLoader / WaveLoader / InlineLoader", "slug": "spinner-dotsloader-barsloader-pulseloader-ringloader-orbitloader-waveloader-inlineloader", "components": ["Spinner", "DotsLoader", "BarsLoader", "PulseLoader", "RingLoader", "OrbitLoader", "WaveLoader", "InlineLoader"]}, {"title": "Skeleton / SkeletonText / SkeletonAvatar / SkeletonCard / SkeletonTable", "slug": "skeleton-skeletontext-skeletonavatar-skeletoncard-skeletontable", "components": ["Skeleton", "SkeletonText", "SkeletonAvatar", "SkeletonCard", "SkeletonTable"]}, {"title": "Shimmer", "slug": "shimmer", "components": ["Shimmer"]}, {"title": "LoadingButton", "slug": "loadingbutton", "components": ["LoadingButton"]}, {"title": "LoadMore", "slug": "loadmore", "components": ["LoadMore"]}, {"title": "ProgressBar / ProgressCircle / ProgressRing", "slug": "progressbar-progresscircle-progressring", "components": ["ProgressBar", "ProgressCircle", "ProgressRing"]}, {"title": "LoadingOverlay", "slug": "loadingoverlay", "components": ["LoadingOverlay"]}, {"title": "LazyLoad", "slug": "lazyload", "components": ["LazyLoad"]}, {"title": "Suspense / AsyncView", "slug": "suspense-asyncview", "components": ["Suspense", "AsyncView"]}, {"title": "RefreshIndicator / TypingIndicator", "slug": "refreshindicator-typingindicator", "components": ["RefreshIndicator", "TypingIndicator"]}, {"title": "UploadList", "slug": "uploadlist", "components": ["UploadList"]}, {"title": "Transition", "slug": "transition", "components": ["Transition"]}, {"title": "Stagger", "slug": "stagger", "components": ["Stagger"]}, {"title": "AnimatePresence", "slug": "animatepresence", "components": ["AnimatePresence"]}, {"title": "Flip", "slug": "flip", "components": ["Flip"]}, {"title": "Reorder", "slug": "reorder", "components": ["Reorder"]}, {"title": "Marquee", "slug": "marquee", "components": ["Marquee"]}, {"title": "Ripple / Confetti", "slug": "ripple-confetti", "components": ["Ripple", "Confetti"]}, {"title": "Glow / Pulse", "slug": "glow-pulse", "components": ["Glow", "Pulse"]}, {"title": "Blink / Flash / Shake", "slug": "blink-flash-shake", "components": ["Blink", "Flash", "Shake"]}, {"title": "ParticleBackground / AnimatedGradient / Lottie Player", "slug": "particlebackground-animatedgradient-lottie-player", "components": ["ParticleBackground", "AnimatedGradient", "Lottie Player"]}]},
{"number": 12, "slug": "data", "title": "Data Display", "summary": "People, numbers and records, shown plainly.", "stories": [{"title": "Badge / CountBadge / DotBadge", "slug": "badge-countbadge-dotbadge", "components": ["Badge", "CountBadge", "DotBadge"]}, {"title": "Tag / Chip", "slug": "tag-chip", "components": ["Tag", "Chip"]}, {"title": "Avatar / AvatarUpload", "slug": "avatar-avatarupload", "components": ["Avatar", "AvatarUpload"]}, {"title": "AvatarGroup / UserChip", "slug": "avatargroup-userchip", "components": ["AvatarGroup", "UserChip"]}, {"title": "Statistic / KPI Card / Metric / TrendIndicator", "slug": "statistic-kpi-card-metric-trendindicator", "components": ["Statistic", "KPI Card", "Metric", "TrendIndicator"]}, {"title": "DescriptionList / KeyValueList / InfoRow", "slug": "descriptionlist-keyvaluelist-inforow", "components": ["DescriptionList", "KeyValueList", "InfoRow"]}, {"title": "PropertyGrid", "slug": "propertygrid", "components": ["PropertyGrid"]}, {"title": "Timeline / TimelineItem", "slug": "timeline-timelineitem", "components": ["Timeline", "TimelineItem"]}, {"title": "ActivityFeed", "slug": "activityfeed", "components": ["ActivityFeed"]}, {"title": "Changelog", "slug": "changelog", "components": ["Changelog"]}, {"title": "Carousel", "slug": "carousel", "components": ["Carousel"]}, {"title": "Gallery", "slug": "gallery", "components": ["Gallery"]}, {"title": "BeforeAfter", "slug": "beforeafter", "components": ["BeforeAfter"]}, {"title": "Watermark", "slug": "watermark", "components": ["Watermark"]}, {"title": "QRCode / Barcode", "slug": "qrcode-barcode", "components": ["QRCode", "Barcode"]}, {"title": "Meter / Gauge / UsageBar", "slug": "meter-gauge-usagebar", "components": ["Meter", "Gauge", "UsageBar"]}, {"title": "Stars / Rating display", "slug": "stars-rating-display", "components": ["Rating display"]}, {"title": "Comparison", "slug": "comparison", "components": ["Comparison"]}]},
{"number": 13, "slug": "lists", "title": "Lists & Trees", "summary": "Rows to read, pick, reorder and swipe; lists long enough to need care.", "stories": [{"title": "List / ListItem", "slug": "list-listitem", "components": ["List", "ListItem"]}, {"title": "SelectableList", "slug": "selectablelist", "components": ["SelectableList"]}, {"title": "SortableList / ReorderableList", "slug": "sortablelist-reorderablelist", "components": ["SortableList", "ReorderableList"]}, {"title": "SwipeableListItem", "slug": "swipeablelistitem", "components": ["SwipeableListItem"]}, {"title": "VirtualList", "slug": "virtuallist", "components": ["VirtualList"]}, {"title": "InfiniteList", "slug": "infinitelist", "components": ["InfiniteList"]}, {"title": "GroupedList / SectionList", "slug": "groupedlist-sectionlist", "components": ["GroupedList", "SectionList"]}, {"title": "Tree / TreeView / VirtualTree", "slug": "tree-treeview-virtualtree", "components": ["Tree", "TreeView", "VirtualTree"]}, {"title": "CheckboxTree", "slug": "checkboxtree", "components": ["CheckboxTree"]}, {"title": "TreeSelect", "slug": "treeselect", "components": ["TreeSelect"]}, {"title": "Outline / NestedList", "slug": "outline-nestedlist", "components": ["Outline", "NestedList"]}, {"title": "FileTree", "slug": "filetree", "components": ["FileTree"]}, {"title": "DirectoryListing", "slug": "directorylisting", "components": ["DirectoryListing"]}]},
-{"number": 14, "slug": "tables", "title": "Tables", "summary": "Rows and columns that sort, filter, page and select, and stay quick at a hundred thousand rows.", "stories": [{"title": "Table", "slug": "table", "components": ["Table"]}, {"title": "DataTable / TableToolbar / FilterBuilder / SortBuilder / ColumnVisibility / CellRenderer / RowSelection / TableDensity / AggregationFooter / ConditionalFormatting", "slug": "datatable-tabletoolbar-filterbuilder-sortbuilder-columnvisibility-cellrenderer-rowselection-tabledensity-aggregationfooter-conditionalformatting", "components": ["DataTable", "TableToolbar", "FilterBuilder", "SortBuilder", "ColumnVisibility", "CellRenderer", "RowSelection", "TableDensity", "AggregationFooter", "ConditionalFormatting"]}, {"title": "ColumnPinning / ColumnResizer / ColumnReorder", "slug": "columnpinning-columnresizer-columnreorder", "components": ["ColumnPinning", "ColumnResizer", "ColumnReorder"]}, {"title": "RowExpansion / InlineRowEdit", "slug": "rowexpansion-inlinerowedit", "components": ["RowExpansion", "InlineRowEdit"]}, {"title": "RowGrouping", "slug": "rowgrouping", "components": ["RowGrouping"]}, {"title": "DataGrid", "slug": "datagrid", "components": ["DataGrid"]}, {"title": "Spreadsheet", "slug": "spreadsheet", "components": ["Spreadsheet"]}, {"title": "TreeTable", "slug": "treetable", "components": ["TreeTable"]}, {"title": "PivotTable", "slug": "pivottable", "components": ["PivotTable"]}, {"title": "VirtualTable", "slug": "virtualtable", "components": ["VirtualTable"]}, {"title": "HeatmapTable", "slug": "heatmaptable", "components": ["HeatmapTable"]}]},
+{"number": 14, "slug": "tables", "title": "Tables", "summary": "Rows and columns that sort, filter, page and select, and stay quick at a hundred thousand rows.", "stories": [{"title": "Table", "slug": "table", "components": ["Table"]}, {"title": "DataTable / TableToolbar / FilterBuilder / SortBuilder / ColumnVisibility / CellRenderer / RowSelection / TableDensity / AggregationFooter / ConditionalFormatting", "slug": "datatable-tabletoolbar-filterbuilder-sortbuilder-columnvisibility-cellrenderer-rowselection-tabledensity-aggregationfooter-conditionalformatting", "components": ["DataTable", "TableToolbar", "FilterBuilder", "SortBuilder", "ColumnVisibility", "CellRenderer", "RowSelection", "TableDensity", "AggregationFooter", "ConditionalFormatting", "Sparkline"]}, {"title": "ColumnPinning / ColumnResizer / ColumnReorder", "slug": "columnpinning-columnresizer-columnreorder", "components": ["ColumnPinning", "ColumnResizer", "ColumnReorder"]}, {"title": "RowExpansion / InlineRowEdit", "slug": "rowexpansion-inlinerowedit", "components": ["RowExpansion", "InlineRowEdit"]}, {"title": "RowGrouping", "slug": "rowgrouping", "components": ["RowGrouping"]}, {"title": "DataGrid", "slug": "datagrid", "components": ["DataGrid"]}, {"title": "Spreadsheet", "slug": "spreadsheet", "components": ["Spreadsheet"]}, {"title": "TreeTable", "slug": "treetable", "components": ["TreeTable"]}, {"title": "PivotTable", "slug": "pivottable", "components": ["PivotTable"]}, {"title": "VirtualTable", "slug": "virtualtable", "components": ["VirtualTable"]}, {"title": "HeatmapTable", "slug": "heatmaptable", "components": ["HeatmapTable"]}]},
{"number": 15, "slug": "charts", "title": "Charts", "summary": "Lines, bars, parts of a whole, spreads, flows and schedules on quiet axes, with legends, tooltips, zoom and export.", "stories": [{"title": "LineChart / ChartAxis / ChartGrid / ChartLegend / ChartTooltip / ChartCrosshair / ChartAnnotation / ChartZoom / ChartExport", "slug": "linechart-chartaxis-chartgrid-chartlegend-charttooltip-chartcrosshair-chartannotation-chartzoom-chartexport", "components": ["LineChart", "ChartAxis", "ChartGrid", "ChartLegend", "ChartTooltip", "ChartCrosshair", "ChartAnnotation", "ChartZoom", "ChartExport"]}, {"title": "AreaChart / StackedArea / BarChart", "slug": "areachart-stackedarea-barchart", "components": ["AreaChart", "StackedArea", "BarChart"]}, {"title": "PieChart / DonutChart", "slug": "piechart-donutchart", "components": ["PieChart", "DonutChart"]}, {"title": "ScatterChart / BubbleChart", "slug": "scatterchart-bubblechart", "components": ["ScatterChart", "BubbleChart"]}, {"title": "RadarChart", "slug": "radarchart", "components": ["RadarChart"]}, {"title": "HeatmapChart / CalendarHeatmap", "slug": "heatmapchart-calendarheatmap", "components": ["HeatmapChart", "CalendarHeatmap"]}, {"title": "Treemap / Sunburst", "slug": "treemap-sunburst", "components": ["Treemap", "Sunburst"]}, {"title": "SankeyChart / FunnelChart", "slug": "sankeychart-funnelchart", "components": ["SankeyChart", "FunnelChart"]}, {"title": "WaterfallChart", "slug": "waterfallchart", "components": ["WaterfallChart"]}, {"title": "Histogram / BoxPlot / ViolinPlot", "slug": "histogram-boxplot-violinplot", "components": ["Histogram", "BoxPlot", "ViolinPlot"]}, {"title": "GanttChart", "slug": "ganttchart", "components": ["GanttChart"]}, {"title": "NetworkGraph / ForceGraph / ChordDiagram / ParallelCoordinates", "slug": "networkgraph-forcegraph-chorddiagram-parallelcoordinates", "components": ["NetworkGraph", "ForceGraph", "ChordDiagram", "ParallelCoordinates"]}, {"title": "Bullet Chart / ProgressChart", "slug": "bullet-chart-progresschart", "components": ["Bullet Chart", "ProgressChart"]}, {"title": "RealtimeChart", "slug": "realtimechart", "components": ["RealtimeChart"]}]},
{"number": 16, "slug": "finance", "title": "Finance", "summary": "Market charts with the studies traders read, books, quotes, order entry and portfolios.", "stories": [{"title": "CandlestickChart / OHLCChart / HeikinAshiChart / LineQuoteChart / VolumeChart / ChartTypeSwitcher / TimeRangeSelector / IntervalSelector", "slug": "candlestickchart-ohlcchart-heikinashichart-linequotechart-volumechart-charttypeswitcher-timerangeselector-intervalselector", "components": ["CandlestickChart", "OHLCChart", "HeikinAshiChart", "LineQuoteChart", "VolumeChart", "ChartTypeSwitcher", "TimeRangeSelector", "IntervalSelector"]}, {"title": "IndicatorOverlay / IndicatorPane / IndicatorSelector / CompareSymbol / PriceAlertLine", "slug": "indicatoroverlay-indicatorpane-indicatorselector-comparesymbol-pricealertline", "components": ["IndicatorOverlay", "IndicatorPane", "IndicatorSelector", "CompareSymbol", "PriceAlertLine"]}, {"title": "DrawingTools / DrawingToolbar", "slug": "drawingtools-drawingtoolbar", "components": ["DrawingTools", "DrawingToolbar"]}, {"title": "DepthChart", "slug": "depthchart", "components": ["DepthChart"]}, {"title": "MarketProfile / VolumeProfile", "slug": "marketprofile-volumeprofile", "components": ["MarketProfile", "VolumeProfile"]}, {"title": "RenkoChart / PointAndFigure", "slug": "renkochart-pointandfigure", "components": ["RenkoChart", "PointAndFigure"]}, {"title": "MultiChartLayout / ChartSync", "slug": "multichartlayout-chartsync", "components": ["MultiChartLayout", "ChartSync"]}, {"title": "Ticker / TickerTape / QuoteCard / PriceText / PriceChangeBadge", "slug": "ticker-tickertape-quotecard-pricetext-pricechangebadge", "components": ["Ticker", "TickerTape", "QuoteCard", "PriceText", "PriceChangeBadge"]}, {"title": "OrderBook / SpreadIndicator / BidAskBar / Level2 Quotes", "slug": "orderbook-spreadindicator-bidaskbar-level2-quotes", "components": ["OrderBook", "SpreadIndicator", "BidAskBar", "Level2 Quotes"]}, {"title": "TimeAndSales / TradeTape / MarketDepthLadder / DOM", "slug": "timeandsales-tradetape-marketdepthladder-dom", "components": ["TimeAndSales", "TradeTape", "MarketDepthLadder", "DOM"]}, {"title": "OrderEntry / TradePanel / QuickTradeButtons / OrderConfirmDialog", "slug": "orderentry-tradepanel-quicktradebuttons-orderconfirmdialog", "components": ["OrderEntry", "TradePanel", "QuickTradeButtons", "OrderConfirmDialog"]}, {"title": "PositionTable / OrderTable / TradeHistoryTable / PnLDisplay", "slug": "positiontable-ordertable-tradehistorytable-pnldisplay", "components": ["PositionTable", "OrderTable", "TradeHistoryTable", "PnLDisplay"]}, {"title": "LeverageSlider / MarginIndicator / RiskMeter", "slug": "leverageslider-marginindicator-riskmeter", "components": ["LeverageSlider", "MarginIndicator", "RiskMeter"]}, {"title": "OptionChain / GreeksTable / PayoffDiagram", "slug": "optionchain-greekstable-payoffdiagram", "components": ["OptionChain", "GreeksTable", "PayoffDiagram"]}, {"title": "Watchlist / SymbolBadge / SymbolSearch", "slug": "watchlist-symbolbadge-symbolsearch", "components": ["Watchlist", "SymbolBadge", "SymbolSearch"]}, {"title": "MarketHeatmap / SectorTreemap", "slug": "marketheatmap-sectortreemap", "components": ["MarketHeatmap", "SectorTreemap"]}, {"title": "Screener / FilterPanel", "slug": "screener-filterpanel", "components": ["Screener", "FilterPanel"]}, {"title": "MarketOverview / IndexCard / MarketStatus / TradingSessionClock", "slug": "marketoverview-indexcard-marketstatus-tradingsessionclock", "components": ["MarketOverview", "IndexCard", "MarketStatus", "TradingSessionClock"]}, {"title": "EconomicCalendar / EarningsCalendar / NewsFeed", "slug": "economiccalendar-earningscalendar-newsfeed", "components": ["EconomicCalendar", "EarningsCalendar", "NewsFeed"]}, {"title": "PortfolioSummary / AssetAllocationChart / PerformanceChart / SentimentGauge", "slug": "portfoliosummary-assetallocationchart-performancechart-sentimentgauge", "components": ["PortfolioSummary", "AssetAllocationChart", "PerformanceChart", "SentimentGauge"]}, {"title": "DividendTable / FinancialStatementTable", "slug": "dividendtable-financialstatementtable", "components": ["DividendTable", "FinancialStatementTable"]}, {"title": "CurrencyConverter / CryptoWalletCard / TransactionList / Candle Countdown", "slug": "currencyconverter-cryptowalletcard-transactionlist-candle-countdown", "components": ["CurrencyConverter", "CryptoWalletCard", "TransactionList", "Candle Countdown"]}]},
{"number": 17, "slug": "editor", "title": "Editor", "summary": "A code editor with the gutter, folds and cursors it needs, the help a language server gives, search, the panels around it and its status row.", "stories": [{"title": "CodeEditor / EditorGutter / LineNumbers / FoldingControl / Minimap / Ruler / IndentGuide / BracketMatcher / RainbowBrackets / MultiCursor / SelectionHighlight / StickyScroll / Breadcrumb / InlayHints / CodeLens / InlineDecoration", "slug": "codeeditor-editorgutter-linenumbers-foldingcontrol-minimap-ruler-indentguide-bracketmatcher-rainbowbrackets-multicursor-selectionhighlight-stickyscroll-breadcrumb-inlayhints-codelens-inlinedecoration", "components": ["CodeEditor", "EditorGutter", "LineNumbers", "FoldingControl", "MiniMap", "Ruler", "IndentGuide", "BracketMatcher", "RainbowBrackets", "MultiCursor", "SelectionHighlight", "StickyScroll", "Breadcrumb", "InlayHints", "CodeLens", "InlineDecoration"]}, {"title": "WhitespaceRenderer / CursorRenderer", "slug": "whitespacerenderer-cursorrenderer", "components": ["WhitespaceRenderer", "CursorRenderer"]}, {"title": "InlineDiff / GhostText / InlineChat / ReadOnlyBanner / VimModeIndicator", "slug": "inlinediff-ghosttext-inlinechat-readonlybanner-vimmodeindicator", "components": ["InlineDiff", "GhostText", "InlineChat", "ReadOnlyBanner", "VimModeIndicator"]}, {"title": "CompletionMenu / SignatureHelp / HoverInfo", "slug": "completionmenu-signaturehelp-hoverinfo", "components": ["CompletionMenu", "SignatureHelp", "HoverInfo"]}, {"title": "CodeActionMenu / RenameInput / PeekView / ReferencesPanel / SymbolOutline / GoToSymbol / CallHierarchy / TypeHierarchy", "slug": "codeactionmenu-renameinput-peekview-referencespanel-symboloutline-gotosymbol-callhierarchy-typehierarchy", "components": ["CodeActionMenu", "RenameInput", "PeekView", "ReferencesPanel", "SymbolOutline", "GoToSymbol", "CallHierarchy", "TypeHierarchy"]}, {"title": "FindWidget / ReplaceWidget", "slug": "findwidget-replacewidget", "components": ["FindWidget", "ReplaceWidget"]}, {"title": "SearchPanel / SearchResultItem / SearchFilters", "slug": "searchpanel-searchresultitem-searchfilters", "components": ["SearchPanel", "SearchResultItem", "SearchFilters"]}, {"title": "ProblemsPanel / DiagnosticsList / OutputPanel", "slug": "problemspanel-diagnosticslist-outputpanel", "components": ["ProblemsPanel", "DiagnosticsList", "OutputPanel"]}, {"title": "DebugConsole / ExtensionsPanel / PluginList", "slug": "debugconsole-extensionspanel-pluginlist", "components": ["DebugConsole", "ExtensionsPanel", "PluginList"]}, {"title": "SettingsEditor / KeybindingsEditor", "slug": "settingseditor-keybindingseditor", "components": ["SettingsEditor", "KeybindingsEditor"]}, {"title": "WelcomePage / RecentProjects / ProjectSwitcher / ThemePreview / TaskRunner / RunConfiguration", "slug": "welcomepage-recentprojects-projectswitcher-themepreview-taskrunner-runconfiguration", "components": ["WelcomePage", "RecentProjects", "ProjectSwitcher", "ThemePreview", "TaskRunner", "RunConfiguration"]}, {"title": "CursorPosition / LanguageMode / Encoding / LineEnding / IndentSettings / BranchIndicator / LspStatus / NotificationBell", "slug": "cursorposition-languagemode-encoding-lineending-indentsettings-branchindicator-lspstatus-notificationbell", "components": ["CursorPosition", "LanguageMode", "Encoding", "LineEnding", "IndentSettings", "BranchIndicator", "LspStatus", "NotificationBell"]}]},
@@ -21,7 +21,7 @@
{"number": 20, "slug": "debug", "title": "Debug", "summary": "A paused program: its breakpoints, stack, threads and values, memory and machine code; profiles and network.", "stories": [{"title": "DebugToolbar", "slug": "debugtoolbar", "components": ["DebugToolbar"]}, {"title": "BreakpointList / BreakpointGutter / CallStack / ThreadList", "slug": "breakpointlist-breakpointgutter-callstack-threadlist", "components": ["BreakpointList", "BreakpointGutter", "CallStack", "ThreadList"]}, {"title": "VariablesPanel / WatchPanel / ConsoleREPL", "slug": "variablespanel-watchpanel-consolerepl", "components": ["VariablesPanel", "WatchPanel", "ConsoleREPL"]}, {"title": "MemoryViewer / HexViewer / Disassembly", "slug": "memoryviewer-hexviewer-disassembly", "components": ["MemoryViewer", "HexViewer", "Disassembly"]}, {"title": "PerformanceProfiler / Flamegraph / TimelineProfiler", "slug": "performanceprofiler-flamegraph-timelineprofiler", "components": ["PerformanceProfiler", "Flamegraph", "TimelineProfiler"]}, {"title": "NetworkInspector", "slug": "networkinspector", "components": ["NetworkInspector"]}]},
{"number": 21, "slug": "documents", "title": "Documents", "summary": "Markdown written and read, blocks like a notebook's, and a knowledge base around them.", "stories": [{"title": "RichTextEditor / FixedFormatToolbar / FloatingFormatToolbar / LinkEditor / MentionMenu / EmojiAutocomplete / WordCount / ReadingTime", "slug": "richtexteditor-fixedformattoolbar-floatingformattoolbar-linkeditor-mentionmenu-emojiautocomplete-wordcount-readingtime", "components": ["RichTextEditor", "FixedFormatToolbar", "FloatingFormatToolbar", "LinkEditor", "MentionMenu", "EmojiAutocomplete", "WordCount", "ReadingTime"]}, {"title": "MarkdownEditor", "slug": "markdowneditor", "components": ["MarkdownEditor"]}, {"title": "BlockEditor / BlockHandle / SlashMenu / PlaceholderText", "slug": "blockeditor-blockhandle-slashmenu-placeholdertext", "components": ["BlockEditor", "BlockHandle", "SlashMenu", "PlaceholderText"]}, {"title": "Block types / TableEditor / ImageEditorBlock / MathEditor / DiagramBlock / CodeBlockEditor", "slug": "block-types-tableeditor-imageeditorblock-matheditor-diagramblock-codeblockeditor", "components": ["Block types", "TableEditor", "ImageEditorBlock", "MathEditor", "DiagramBlock", "CodeBlockEditor"]}, {"title": "TodoItem / Checklist", "slug": "todoitem-checklist", "components": ["TodoItem", "Checklist"]}, {"title": "MarkdownRenderer / TableOfContents / DocumentOutline / ReadingProgress", "slug": "markdownrenderer-tableofcontents-documentoutline-readingprogress", "components": ["MarkdownRenderer", "TableOfContents", "DocumentOutline", "ReadingProgress"]}, {"title": "DocumentViewer / PDFViewer / PageThumbnailList", "slug": "documentviewer-pdfviewer-pagethumbnaillist", "components": ["DocumentViewer", "PDFViewer", "PageThumbnailList"]}, {"title": "OfficePreview", "slug": "officepreview", "components": ["OfficePreview"]}, {"title": "EpubReader", "slug": "epubreader", "components": ["EpubReader"]}, {"title": "Footnote / Glossary / TooltipTerm", "slug": "footnote-glossary-tooltipterm", "components": ["Footnote", "Glossary", "TooltipTerm"]}, {"title": "FocusMode / ZenMode", "slug": "focusmode-zenmode", "components": ["FocusMode", "ZenMode"]}, {"title": "PrintPreview", "slug": "printpreview", "components": ["PrintPreview"]}, {"title": "PageTree / Favorites / Pinned", "slug": "pagetree-favorites-pinned", "components": ["PageTree", "Favorites", "Pinned"]}, {"title": "PageCover / PageIcon / PageProperties", "slug": "pagecover-pageicon-pageproperties", "components": ["PageCover", "PageIcon", "PageProperties"]}, {"title": "Backlinks / GraphView", "slug": "backlinks-graphview", "components": ["Backlinks", "GraphView"]}, {"title": "TemplatePicker", "slug": "templatepicker", "components": ["TemplatePicker"]}, {"title": "TrashBin", "slug": "trashbin", "components": ["TrashBin"]}, {"title": "VersionHistory / PageHistoryDiff", "slug": "versionhistory-pagehistorydiff", "components": ["VersionHistory", "PageHistoryDiff"]}]},
{"number": 22, "slug": "collab", "title": "Collaboration", "summary": "People in the same document: who is here and where, comments and reactions, suggested changes, and sharing.", "stories": [{"title": "PresenceAvatars / LiveIndicator / FollowMode / RemoteCursor / RemoteSelection", "slug": "presenceavatars-liveindicator-followmode-remotecursor-remoteselection", "components": ["PresenceAvatars", "LiveIndicator", "FollowMode", "RemoteCursor", "RemoteSelection"]}, {"title": "CommentThread / Reply / Reactions / ReactionPicker", "slug": "commentthread-reply-reactions-reactionpicker", "components": ["CommentThread", "Reply", "Reactions", "ReactionPicker"]}, {"title": "CommentBubble / CommentMarker", "slug": "commentbubble-commentmarker", "components": ["CommentBubble", "CommentMarker"]}, {"title": "CommentSidebar", "slug": "commentsidebar", "components": ["CommentSidebar"]}, {"title": "Annotation / Highlight", "slug": "annotation-highlight", "components": ["Annotation", "Highlight"]}, {"title": "SuggestionMode / TrackChanges", "slug": "suggestionmode-trackchanges", "components": ["SuggestionMode", "TrackChanges"]}, {"title": "ShareDialog / InviteInput / PermissionSelect / AccessList", "slug": "sharedialog-inviteinput-permissionselect-accesslist", "components": ["ShareDialog", "InviteInput", "PermissionSelect", "AccessList"]}, {"title": "ActivityLog → data_display::ActivityFeed", "slug": "activitylog-data-display-activityfeed", "components": ["ActivityLog"]}]},
-{"number": 23, "slug": "chat", "title": "AI Chat", "summary": "A conversation with an assistant: messages that stream in, code and media inside them, and what can be done with each.", "stories": [{"title": "ChatContainer / MessageList / MessageBubble / MessageAvatar / MessageHeader / MessageFooter / DateSeparator / ScrollToBottomButton", "slug": "chatcontainer-messagelist-messagebubble-messageavatar-messageheader-messagefooter-dateseparator-scrolltobottombutton", "components": ["ChatContainer", "MessageList", "MessageBubble", "MessageAvatar", "MessageHeader", "MessageFooter", "DateSeparator", "ScrollToBottomButton"]}, {"title": "StreamingText / StreamingMarkdown / StreamingCursor", "slug": "streamingtext-streamingmarkdown-streamingcursor", "components": ["StreamingText", "StreamingMarkdown", "StreamingCursor"]}, {"title": "CodeBlock", "slug": "codeblock", "components": ["CodeBlock"]}, {"title": "MathBlock / TableBlock / MermaidRenderer", "slug": "mathblock-tableblock-mermaidrenderer", "components": ["MathBlock", "TableBlock", "MermaidRenderer"]}, {"title": "ImageMessage / ImageGrid / FileMessage / AudioMessage / VideoMessage / LinkPreviewCard", "slug": "imagemessage-imagegrid-filemessage-audiomessage-videomessage-linkpreviewcard", "components": ["ImageMessage", "ImageGrid", "FileMessage", "AudioMessage", "VideoMessage", "LinkPreviewCard"]}, {"title": "QuoteReply / MessageActions / MessageEditor / BranchNavigator / RegenerateButton / StopGeneratingButton / ContinueButton", "slug": "quotereply-messageactions-messageeditor-branchnavigator-regeneratebutton-stopgeneratingbutton-continuebutton", "components": ["QuoteReply", "MessageActions", "MessageEditor", "BranchNavigator", "RegenerateButton", "StopGeneratingButton", "ContinueButton"]}, {"title": "ErrorMessage / RetryMessage / RateLimitNotice / FeedbackForm", "slug": "errormessage-retrymessage-ratelimitnotice-feedbackform", "components": ["ErrorMessage", "RetryMessage", "RateLimitNotice", "FeedbackForm"]}, {"title": "ThinkingBlock / ReasoningPanel / ThinkingIndicator / ThinkingDuration", "slug": "thinkingblock-reasoningpanel-thinkingindicator-thinkingduration", "components": ["ThinkingBlock", "ReasoningPanel", "ThinkingIndicator", "ThinkingDuration"]}, {"title": "CitationBadge / InlineCitation / SourceCard / SourceList / SourcesPanel", "slug": "citationbadge-inlinecitation-sourcecard-sourcelist-sourcespanel", "components": ["CitationBadge", "InlineCitation", "SourceCard", "SourceList", "SourcesPanel"]}, {"title": "SearchProgress / WebResultCard / DocumentChunkPreview", "slug": "searchprogress-webresultcard-documentchunkpreview", "components": ["SearchProgress", "WebResultCard", "DocumentChunkPreview"]}, {"title": "PromptInput / Composer / AttachmentButton / AttachmentChip / AttachmentPreview / PasteImagePreview / DragDropOverlay / ContextChips / SlashCommandMenu / ContextMentionMenu / SendButton / InputHint", "slug": "promptinput-composer-attachmentbutton-attachmentchip-attachmentpreview-pasteimagepreview-dragdropoverlay-contextchips-slashcommandmenu-contextmentionmenu-sendbutton-inputhint", "components": ["PromptInput", "Composer", "AttachmentButton", "AttachmentChip", "AttachmentPreview", "PasteImagePreview", "DragDropOverlay", "ContextChips", "SlashCommandMenu", "ContextMentionMenu", "SendButton", "InputHint"]}, {"title": "ModelSelector / ModeSelector / ToolToggleMenu / PromptTemplateMenu", "slug": "modelselector-modeselector-tooltogglemenu-prompttemplatemenu", "components": ["ModelSelector", "ModeSelector", "ToolToggleMenu", "PromptTemplateMenu"]}, {"title": "TemperatureSlider / ParameterPanel / SystemPromptEditor / TokenCounter / ContextWindowMeter / CostEstimator", "slug": "temperatureslider-parameterpanel-systemprompteditor-tokencounter-contextwindowmeter-costestimator", "components": ["TemperatureSlider", "ParameterPanel", "SystemPromptEditor", "TokenCounter", "ContextWindowMeter", "CostEstimator"]}, {"title": "ConversationList / ConversationItem / ConversationSearch / NewChatButton", "slug": "conversationlist-conversationitem-conversationsearch-newchatbutton", "components": ["ConversationList", "ConversationItem", "ConversationSearch", "NewChatButton"]}, {"title": "FolderList / ProjectList / ProjectKnowledgePanel", "slug": "folderlist-projectlist-projectknowledgepanel", "components": ["FolderList", "ProjectList", "ProjectKnowledgePanel"]}, {"title": "SharedConversationView / ConversationExport", "slug": "sharedconversationview-conversationexport", "components": ["SharedConversationView", "ConversationExport"]}, {"title": "WelcomeScreen / Greeting / SuggestionChips / StarterPrompts / CapabilityCards", "slug": "welcomescreen-greeting-suggestionchips-starterprompts-capabilitycards", "components": ["WelcomeScreen", "Greeting", "SuggestionChips", "StarterPrompts", "CapabilityCards"]}, {"title": "FollowUpSuggestions", "slug": "followupsuggestions", "components": ["FollowUpSuggestions"]}, {"title": "PromptLibrary", "slug": "promptlibrary", "components": ["PromptLibrary"]}]},
+{"number": 23, "slug": "chat", "title": "AI Chat", "summary": "A conversation with an assistant: messages that stream in, code and media inside them, and what can be done with each.", "stories": [{"title": "ChatContainer / MessageList / MessageBubble / MessageAvatar / MessageHeader / MessageFooter / DateSeparator / ScrollToBottomButton", "slug": "chatcontainer-messagelist-messagebubble-messageavatar-messageheader-messagefooter-dateseparator-scrolltobottombutton", "components": ["ChatContainer", "MessageList", "MessageBubble", "MessageAvatar", "MessageHeader", "MessageFooter", "DateSeparator", "ScrollToBottomButton"]}, {"title": "StreamingText / StreamingMarkdown / StreamingCursor", "slug": "streamingtext-streamingmarkdown-streamingcursor", "components": ["StreamingText", "StreamingMarkdown", "StreamingCursor"]}, {"title": "CodeBlock", "slug": "codeblock", "components": ["CodeBlock"]}, {"title": "MathBlock / TableBlock / MermaidRenderer", "slug": "mathblock-tableblock-mermaidrenderer", "components": ["MathBlock", "TableBlock", "MermaidRenderer"]}, {"title": "ImageMessage / ImageGrid / FileMessage / AudioMessage / VideoMessage / LinkPreviewCard", "slug": "imagemessage-imagegrid-filemessage-audiomessage-videomessage-linkpreviewcard", "components": ["ImageMessage", "ImageGrid", "FileMessage", "AudioMessage", "VideoMessage", "LinkPreviewCard"]}, {"title": "QuoteReply / MessageActions / MessageEditor / BranchNavigator / RegenerateButton / StopGeneratingButton / ContinueButton", "slug": "quotereply-messageactions-messageeditor-branchnavigator-regeneratebutton-stopgeneratingbutton-continuebutton", "components": ["QuoteReply", "MessageActions", "MessageEditor", "BranchNavigator", "RegenerateButton", "StopGeneratingButton", "ContinueButton"]}, {"title": "ErrorMessage / RetryMessage / RateLimitNotice / FeedbackForm", "slug": "errormessage-retrymessage-ratelimitnotice-feedbackform", "components": ["ErrorMessage", "RetryMessage", "RateLimitNotice", "FeedbackForm"]}, {"title": "ThinkingBlock / ReasoningPanel / ThinkingIndicator / ThinkingDuration", "slug": "thinkingblock-reasoningpanel-thinkingindicator-thinkingduration", "components": ["ThinkingBlock", "ReasoningPanel", "ThinkingIndicator", "ThinkingDuration"]}, {"title": "CitationBadge / InlineCitation / SourceCard / SourceList / SourcesPanel", "slug": "citationbadge-inlinecitation-sourcecard-sourcelist-sourcespanel", "components": ["CitationBadge", "InlineCitation", "SourceCard", "SourceList", "SourcesPanel"]}, {"title": "SearchProgress / WebResultCard / DocumentChunkPreview", "slug": "searchprogress-webresultcard-documentchunkpreview", "components": ["SearchProgress", "WebResultCard", "DocumentChunkPreview"]}, {"title": "PromptInput / Composer / AttachmentButton / AttachmentChip / AttachmentPreview / PasteImagePreview / DragDropOverlay / ContextChips / SlashCommandMenu / ContextMentionMenu / SendButton / InputHint", "slug": "promptinput-composer-attachmentbutton-attachmentchip-attachmentpreview-pasteimagepreview-dragdropoverlay-contextchips-slashcommandmenu-contextmentionmenu-sendbutton-inputhint", "components": ["PromptInput", "Composer", "AttachmentButton", "AttachmentChip", "AttachmentPreview", "PasteImagePreview", "DragDropOverlay", "ContextChips", "SlashCommandMenu", "ContextMentionMenu", "SendButton", "InputHint", "VoiceInputButton", "VoiceWaveform"]}, {"title": "ModelSelector / ModeSelector / ToolToggleMenu / PromptTemplateMenu", "slug": "modelselector-modeselector-tooltogglemenu-prompttemplatemenu", "components": ["ModelSelector", "ModeSelector", "ToolToggleMenu", "PromptTemplateMenu"]}, {"title": "TemperatureSlider / ParameterPanel / SystemPromptEditor / TokenCounter / ContextWindowMeter / CostEstimator", "slug": "temperatureslider-parameterpanel-systemprompteditor-tokencounter-contextwindowmeter-costestimator", "components": ["TemperatureSlider", "ParameterPanel", "SystemPromptEditor", "TokenCounter", "ContextWindowMeter", "CostEstimator"]}, {"title": "ConversationList / ConversationItem / ConversationSearch / NewChatButton", "slug": "conversationlist-conversationitem-conversationsearch-newchatbutton", "components": ["ConversationList", "ConversationItem", "ConversationSearch", "NewChatButton"]}, {"title": "FolderList / ProjectList / ProjectKnowledgePanel", "slug": "folderlist-projectlist-projectknowledgepanel", "components": ["FolderList", "ProjectList", "ProjectKnowledgePanel"]}, {"title": "SharedConversationView / ConversationExport", "slug": "sharedconversationview-conversationexport", "components": ["SharedConversationView", "ConversationExport"]}, {"title": "WelcomeScreen / Greeting / SuggestionChips / StarterPrompts / CapabilityCards", "slug": "welcomescreen-greeting-suggestionchips-starterprompts-capabilitycards", "components": ["WelcomeScreen", "Greeting", "SuggestionChips", "StarterPrompts", "CapabilityCards"]}, {"title": "FollowUpSuggestions", "slug": "followupsuggestions", "components": ["FollowUpSuggestions"]}, {"title": "PromptLibrary", "slug": "promptlibrary", "components": ["PromptLibrary"]}]},
{"number": 24, "slug": "agent", "title": "Agent", "summary": "An assistant at work: the tools it calls, what it asks before it acts, how far it has come, what it would change, what it sees and what it makes.", "stories": [{"title": "ToolCallCard / ToolCallGroup", "slug": "toolcallcard-toolcallgroup", "components": ["ToolCallCard", "ToolCallGroup"]}, {"title": "ToolApprovalDialog / PermissionPrompt", "slug": "toolapprovaldialog-permissionprompt", "components": ["ToolApprovalDialog", "PermissionPrompt"]}, {"title": "AgentStepList / TaskTimeline / AgentPlan / TodoList / AgentStatus / AgentProgress", "slug": "agentsteplist-tasktimeline-agentplan-todolist-agentstatus-agentprogress", "components": ["AgentStepList", "TaskTimeline", "AgentPlan", "TodoList", "AgentStatus", "AgentProgress"]}, {"title": "SubAgentTree", "slug": "subagenttree", "components": ["SubAgentTree"]}, {"title": "FileChangeCard / MultiFileDiff Review / CommandExecutionCard", "slug": "filechangecard-multifilediff-review-commandexecutioncard", "components": ["FileChangeCard", "MultiFileDiff Review", "CommandExecutionCard"]}, {"title": "BrowserPreview / ScreenshotStream / ComputerUseViewer", "slug": "browserpreview-screenshotstream-computeruseviewer", "components": ["BrowserPreview", "ScreenshotStream", "ComputerUseViewer"]}, {"title": "ArtifactPanel / ArtifactVersionSwitcher / LivePreview", "slug": "artifactpanel-artifactversionswitcher-livepreview", "components": ["ArtifactPanel", "ArtifactVersionSwitcher", "LivePreview"]}, {"title": "SandboxStatus", "slug": "sandboxstatus", "components": ["SandboxStatus"]}, {"title": "MCPServerList / ConnectorList / ToolRegistry Panel", "slug": "mcpserverlist-connectorlist-toolregistry-panel", "components": ["MCPServerList", "ConnectorList", "ToolRegistry Panel"]}, {"title": "MemoryPanel / CheckpointList / Rewind", "slug": "memorypanel-checkpointlist-rewind", "components": ["MemoryPanel", "CheckpointList", "Rewind"]}, {"title": "InterruptButton / HumanInputRequest", "slug": "interruptbutton-humaninputrequest", "components": ["InterruptButton", "HumanInputRequest"]}, {"title": "TokenUsageChart / CostBreakdown", "slug": "tokenusagechart-costbreakdown", "components": ["TokenUsageChart", "CostBreakdown"]}, {"title": "TraceViewer / EvalResultTable", "slug": "traceviewer-evalresulttable", "components": ["TraceViewer", "EvalResultTable"]}]},
{"number": 25, "slug": "generative", "title": "Generative", "summary": "Making pictures, sound and video with a model: the prompt and its settings, the queue and what comes back, the canvas, the models behind them, and the data and prompts they work from.", "stories": [{"title": "ImageGenerationPanel / PromptEnhancer / NegativePromptInput / StylePresetPicker / AspectRatioPicker / SeedInput", "slug": "imagegenerationpanel-promptenhancer-negativepromptinput-stylepresetpicker-aspectratiopicker-seedinput", "components": ["ImageGenerationPanel", "PromptEnhancer", "NegativePromptInput", "StylePresetPicker", "AspectRatioPicker", "SeedInput"]}, {"title": "GenerationQueue", "slug": "generationqueue", "components": ["GenerationQueue"]}, {"title": "GenerationGrid / ImageCompare", "slug": "generationgrid-imagecompare", "components": ["GenerationGrid", "ImageCompare"]}, {"title": "VariationPicker / ABCompareView", "slug": "variationpicker-abcompareview", "components": ["VariationPicker", "ABCompareView"]}, {"title": "InpaintCanvas / MaskBrush", "slug": "inpaintcanvas-maskbrush", "components": ["InpaintCanvas", "MaskBrush"]}, {"title": "AudioGenerationPlayer", "slug": "audiogenerationplayer", "components": ["AudioGenerationPlayer"]}, {"title": "TTSVoicePicker", "slug": "ttsvoicepicker", "components": ["TTSVoicePicker"]}, {"title": "VideoGenerationTimeline", "slug": "videogenerationtimeline", "components": ["VideoGenerationTimeline"]}, {"title": "ModelCard", "slug": "modelcard", "components": ["ModelCard"]}, {"title": "ModelDownloadManager", "slug": "modeldownloadmanager", "components": ["ModelDownloadManager"]}, {"title": "ModelStatus / HardwareMonitor", "slug": "modelstatus-hardwaremonitor", "components": ["ModelStatus", "HardwareMonitor"]}, {"title": "FineTuneJobCard", "slug": "finetunejobcard", "components": ["FineTuneJobCard"]}, {"title": "DatasetViewer → tables::DataTable", "slug": "datasetviewer-tables-datatable", "components": ["DatasetViewer"]}, {"title": "EmbeddingVisualizer", "slug": "embeddingvisualizer", "components": ["EmbeddingVisualizer"]}, {"title": "PromptPlayground", "slug": "promptplayground", "components": ["PromptPlayground"]}, {"title": "PromptDiff / PromptVersionHistory", "slug": "promptdiff-promptversionhistory", "components": ["PromptDiff", "PromptVersionHistory"]}]},
{"number": 26, "slug": "media", "title": "Media", "summary": "Pictures, video and sound: looking closely, cropping and marking up, playing, and the controls and devices around them.", "stories": [{"title": "ImageViewer", "slug": "imageviewer", "components": ["ImageViewer"]}, {"title": "ImageThumbnail / Lightbox → overlays::Lightbox", "slug": "imagethumbnail-lightbox-overlays-lightbox", "components": ["ImageThumbnail", "Lightbox"]}, {"title": "ImageCropper", "slug": "imagecropper", "components": ["ImageCropper"]}, {"title": "ImageUpload", "slug": "imageupload", "components": ["ImageUpload"]}, {"title": "ImageAnnotator", "slug": "imageannotator", "components": ["ImageAnnotator"]}, {"title": "VideoPlayer", "slug": "videoplayer", "components": ["VideoPlayer"]}, {"title": "VideoTimeline / Scrubber", "slug": "videotimeline-scrubber", "components": ["VideoTimeline", "Scrubber"]}, {"title": "VideoThumbnailStrip", "slug": "videothumbnailstrip", "components": ["VideoThumbnailStrip"]}, {"title": "SubtitleEditor", "slug": "subtitleeditor", "components": ["SubtitleEditor"]}, {"title": "AudioPlayer", "slug": "audioplayer", "components": ["AudioPlayer"]}, {"title": "AudioWaveform", "slug": "audiowaveform", "components": ["AudioWaveform"]}, {"title": "AudioSpectrum / Visualizer", "slug": "audiospectrum-visualizer", "components": ["AudioSpectrum", "Visualizer"]}, {"title": "VolumeControl", "slug": "volumecontrol", "components": ["VolumeControl"]}, {"title": "PlaybackSpeedControl", "slug": "playbackspeedcontrol", "components": ["PlaybackSpeedControl"]}, {"title": "MediaControls", "slug": "mediacontrols", "components": ["MediaControls"]}, {"title": "Playlist", "slug": "playlist", "components": ["Playlist"]}, {"title": "ScreenRecorderControls", "slug": "screenrecordercontrols", "components": ["ScreenRecorderControls"]}, {"title": "CameraPreview", "slug": "camerapreview", "components": ["CameraPreview"]}, {"title": "MicLevelMeter", "slug": "miclevelmeter", "components": ["MicLevelMeter"]}, {"title": "DeviceSelector", "slug": "deviceselector", "components": ["DeviceSelector"]}, {"title": "3DModelViewer", "slug": "3dmodelviewer", "components": ["3DModelViewer"]}]},
@@ -33,11 +33,11 @@
{"number": 32, "slug": "canvas", "title": "Canvas & Design", "summary": "An endless plane to lay work on, the tools and panels around it, and graphs of nodes.", "stories": [{"title": "InfiniteCanvas · CanvasGrid / Guides · Ruler · ArtboardFrame · ZoomControls / ZoomIndicator · MiniMap", "slug": "infinitecanvas-canvasgrid-guides-ruler-artboardframe-zoomcontrols-zoomindicator-minimap", "components": ["InfiniteCanvas", "CanvasGrid", "Guides", "Ruler", "ArtboardFrame", "ZoomControls", "ZoomIndicator", "MiniMap"]}, {"title": "ToolPalette · SelectionBox · TransformHandles · SnapIndicator · ShapeTools · PenTool / PathEditor · TextTool · BrushTool / BrushSettings · HistoryPanel", "slug": "toolpalette-selectionbox-transformhandles-snapindicator-shapetools-pentool-patheditor-texttool-brushtool-brushsettings-historypanel", "components": ["ToolPalette", "SelectionBox", "TransformHandles", "SnapIndicator", "ShapeTools", "PenTool", "PathEditor", "TextTool", "BrushTool", "BrushSettings", "HistoryPanel"]}, {"title": "LayerPanel · InspectorPanel · AlignmentToolbar · AssetPanel", "slug": "layerpanel-inspectorpanel-alignmenttoolbar-assetpanel", "components": ["LayerPanel", "InspectorPanel", "AlignmentToolbar", "AssetPanel"]}, {"title": "ColorPanel · GradientPanel · ShadowEditor · BorderEditor · TypographyPanel", "slug": "colorpanel-gradientpanel-shadoweditor-bordereditor-typographypanel", "components": ["ColorPanel", "GradientPanel", "ShadowEditor", "BorderEditor", "TypographyPanel"]}, {"title": "ConstraintsEditor · AutoLayoutControls · ExportPanel", "slug": "constraintseditor-autolayoutcontrols-exportpanel", "components": ["ConstraintsEditor", "AutoLayoutControls", "ExportPanel"]}, {"title": "NodeEditor / NodeGraph · Node / Port / Edge / Connection", "slug": "nodeeditor-nodegraph-node-port-edge-connection", "components": ["NodeEditor", "NodeGraph", "Node", "Port", "Edge", "Connection"]}, {"title": "FlowChart / DiagramEditor · Connector Line", "slug": "flowchart-diagrameditor-connector-line", "components": ["FlowChart", "DiagramEditor", "Connector Line"]}, {"title": "MindMap", "slug": "mindmap", "components": ["MindMap"]}, {"title": "Whiteboard · StickyNote", "slug": "whiteboard-stickynote", "components": ["Whiteboard", "StickyNote"]}]},
{"number": 33, "slug": "devtools", "title": "DB & Dev Tools", "summary": "Connections, schemas and queries, data to read, requests to send, and the machines that run them.", "stories": [{"title": "ConnectionManager · ConnectionForm", "slug": "connectionmanager-connectionform", "components": ["ConnectionManager", "ConnectionForm"]}, {"title": "SchemaTree · ERDiagram", "slug": "schematree-erdiagram", "components": ["SchemaTree", "ERDiagram"]}, {"title": "QueryEditor → editor::CodeEditor · QueryResultGrid → tables::DataGrid · QueryHistory · QueryPlanViewer", "slug": "queryeditor-editor-codeeditor-queryresultgrid-tables-datagrid-queryhistory-queryplanviewer", "components": ["QueryEditor", "QueryResultGrid", "QueryHistory", "QueryPlanViewer"]}, {"title": "TableStructureEditor · IndexManager", "slug": "tablestructureeditor-indexmanager", "components": ["TableStructureEditor", "IndexManager"]}, {"title": "RedisKeyBrowser", "slug": "rediskeybrowser", "components": ["RedisKeyBrowser"]}, {"title": "DocumentViewer (MongoDB / JSON) → devtools::JsonViewer · JsonViewer / JsonTree · JsonEditor · YamlViewer · XmlViewer", "slug": "documentviewer-mongodb-json-devtools-jsonviewer-jsonviewer-jsontree-jsoneditor-yamlviewer-xmlviewer", "components": ["DocumentViewer", "JsonViewer", "JsonTree", "JsonEditor", "YamlViewer", "XmlViewer"]}, {"title": "ApiRequestBuilder · ResponseViewer · HeadersTable · QueryParamsEditor → forms::KeyValueInput · EnvironmentSelector · CollectionTree", "slug": "apirequestbuilder-responseviewer-headerstable-queryparamseditor-forms-keyvalueinput-environmentselector-collectiontree", "components": ["ApiRequestBuilder", "ResponseViewer", "HeadersTable", "QueryParamsEditor", "EnvironmentSelector", "CollectionTree"]}, {"title": "WebSocketConsole", "slug": "websocketconsole", "components": ["WebSocketConsole"]}, {"title": "GraphQLExplorer", "slug": "graphqlexplorer", "components": ["GraphQLExplorer"]}, {"title": "RegexTester · Base64 / Encoder · ColorContrastChecker", "slug": "regextester-base64-encoder-colorcontrastchecker", "components": ["RegexTester", "Base64", "Encoder", "ColorContrastChecker"]}, {"title": "ContainerList · PodList · ResourceMonitor", "slug": "containerlist-podlist-resourcemonitor", "components": ["ContainerList", "PodList", "ResourceMonitor"]}]},
{"number": 34, "slug": "dashboard", "title": "Dashboard & Monitoring", "summary": "Widgets on a grid you arrange, what is firing and what is up, and the stream of what happens.", "stories": [{"title": "Dashboard Grid · Widget / DashboardCard · RefreshIntervalSelector · DashboardFilterBar · StatCard → data_display::Statistic · MetricsChart → charts::LineChart · ResourceGauge → data_display::Gauge", "slug": "dashboard-grid-widget-dashboardcard-refreshintervalselector-dashboardfilterbar-statcard-data-display-statistic-metricschart-charts-linechart-resourcegauge-data-display-gauge", "components": ["Dashboard Grid", "Widget", "DashboardCard", "RefreshIntervalSelector", "DashboardFilterBar", "StatCard", "MetricsChart", "ResourceGauge"]}, {"title": "UptimeBar · ServiceStatus · HealthCheck Indicator", "slug": "uptimebar-servicestatus-healthcheck-indicator", "components": ["UptimeBar", "ServiceStatus", "HealthCheck Indicator"]}, {"title": "AlertList · IncidentCard", "slug": "alertlist-incidentcard", "components": ["AlertList", "IncidentCard"]}, {"title": "EventStream · LogStream → terminal::LogViewer · TraceWaterfall → debug::TimelineProfiler · SystemMonitor → devtools::ResourceMonitor · ProcessTable → terminal::ProcessList · NetworkGraph (throughput) → charts::RealtimeChart · MapView / GeoHeatmap → maps::MapView, maps::GeoHeatmap · WorldMap → maps::WorldMap", "slug": "eventstream-logstream-terminal-logviewer-tracewaterfall-debug-timelineprofiler-systemmonitor-devtools-resourcemonitor-processtable-terminal-processlist-networkgraph-throughput-charts-realtimechart-mapview-geoheatmap-maps-mapview-maps-geoheatmap-worldmap-maps-worldmap", "components": ["EventStream", "LogStream", "TraceWaterfall", "SystemMonitor", "ProcessTable", "NetworkGraph", "MapView", "GeoHeatmap", "WorldMap"]}]},
-{"number": 35, "slug": "settings", "title": "Settings", "summary": "A settings window: its sections, a search over them, and the controls each one holds.", "stories": [{"title": "SettingsLayout · SettingsSection · SettingsRow · SettingsSearch", "slug": "settingslayout-settingssection-settingsrow-settingssearch", "components": ["SettingsLayout", "SettingsSection", "SettingsRow", "SettingsSearch"]}]},
+{"number": 35, "slug": "settings", "title": "Settings", "summary": "A settings window: its sections, a search over them, and the controls each one holds.", "stories": [{"title": "SettingsLayout · SettingsSection · SettingsRow · SettingsSearch", "slug": "settingslayout-settingssection-settingsrow-settingssearch", "components": ["SettingsLayout", "ThemeSelector", "AccentColorPicker", "FontSizeControl", "DensitySelector", "KeyboardShortcutsList", "ProxySettings", "PrivacySettings", "NotificationSettings", "StartupSettings", "StorageSettings", "ResetToDefault", "ImportExportSettings", "AdvancedSettings", "DeveloperMode Toggle", "SettingsSection", "SettingsRow", "SettingsSearch"]}]},
{"number": 36, "slug": "account", "title": "Account", "summary": "Signing in and up, a link by email, a second factor, and the account once inside.", "stories": [{"title": "LoginForm · OAuthButtons", "slug": "loginform-oauthbuttons", "components": ["LoginForm", "OAuthButtons"]}, {"title": "SignupForm", "slug": "signupform", "components": ["SignupForm"]}, {"title": "MagicLinkForm · ForgotPassword", "slug": "magiclinkform-forgotpassword", "components": ["MagicLinkForm", "ForgotPassword"]}, {"title": "TwoFactorInput", "slug": "twofactorinput", "components": ["TwoFactorInput"]}, {"title": "AccountSwitcher · WorkspaceSwitcher / OrgSwitcher · UserMenu", "slug": "accountswitcher-workspaceswitcher-orgswitcher-usermenu", "components": ["AccountSwitcher", "WorkspaceSwitcher", "OrgSwitcher", "UserMenu"]}, {"title": "ProfileCard · ProfileEditor", "slug": "profilecard-profileeditor", "components": ["ProfileCard", "ProfileEditor"]}, {"title": "SessionList · ApiKeyManager", "slug": "sessionlist-apikeymanager", "components": ["SessionList", "ApiKeyManager"]}, {"title": "SubscriptionCard / PlanBadge · UsageQuota · PaymentMethodForm", "slug": "subscriptioncard-planbadge-usagequota-paymentmethodform", "components": ["SubscriptionCard", "PlanBadge", "UsageQuota", "PaymentMethodForm"]}, {"title": "BillingHistory · UpgradePrompt / Paywall", "slug": "billinghistory-upgradeprompt-paywall", "components": ["BillingHistory", "UpgradePrompt", "Paywall"]}, {"title": "TeamMemberTable · RoleSelector · InvitationList", "slug": "teammembertable-roleselector-invitationlist", "components": ["TeamMemberTable", "RoleSelector", "InvitationList"]}]},
{"number": 37, "slug": "onboarding", "title": "Onboarding & Help", "summary": "A first run in steps, what is new called out, first things to do, and help where it is needed.", "stories": [{"title": "OnboardingWizard · WelcomeTour", "slug": "onboardingwizard-welcometour", "components": ["OnboardingWizard", "WelcomeTour"]}, {"title": "Coachmark / Hotspot · FeatureHighlight / NewBadge", "slug": "coachmark-hotspot-featurehighlight-newbadge", "components": ["Coachmark", "Hotspot", "FeatureHighlight", "NewBadge"]}, {"title": "Checklist (first-run tasks)", "slug": "checklist-first-run-tasks", "components": ["Checklist"]}, {"title": "HelpTooltip · InlineHelp · EmptyStateWithAction", "slug": "helptooltip-inlinehelp-emptystatewithaction", "components": ["HelpTooltip", "InlineHelp", "EmptyStateWithAction"]}, {"title": "HelpPanel / DocsSidebar", "slug": "helppanel-docssidebar", "components": ["HelpPanel", "DocsSidebar"]}, {"title": "KeyboardShortcutCheatsheet · WhatsNewDialog", "slug": "keyboardshortcutcheatsheet-whatsnewdialog", "components": ["KeyboardShortcutCheatsheet", "WhatsNewDialog"]}, {"title": "FeedbackWidget · ContactSupport", "slug": "feedbackwidget-contactsupport", "components": ["FeedbackWidget", "ContactSupport"]}]},
{"number": 38, "slug": "interaction", "title": "Interaction", "summary": "Drag and drop, resizing and turning, band selection, presses and gestures, keys, scrolling and focus.", "stories": [{"title": "Draggable · Droppable / DropTarget · DragOverlay / DragPreview · DragGhost", "slug": "draggable-droppable-droptarget-dragoverlay-dragpreview-dragghost", "components": ["Draggable", "Droppable", "DropTarget", "DragOverlay", "DragPreview", "DragGhost"]}, {"title": "Resizable · Rotatable · Selectable / SelectionArea · RubberBandSelection · Sortable", "slug": "resizable-rotatable-selectable-selectionarea-rubberbandselection-sortable", "components": ["Resizable", "Rotatable", "Selectable", "SelectionArea", "RubberBandSelection", "Sortable"]}, {"title": "LongPress · DoubleClick · Gesture · PanZoom", "slug": "longpress-doubleclick-gesture-panzoom", "components": ["LongPress", "DoubleClick", "Gesture", "PanZoom"]}, {"title": "Hotkeys / KeyBinding · KeyChord", "slug": "hotkeys-keybinding-keychord", "components": ["Hotkeys", "KeyBinding", "KeyChord"]}, {"title": "Undo / Redo Manager", "slug": "undo-redo-manager", "components": ["Undo", "Redo Manager"]}, {"title": "VirtualScroller · ScrollSync · InfiniteScroll Trigger", "slug": "virtualscroller-scrollsync-infinitescroll-trigger", "components": ["VirtualScroller", "ScrollSync", "InfiniteScroll Trigger"]}, {"title": "Autofocus · RovingTabIndex · TypeAhead · FocusVisible", "slug": "autofocus-rovingtabindex-typeahead-focusvisible", "components": ["Autofocus", "RovingTabIndex", "TypeAhead", "FocusVisible"]}]},
-{"number": 39, "slug": "theme", "title": "Theme", "summary": "Tokens every component reads. Light and dark share one grammar.", "stories": [{"title": "Surfaces", "slug": "surfaces", "components": []}, {"title": "Ink", "slug": "ink", "components": []}, {"title": "Signals", "slug": "signals", "components": []}, {"title": "Series", "slug": "series", "components": []}, {"title": "Syntax", "slug": "syntax", "components": []}, {"title": "Type", "slug": "type", "components": []}, {"title": "Shape", "slug": "shape", "components": []}, {"title": "Motion", "slug": "motion", "components": ["Motion"]}, {"title": "ThemeEditor · DensityProvider · RadiusProvider · FontProvider · HighContrastMode · ReducedMotionProvider", "slug": "themeeditor-densityprovider-radiusprovider-fontprovider-highcontrastmode-reducedmotionprovider", "components": ["ThemeEditor", "DensityProvider", "RadiusProvider", "FontProvider", "HighContrastMode", "ReducedMotionProvider"]}, {"title": "ThemeImporter · SyntaxThemes", "slug": "themeimporter-syntaxthemes", "components": ["ThemeImporter", "SyntaxThemes"]}, {"title": "Platform Style · IconThemeProvider · VibrancyBackground", "slug": "platform-style-iconthemeprovider-vibrancybackground", "components": ["Platform Style", "IconThemeProvider", "VibrancyBackground"]}]},
+{"number": 39, "slug": "theme", "title": "Theme", "summary": "Tokens every component reads. Light and dark share one grammar.", "stories": [{"title": "Surfaces", "slug": "surfaces", "components": ["ColorTokens"]}, {"title": "Ink", "slug": "ink", "components": ["ColorTokens"]}, {"title": "Signals", "slug": "signals", "components": ["ColorTokens"]}, {"title": "Series", "slug": "series", "components": ["ColorTokens"]}, {"title": "Syntax", "slug": "syntax", "components": ["ColorTokens"]}, {"title": "Type", "slug": "type", "components": []}, {"title": "Shape", "slug": "shape", "components": ["Elevation"]}, {"title": "Motion", "slug": "motion", "components": ["Motion", "Spring"]}, {"title": "ThemeEditor · DensityProvider · RadiusProvider · FontProvider · HighContrastMode · ReducedMotionProvider", "slug": "themeeditor-densityprovider-radiusprovider-fontprovider-highcontrastmode-reducedmotionprovider", "components": ["ThemeEditor", "ThemeProvider", "DensityProvider", "RadiusProvider", "FontProvider", "HighContrastMode", "ReducedMotionProvider"]}, {"title": "ThemeImporter · SyntaxThemes", "slug": "themeimporter-syntaxthemes", "components": ["ThemeImporter", "SyntaxThemes"]}, {"title": "Platform Style · IconThemeProvider · VibrancyBackground", "slug": "platform-style-iconthemeprovider-vibrancybackground", "components": ["Platform Style", "IconThemeProvider", "VibrancyBackground"]}]},
{"number": 40, "slug": "i18n", "title": "i18n & a11y", "summary": "Messages, numbers and dates in the reader's locale. A right-to-left locale mirrors its stacks.", "stories": [{"title": "I18nProvider · Trans / LocalizedText", "slug": "i18nprovider-trans-localizedtext", "components": ["I18nProvider", "Trans", "LocalizedText"]}, {"title": "LocaleNumber / LocaleDate", "slug": "localenumber-localedate", "components": ["LocaleNumber", "LocaleDate"]}, {"title": "RTL layout", "slug": "rtl-layout", "components": ["RTL layout"]}, {"title": "SkipLink · KeyboardNavigationHelper", "slug": "skiplink-keyboardnavigationhelper", "components": ["SkipLink", "KeyboardNavigationHelper"]}, {"title": "ColorBlindSafe Palette", "slug": "colorblindsafe-palette", "components": ["ColorBlindSafe Palette"]}]},
{"number": 41, "slug": "maps", "title": "Maps", "summary": "Tiles the host supplies, pins with a popup, a picker's crosshair, routes, GeoJSON, heat, clusters and choropleths. The land is Natural Earth's.", "stories": [{"title": "MapView · MapMarker · MapPopup", "slug": "mapview-mapmarker-mappopup", "components": ["MapView", "MapMarker", "MapPopup"]}, {"title": "CoordinateDisplay", "slug": "coordinatedisplay", "components": ["CoordinateDisplay"]}, {"title": "LocationPicker", "slug": "locationpicker", "components": ["LocationPicker"]}, {"title": "RouteLine · GeoJSON Layer", "slug": "routeline-geojson-layer", "components": ["RouteLine", "GeoJSON Layer"]}, {"title": "GeoHeatmap", "slug": "geoheatmap", "components": ["GeoHeatmap"]}, {"title": "MapCluster", "slug": "mapcluster", "components": ["MapCluster"]}, {"title": "ChoroplethMap · WorldMap", "slug": "choroplethmap-worldmap", "components": ["ChoroplethMap", "WorldMap"]}]},
{"number": 42, "slug": "misc", "title": "Misc", "summary": "Small tools that stand alone: clocks, a stopwatch, a calculator, a unit converter, a QR code scanner, a captcha, a poll, a survey, a quiz, flashcards, licenses, terms, a cookie banner, data out and in, and web views.", "stories": [{"title": "Clock / WorldClock", "slug": "clock-worldclock", "components": ["Clock", "WorldClock"]}, {"title": "Stopwatch", "slug": "stopwatch", "components": ["Stopwatch"]}, {"title": "Calculator", "slug": "calculator", "components": ["Calculator"]}, {"title": "UnitConverter", "slug": "unitconverter", "components": ["UnitConverter"]}, {"title": "QRCodeScanner", "slug": "qrcodescanner", "components": ["QRCodeScanner"]}, {"title": "Captcha", "slug": "captcha", "components": ["Captcha"]}, {"title": "BarcodeDisplay · Signature · Rating Widget", "slug": "barcodedisplay-signature-rating-widget", "components": ["BarcodeDisplay", "Signature", "Rating Widget"]}, {"title": "Poll / Survey", "slug": "poll-survey", "components": ["Poll", "Survey"]}, {"title": "Quiz / Flashcard", "slug": "quiz-flashcard", "components": ["Quiz", "Flashcard"]}, {"title": "ChangeLog Viewer", "slug": "changelog-viewer", "components": ["ChangeLog Viewer"]}, {"title": "LicenseViewer", "slug": "licenseviewer", "components": ["LicenseViewer"]}, {"title": "Terms / Consent Dialog / CookieBanner", "slug": "terms-consent-dialog-cookiebanner", "components": ["Terms", "Consent Dialog", "CookieBanner"]}, {"title": "ExportDialog / ImportDialog / CSVImporter", "slug": "exportdialog-importdialog-csvimporter", "components": ["ExportDialog", "ImportDialog", "CSVImporter"]}, {"title": "WebView / HTMLPreview", "slug": "webview-htmlpreview", "components": ["WebView", "HTMLPreview"]}, {"title": "IframeEmbed / EmbedCard", "slug": "iframeembed-embedcard", "components": ["IframeEmbed", "EmbedCard"]}, {"title": "PrintButton · ShareSheet", "slug": "printbutton-sharesheet", "components": ["PrintButton", "ShareSheet"]}]},
diff --git a/examples/gallery/ui.rs b/examples/gallery/ui.rs
index 4aa8571..5bf571e 100644
--- a/examples/gallery/ui.rs
+++ b/examples/gallery/ui.rs
@@ -55,7 +55,7 @@ pub fn slug(title: &str) -> String {
}
/// Titled block of demos. Under a story, only the one asked for draws, without its title.
-pub fn section(title: impl Into, note: impl Into, cx: &App) -> Div {
+pub fn section(title: impl Into, note: impl Into, cx: &App) -> Section {
let title = title.into();
let theme = cx.theme();
let story = cx.try_global::();
@@ -63,33 +63,58 @@ pub fn section(title: impl Into, note: impl Into, cx
story.met.borrow_mut().push(title.clone());
story.answers(&title)
});
- div()
- .flex()
- .flex_col()
- .gap_4()
- .when(story.is_none(), |section| section.pt_10())
- .when(!shown, |section| section.hidden())
- .child(
- div()
- .flex()
- .flex_col()
- .gap_1()
- .when(story.is_none(), |header| {
- header.child(
- div()
- .text_size(theme.text_size(TextSize::Md))
- .font_weight(FontWeight::SEMIBOLD)
- .text_color(theme.colors.fg)
- .child(title),
- )
- })
- .child(
+ Section {
+ div: div()
+ .flex()
+ .flex_col()
+ .gap_4()
+ .when(story.is_none(), |section| section.pt_10())
+ .when(!shown, |section| section.hidden()),
+ shown,
+ }
+ .child(
+ div()
+ .flex()
+ .flex_col()
+ .gap_1()
+ .when(story.is_none(), |header| {
+ header.child(
div()
- .text_size(theme.text_size(TextSize::Sm))
- .text_color(theme.colors.fg_muted)
- .child(note.into()),
- ),
- )
+ .text_size(theme.text_size(TextSize::Md))
+ .font_weight(FontWeight::SEMIBOLD)
+ .text_color(theme.colors.fg)
+ .child(title),
+ )
+ })
+ .child(
+ div()
+ .text_size(theme.text_size(TextSize::Sm))
+ .text_color(theme.colors.fg_muted)
+ .child(note.into()),
+ ),
+ )
+}
+
+/// A section's box. One a story passes over drops its demos, so none lays out, loads or moves.
+pub struct Section {
+ div: Div,
+ shown: bool,
+}
+
+impl ParentElement for Section {
+ fn extend(&mut self, elements: impl IntoIterator- ) {
+ if self.shown {
+ self.div.extend(elements);
+ }
+ }
+}
+
+impl IntoElement for Section {
+ type Element = Div;
+
+ fn into_element(self) -> Div {
+ self.div
+ }
}
/// A picture under the gallery's assets: a file natively, an address on the web.
@@ -163,6 +188,13 @@ pub fn blocked(text: impl Into, cx: &App) -> impl IntoElement {
.child(div().flex_1().min_w_0().child(text.into()))
}
+/// Why no screen reader reads a demo here.
+pub const UNREAD: &str = if cfg!(target_family = "wasm") {
+ "gpui builds no AccessKit tree on the web, so no screen reader reads it here"
+} else {
+ "gpui builds an AccessKit tree from elements with an id and a role, and no screen reader here reads it"
+};
+
/// Why a demo that takes files takes none on the web.
pub const NO_FILES: &str = "A browser hands gpui no files: on the web the file dialog fails and dropped files never arrive, so nothing is taken here.";
diff --git a/examples/gallery/web.rs b/examples/gallery/web.rs
index 47998cb..948dabb 100644
--- a/examples/gallery/web.rs
+++ b/examples/gallery/web.rs
@@ -1,4 +1,9 @@
-use std::{borrow::Cow, cell::RefCell, rc::Rc, sync::Arc};
+use std::{
+ borrow::Cow,
+ cell::{Cell, RefCell},
+ rc::Rc,
+ sync::Arc,
+};
use anyhow::{Context as _, Result, anyhow, bail};
use ely_gpui_component::Assets;
@@ -18,6 +23,8 @@ const HEBREW: &[u8] = include_bytes!("fonts/NotoSansHebrew-Regular.ttf");
thread_local! {
/// The running app and its window, for the host page's calls.
static HOST: RefCell