Repository navigation
Commit 42721ea
empty: Add composable empty states (longbridge#3030)
Closes longbridge#2862
## Description
- Add six stateless, composable parts: `Empty`, `EmptyHeader`,
`EmptyMedia`, `EmptyTitle`, `EmptyDescription`, and `EmptyContent`.
- Provide optional typed header/content and media/title/description
slots with replacement semantics and stable rendering order. Extra root
children follow the named slots.
- Keep every part independently styleable, with theme-derived
colors/radii and rem-based spacing. Media accepts icons, avatars, avatar
groups, and arbitrary elements; actions and retained input state stay in
the application. No Base-layer changes, dependencies, or
component-specific global theme fields are added.
- Add Story examples for default actions, outline/background styling,
avatars, avatar groups, search results, embedded inputs, constrained
layouts, and minimal content, plus matching English and Chinese
documentation.
- Cover builders and real component composition. The layout regression
catches zero-width avatar groups and verifies centered/leading
alignment, two rem sizes, and named-slot ordering.
- Register all six Empty parts in Component Shell, preserve typed named
slots and independently styled parts, and add the inventory entries and
a JavaScript Story with application-owned actions and retained input
state.
- Keep element arguments intact across the shared named-slot bridge so
registered `header`/`content` methods receive the same Element values as
other registered methods. Existing built-in slots retain their ownership
checks.
- Remove the optional external reference links from both Empty
documentation pages so the generated documentation bundle passes its
canonical-route check without changing that check.
Composition and spacing reference the shadcn/ui Empty Nova examples
while retaining GPUI Component's theme and native controls.
## Screenshot
Screenshots are not attached. Visual verification was completed in the
signed macOS Story app: individual avatars and avatar groups are
centered, constrained Chinese text wraps without clipping, and Empty
follows the theme's font-size and corner-radius controls.
## Breaking Changes
None. The API is additive; existing imports and consumers remain
unchanged. Applications can optionally adopt named parts in place of
their own placeholder markup (this is not a required migration):
```diff
- div().child("No projects yet")
+ Empty::new().header(
+ EmptyHeader::new().title(EmptyTitle::new().child("No projects yet")),
+ )
```
The new types are imported from `gpui_kit::component::empty`; GPUI's
existing `gpui_kit::Empty` remains unchanged.
## How to Test
Passed:
```sh
cargo build --locked -p gpui-component -p gpui-component-story
cargo test --locked -p gpui-component --lib empty::tests
cargo clippy --locked -p gpui-component -p gpui-component-story --all-targets -- --deny warnings
cargo test --locked -p gpui-component-shell --all-targets
cargo test --locked -p gpui-shell --lib tests::render
cargo clippy --locked -p gpui-component-shell --all-targets -- --deny warnings
GPUI_COMPONENT_SHELL_BIN=target/debug/gpui-component-shell node crates/component-shell/tests/types/run.mjs
node examples/js_story/fixtures/verify-coverage.mjs
rustfmt --edition 2024 --check crates/component/src/empty.rs crates/story/src/stories/empty_story.rs
typos crates/component/src/empty.rs crates/story/src/stories/empty_story.rs website/component/empty.md website/zh-CN/component/empty.md
git diff --check
```
Native verification used `./script/run-story-macos Empty`:
- Create project shows `Untitled project`; Reset example restores the
empty state.
- Clear search removes `Archive` and restores all results; typing
`Website` immediately afterward filters the list without refocusing the
field.
- The input embedded in EmptyContent edits independently of the
project-search input.
- Avatar and AvatarGroup centering, leading-aligned constrained content,
long Chinese text, larger font size, and zero/default theme radii were
checked visually.
Both Markdown files parse, and their eight Rust code blocks match. The
production `buildLlmsContent` output passes the canonical-route
assertion and includes both Empty pages. The new host tests cover wrong
slot types, replacement semantics, standalone parts, styles, and a
working child-button callback; all registered Story examples
materialize. Shell CLI tests were run with macOS desktop-service access.
The full documentation-site build and Windows/Linux native runs were not
performed.
## Checklist
- [x] Read CONTRIBUTING and followed the component/design guides.
- [x] Reviewed the scoped API and implementation; this component, Story,
documentation, and regression coverage were AI-assisted.
- [x] Ran the affected Story using the documented signed macOS launch
script.
- [x] No platform-specific implementation changes.
---------
Co-authored-by: Jason Lee <huacnlee@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 6fbc32d commit 42721ea
19 files changed
Lines changed: 2176 additions & 4 deletions
File tree
- crates
- component-shell
- src/shell
- typed_compound
- tests
- types
- component/src
- story/src
- stories
- examples/js_story
- stories
- website
- component
- zh-CN/component
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
346 | 346 | | |
347 | 347 | | |
348 | 348 | | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
349 | 398 | | |
350 | 399 | | |
351 | 400 | | |
| |||
1477 | 1526 | | |
1478 | 1527 | | |
1479 | 1528 | | |
| 1529 | + | |
| 1530 | + | |
| 1531 | + | |
| 1532 | + | |
| 1533 | + | |
| 1534 | + | |
| 1535 | + | |
| 1536 | + | |
| 1537 | + | |
| 1538 | + | |
| 1539 | + | |
| 1540 | + | |
| 1541 | + | |
| 1542 | + | |
| 1543 | + | |
| 1544 | + | |
| 1545 | + | |
| 1546 | + | |
| 1547 | + | |
| 1548 | + | |
| 1549 | + | |
| 1550 | + | |
| 1551 | + | |
| 1552 | + | |
| 1553 | + | |
| 1554 | + | |
| 1555 | + | |
| 1556 | + | |
| 1557 | + | |
| 1558 | + | |
| 1559 | + | |
| 1560 | + | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + | |
| 1564 | + | |
| 1565 | + | |
| 1566 | + | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
| 1574 | + | |
| 1575 | + | |
| 1576 | + | |
| 1577 | + | |
1480 | 1578 | | |
1481 | 1579 | | |
1482 | 1580 | | |
| |||
0 commit comments