| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
assets: share Lucide icon names and preserve default icons (#3020) ## Description Provide the complete Lucide catalog through `gpui-kit-assets::IconName` so Base and other presentation layers can share it without depending on GPUI Component. The package includes all 1,818 Lucide 1.43.0 SVGs and the 12 retained GPUI Kit icons. Keep the existing application workflow: default `Assets` embeds the original 101 component icons, and applications provide additional icons through their own `AssetSource`. Full native embedding is an explicit `AllAssets` choice. The optional `icon_assets!(ExtraIcons, [...])` macro creates a selected source that can be composed with the default bundle. WASM keeps its existing on-demand CDN loader; selected sources can embed bytes directly. ## Compatibility Existing component imports, exhaustive matches, and `IconName::Search.view(cx)` calls remain valid without additional trait imports. Component retains its original enum as a compatibility adapter; `Icon::new(...)` accepts both this enum and the new shared assets enum. Legacy names can convert into shared names using `.into()`. The extension trait is only an optional convenience for the new shared enum. Preserve `Assets::get`, `Assets::iter`, `Assets::new`, the original default path set, asset-source behavior, and Cargo icon-directory metadata. The complete catalog and default component bundle are generated separately; adding Lucide files does not expand default embedding. ## Documentation and maintenance README and both language versions of Icon / Icons & Assets have a prominent NOTE distinguishing the catalog from default embedding, plus a measured comparison table. A default-plus-10-extra-icons example adds 19,648 bytes to a Linux release/stripped resource program; those extra SVGs total 3,903 bytes. The measurement includes source composition/lookup code and is not a fixed per-icon cost or a RAM estimate. `bun script/sync-lucide.ts` replaces the Python updater. It verifies the pinned archive SHA-256, supports offline `--archive` and read-only `--check`, copies the upstream license, and preserves custom icons and the default bundle selection. ## Validation - `cargo test -p gpui-kit-assets --test icons`: 5 tests covering complete/default catalogs, selected resources, empty selection and native compatibility. - `cargo test -p gpui-kit --test assets`: 2 tests covering shared names and unchanged legacy views/conversions; 1 test also passes with `--no-default-features --features assets`. - `cargo clippy -p gpui-component -p gpui-kit-assets -p gpui-component-story -- --deny warnings`; `cargo fmt --all --check`. - `cargo check -p gpui-component --no-default-features`. - `cargo check -p gpui-kit-assets --lib --example selected_assets --target wasm32-unknown-unknown`. - `cargo package -p gpui-kit-assets --allow-dirty` verifies packaged build generation. - `cargo run -p gpui-kit-assets --release --example extra_assets -- icons/accessibility.svg` and `icons/search.svg` verify application and component fallback paths. - `bun test script/tests/sync-lucide.test.ts`: 14 assertions covering check-only behavior, synchronization, custom-file preservation, count validation and corrupt-archive rejection. Online and offline checks verify all 1,818 upstream SVGs and their license. - Website production build passes; generated HTML contains the comparison table inside each of the four NOTE callouts. - Binary inspection confirms 101 SVG payloads by default, 103 with two extras, 111 with ten extras, and 1,830 only with explicit `AllAssets`. | Native resource configuration | Embedded SVG size (KiB) | Binary increase over default (KiB) | | --- | ---: | ---: | | Default (101 icons) | 44.28 | 0.00 | | Default + 2 extras | 45.04 | 15.19 | | Default + 10 extras | 48.09 | 19.19 | | Explicit AllAssets | 731.45 | 1045.16 | 1 KiB = 1,024 bytes. Measured with Rust 1.98.0 on Linux x86_64, release optimization and stripped symbols. Every program retains the same shared-name lookup and runtime path; extra sources fall back to the default and merge/sort/deduplicate their lists. The documentation names the exact icons and explains limitations. ## Checklist - [x] Read the contribution guidelines. - [x] Reviewed the implementation, including AI-generated code. - [x] Ran targeted tests and resource examples. - [ ] Ran the interactive story gallery. - [ ] Tested native macOS and Windows behavior (Linux and WASM compilation validated). | 23 天前 | |
assets: share Lucide icon names and preserve default icons (#3020) ## Description Provide the complete Lucide catalog through `gpui-kit-assets::IconName` so Base and other presentation layers can share it without depending on GPUI Component. The package includes all 1,818 Lucide 1.43.0 SVGs and the 12 retained GPUI Kit icons. Keep the existing application workflow: default `Assets` embeds the original 101 component icons, and applications provide additional icons through their own `AssetSource`. Full native embedding is an explicit `AllAssets` choice. The optional `icon_assets!(ExtraIcons, [...])` macro creates a selected source that can be composed with the default bundle. WASM keeps its existing on-demand CDN loader; selected sources can embed bytes directly. ## Compatibility Existing component imports, exhaustive matches, and `IconName::Search.view(cx)` calls remain valid without additional trait imports. Component retains its original enum as a compatibility adapter; `Icon::new(...)` accepts both this enum and the new shared assets enum. Legacy names can convert into shared names using `.into()`. The extension trait is only an optional convenience for the new shared enum. Preserve `Assets::get`, `Assets::iter`, `Assets::new`, the original default path set, asset-source behavior, and Cargo icon-directory metadata. The complete catalog and default component bundle are generated separately; adding Lucide files does not expand default embedding. ## Documentation and maintenance README and both language versions of Icon / Icons & Assets have a prominent NOTE distinguishing the catalog from default embedding, plus a measured comparison table. A default-plus-10-extra-icons example adds 19,648 bytes to a Linux release/stripped resource program; those extra SVGs total 3,903 bytes. The measurement includes source composition/lookup code and is not a fixed per-icon cost or a RAM estimate. `bun script/sync-lucide.ts` replaces the Python updater. It verifies the pinned archive SHA-256, supports offline `--archive` and read-only `--check`, copies the upstream license, and preserves custom icons and the default bundle selection. ## Validation - `cargo test -p gpui-kit-assets --test icons`: 5 tests covering complete/default catalogs, selected resources, empty selection and native compatibility. - `cargo test -p gpui-kit --test assets`: 2 tests covering shared names and unchanged legacy views/conversions; 1 test also passes with `--no-default-features --features assets`. - `cargo clippy -p gpui-component -p gpui-kit-assets -p gpui-component-story -- --deny warnings`; `cargo fmt --all --check`. - `cargo check -p gpui-component --no-default-features`. - `cargo check -p gpui-kit-assets --lib --example selected_assets --target wasm32-unknown-unknown`. - `cargo package -p gpui-kit-assets --allow-dirty` verifies packaged build generation. - `cargo run -p gpui-kit-assets --release --example extra_assets -- icons/accessibility.svg` and `icons/search.svg` verify application and component fallback paths. - `bun test script/tests/sync-lucide.test.ts`: 14 assertions covering check-only behavior, synchronization, custom-file preservation, count validation and corrupt-archive rejection. Online and offline checks verify all 1,818 upstream SVGs and their license. - Website production build passes; generated HTML contains the comparison table inside each of the four NOTE callouts. - Binary inspection confirms 101 SVG payloads by default, 103 with two extras, 111 with ten extras, and 1,830 only with explicit `AllAssets`. | Native resource configuration | Embedded SVG size (KiB) | Binary increase over default (KiB) | | --- | ---: | ---: | | Default (101 icons) | 44.28 | 0.00 | | Default + 2 extras | 45.04 | 15.19 | | Default + 10 extras | 48.09 | 19.19 | | Explicit AllAssets | 731.45 | 1045.16 | 1 KiB = 1,024 bytes. Measured with Rust 1.98.0 on Linux x86_64, release optimization and stripped symbols. Every program retains the same shared-name lookup and runtime path; extra sources fall back to the default and merge/sort/deduplicate their lists. The documentation names the exact icons and explains limitations. ## Checklist - [x] Read the contribution guidelines. - [x] Reviewed the implementation, including AI-generated code. - [x] Ran targeted tests and resource examples. - [ ] Ran the interactive story gallery. - [ ] Tested native macOS and Windows behavior (Linux and WASM compilation validated). | 23 天前 | |
ci: Split checks into parallel jobs and stop recompiling GPUI per step (#3068) ## Summary The macOS Test job took ~30 minutes because it ran every check in series and compiled GPUI five times over: each step used a different feature set, the Cargo cache was restored only *after* the first two test runs, and typos/machete were built from source with `cargo install`. ### Parallel layout, one feature set per job - **`checks`** (ubuntu, no Rust compile): typos via `crate-ci/typos` and machete via `taiki-e/install-action`, both prebuilt binaries; skill-guide diff; `check-ai docs`. - **`lint`** (macOS) and **`recipes`** (ubuntu) run as their own parallel jobs. The recipes crate is a deliberately isolated workspace and always needs its own build, so it no longer sits on the macOS critical path. - **`test`** matrix keeps one feature set per platform. `cargo tree -e features` confirms the workspace run already enables `gpui-kit/test-support`, so the separate "Headless UI integration tests" step was a duplicate on all three platforms. Doc tests and the Metal rendering test now use the same `--workspace --features gpui-component-story/test-support` invocation (`--doc` / `--test rendering`) and reuse the build. - `gpui-shell-core` doc tests use `--release` to share the release build. - `script/check-ai-recipes`: drop `cargo check --all-targets`; the `cargo test` that follows builds the same targets. `cargo check --bin` stays because it proves the recipes compile before dev-dependencies unify `test-support` in. ### Caches that actually survive The first run of the new layout was still cold in every job: the repository holds 11.7 GB of Actions caches against the 10 GB limit, so entries were evicted before the next run could restore them. Each entry was 1–2 GB, most of it debug info. - `CARGO_PROFILE_DEV_DEBUG=0` for all CI builds — smaller caches, faster linking; nothing in CI reads debug info. - Caches are saved only from `main` (`cache-save-if`); PRs restore the closest `main` entry through rust-cache's prefix fallback instead of adding their own. - Drop the hand-rolled `actions/cache` steps that cached the whole `target/` on top of the rust-cache that `setup-rust-toolchain` already installs. - The two Linux release builds of `gpui-shell` share one cache key. - Linux runners link with mold (`rui314/setup-mold`, no-op elsewhere). Because the cache key includes the `CARGO_PROFILE_*` environment, this PR's own runs stay cold; the first `main` run after merge populates the caches and later PRs restore them. ### Doc-test fixes Running doc tests workspace-wide surfaced two broken doc examples, fixed here: `gpui-fps` was missing `prelude::*`, and `gpui-kit-assets` referenced `gpui_platform` without depending on it (`cargo test --doc` ignores `[lib] doctest = false`, so it is removed and `gpui_platform` added as a dev-dependency). Verified locally: workspace `cargo test --doc` passes for every crate, `--workspace --test rendering` selects and passes the 2 Metal cases, `typos`, `cargo machete`, `cargo fmt --check`, clippy on the touched crates, `check-ai docs`, and the recipes lock file stays consistent under `--locked`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_019RrFLRLnLWUuUNPyDXSJZU --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> | 17 天前 | |
attachment: Adopt the composer design with built-in remove, retry and progress (#3195) ## Summary The `Attachment` family becomes the composer attachment of the Longbridge design: the card geometry, the status treatment and the controls every composer used to wrap by hand are now the component's defaults, verified against the design board and rendered headlessly at each step. `AttachmentGroup` also learns to fade its edges and to scroll through a caller's handle, which is what a composer row needs. ## Changes - **Group scrolling** — `AttachmentGroup::track_scroll(&ScrollHandle)` lets the application drive the row (paging buttons, "scroll to newest"), and `with_edge_fade(color)` draws a short gradient at an edge only while attachments continue past it, with a 200 ms transition. - **Image rounding** — gpui clips rectangularly, so a media image never got the slot's corner radius and poked out of the card's rounded border; the image now carries the radius itself, including a caller's `.rounded()` refinement. The status scrim does the same. - **Composer geometry as defaults** — a `Medium` chip is 56 px tall, 232 px wide once it carries content, with a 38 px media box, 13 px title, `radius.lg` corners and a full-strength destructive border when failed; the other named sizes scale the same geometry. A vertical attachment without content is an image tile: a square the media fills flush with the border, its corners one border width tighter than the card's. - **Status drawn by the slots** — an icon slot shows a spinner (primary) while in progress and the alert glyph once failed; an image keeps its colors and takes a scrim instead: 35 % with a white spinner while in progress, 55 % with the retry control once failed. A failed attachment that offers no retry reads as a rejection and shows the ban glyph. - **Built-in controls** — `on_remove` rides a small surface-colored disc with a hairline border on the card's upper trailing corner (hover on desktop, always on touch; the card reserves the overhang so rows stay aligned). `on_retry` renders a round button over a failed image or a localized "Retry" link after the typed description. `progress(percent)` turns the spinner into a determinate ring (`ProgressCircle`), draws a 2 px bar along a chip's bottom edge and appends "· 62 %" to the description. The bar is a filled path whose ends trace the inner corner arcs, since gpui clips rectangularly and a rectangle could not hug the rounded corners. `tooltip(text)` shows the failure reason on hover. All key their state on `id(...)`. - **Media glyph size** — an icon child without its own size follows a per-size glyph scale (14 / 16 / 20 / 24 px for `XSmall` … `Large`) instead of the card's text size, and the failed and ban glyphs use the same scale. - Docs (`website/component/attachment.md`, zh-CN), the story and the builder tests follow. Observed on the way, left alone: `ButtonCustomVariant` thins its `color` to 20 % (`mix_oklab(transparent, 0.2)` interpolates alpha the wrong way round), so the remove disc sets its surface on the instance. ## Public API ### gpui-component - `AttachmentGroup::track_scroll(mut self, handle: &ScrollHandle) -> Self` — scroll the row through the caller's handle instead of the group's own state. - `AttachmentGroup::with_edge_fade(mut self, color: impl Into<Hsla>) -> Self` — fade an edge into `color` while it hides attachments. - `Attachment::on_remove(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self` — corner remove control; requires `id(...)`. - `Attachment::on_retry(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self` — retry control while `Failed`; requires `id(...)`. - `Attachment::progress(mut self, percent: f32) -> Self` — determinate ring, bottom bar and percentage while `Uploading` (0–100, clamped). - `Attachment::tooltip(mut self, text: impl Into<SharedString>) -> Self` — hover tooltip on the card; requires `id(...)`. - `IconName::RefreshCw`, `IconName::CircleAlert`, `IconName::Ban` — join the default component icon set (used by the retry and failed glyphs). - Locale keys `Attachment.Remove`, `Attachment.Retry` (en, zh-CN, zh-HK, zh-TW). ### Behavior changes (no signature changes) - `Attachment` defaults: radius `radius_tokens().lg` (was `radius_2xl()`), fixed per-size chip geometry (was content-sized with `min_w_40`), 13 px title at `Medium` (was `text_sm`), failed border at full destructive strength (was 30 %), failed description at full destructive (was 80 %). - `AttachmentMedia`: in-progress and failed images take a scrim instead of dimming to 60 %; an icon slot replaces its children with the status glyph while in progress or failed; images and scrims carry the slot's corner radius. ## Test plan - `cargo test -p gpui-component attachment` (15 tests, incl. the new builder/layout tests) and `cargo test -p gpui-kit-assets --test icons` (the default bundle now counts 104 icons) - `cargo clippy -p gpui-component -p gpui-component-story` - Headless renders of every composer state (hovered tile, uploading, 62 % progress, failed, rejected, empty; chips complete / uploading / failed / rejected) compared against the design board. --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> | 6 天前 | |
Bump v0.7.0 | 3 天前 | |
assets: share Lucide icon names and preserve default icons (#3020) ## Description Provide the complete Lucide catalog through `gpui-kit-assets::IconName` so Base and other presentation layers can share it without depending on GPUI Component. The package includes all 1,818 Lucide 1.43.0 SVGs and the 12 retained GPUI Kit icons. Keep the existing application workflow: default `Assets` embeds the original 101 component icons, and applications provide additional icons through their own `AssetSource`. Full native embedding is an explicit `AllAssets` choice. The optional `icon_assets!(ExtraIcons, [...])` macro creates a selected source that can be composed with the default bundle. WASM keeps its existing on-demand CDN loader; selected sources can embed bytes directly. ## Compatibility Existing component imports, exhaustive matches, and `IconName::Search.view(cx)` calls remain valid without additional trait imports. Component retains its original enum as a compatibility adapter; `Icon::new(...)` accepts both this enum and the new shared assets enum. Legacy names can convert into shared names using `.into()`. The extension trait is only an optional convenience for the new shared enum. Preserve `Assets::get`, `Assets::iter`, `Assets::new`, the original default path set, asset-source behavior, and Cargo icon-directory metadata. The complete catalog and default component bundle are generated separately; adding Lucide files does not expand default embedding. ## Documentation and maintenance README and both language versions of Icon / Icons & Assets have a prominent NOTE distinguishing the catalog from default embedding, plus a measured comparison table. A default-plus-10-extra-icons example adds 19,648 bytes to a Linux release/stripped resource program; those extra SVGs total 3,903 bytes. The measurement includes source composition/lookup code and is not a fixed per-icon cost or a RAM estimate. `bun script/sync-lucide.ts` replaces the Python updater. It verifies the pinned archive SHA-256, supports offline `--archive` and read-only `--check`, copies the upstream license, and preserves custom icons and the default bundle selection. ## Validation - `cargo test -p gpui-kit-assets --test icons`: 5 tests covering complete/default catalogs, selected resources, empty selection and native compatibility. - `cargo test -p gpui-kit --test assets`: 2 tests covering shared names and unchanged legacy views/conversions; 1 test also passes with `--no-default-features --features assets`. - `cargo clippy -p gpui-component -p gpui-kit-assets -p gpui-component-story -- --deny warnings`; `cargo fmt --all --check`. - `cargo check -p gpui-component --no-default-features`. - `cargo check -p gpui-kit-assets --lib --example selected_assets --target wasm32-unknown-unknown`. - `cargo package -p gpui-kit-assets --allow-dirty` verifies packaged build generation. - `cargo run -p gpui-kit-assets --release --example extra_assets -- icons/accessibility.svg` and `icons/search.svg` verify application and component fallback paths. - `bun test script/tests/sync-lucide.test.ts`: 14 assertions covering check-only behavior, synchronization, custom-file preservation, count validation and corrupt-archive rejection. Online and offline checks verify all 1,818 upstream SVGs and their license. - Website production build passes; generated HTML contains the comparison table inside each of the four NOTE callouts. - Binary inspection confirms 101 SVG payloads by default, 103 with two extras, 111 with ten extras, and 1,830 only with explicit `AllAssets`. | Native resource configuration | Embedded SVG size (KiB) | Binary increase over default (KiB) | | --- | ---: | ---: | | Default (101 icons) | 44.28 | 0.00 | | Default + 2 extras | 45.04 | 15.19 | | Default + 10 extras | 48.09 | 19.19 | | Explicit AllAssets | 731.45 | 1045.16 | 1 KiB = 1,024 bytes. Measured with Rust 1.98.0 on Linux x86_64, release optimization and stripped symbols. Every program retains the same shared-name lookup and runtime path; extra sources fall back to the default and merge/sort/deduplicate their lists. The documentation names the exact icons and explains limitations. ## Checklist - [x] Read the contribution guidelines. - [x] Reviewed the implementation, including AI-generated code. - [x] Ran targeted tests and resource examples. - [ ] Ran the interactive story gallery. - [ ] Tested native macOS and Windows behavior (Linux and WASM compilation validated). | 23 天前 | |
assets: share Lucide icon names and preserve default icons (#3020) ## Description Provide the complete Lucide catalog through `gpui-kit-assets::IconName` so Base and other presentation layers can share it without depending on GPUI Component. The package includes all 1,818 Lucide 1.43.0 SVGs and the 12 retained GPUI Kit icons. Keep the existing application workflow: default `Assets` embeds the original 101 component icons, and applications provide additional icons through their own `AssetSource`. Full native embedding is an explicit `AllAssets` choice. The optional `icon_assets!(ExtraIcons, [...])` macro creates a selected source that can be composed with the default bundle. WASM keeps its existing on-demand CDN loader; selected sources can embed bytes directly. ## Compatibility Existing component imports, exhaustive matches, and `IconName::Search.view(cx)` calls remain valid without additional trait imports. Component retains its original enum as a compatibility adapter; `Icon::new(...)` accepts both this enum and the new shared assets enum. Legacy names can convert into shared names using `.into()`. The extension trait is only an optional convenience for the new shared enum. Preserve `Assets::get`, `Assets::iter`, `Assets::new`, the original default path set, asset-source behavior, and Cargo icon-directory metadata. The complete catalog and default component bundle are generated separately; adding Lucide files does not expand default embedding. ## Documentation and maintenance README and both language versions of Icon / Icons & Assets have a prominent NOTE distinguishing the catalog from default embedding, plus a measured comparison table. A default-plus-10-extra-icons example adds 19,648 bytes to a Linux release/stripped resource program; those extra SVGs total 3,903 bytes. The measurement includes source composition/lookup code and is not a fixed per-icon cost or a RAM estimate. `bun script/sync-lucide.ts` replaces the Python updater. It verifies the pinned archive SHA-256, supports offline `--archive` and read-only `--check`, copies the upstream license, and preserves custom icons and the default bundle selection. ## Validation - `cargo test -p gpui-kit-assets --test icons`: 5 tests covering complete/default catalogs, selected resources, empty selection and native compatibility. - `cargo test -p gpui-kit --test assets`: 2 tests covering shared names and unchanged legacy views/conversions; 1 test also passes with `--no-default-features --features assets`. - `cargo clippy -p gpui-component -p gpui-kit-assets -p gpui-component-story -- --deny warnings`; `cargo fmt --all --check`. - `cargo check -p gpui-component --no-default-features`. - `cargo check -p gpui-kit-assets --lib --example selected_assets --target wasm32-unknown-unknown`. - `cargo package -p gpui-kit-assets --allow-dirty` verifies packaged build generation. - `cargo run -p gpui-kit-assets --release --example extra_assets -- icons/accessibility.svg` and `icons/search.svg` verify application and component fallback paths. - `bun test script/tests/sync-lucide.test.ts`: 14 assertions covering check-only behavior, synchronization, custom-file preservation, count validation and corrupt-archive rejection. Online and offline checks verify all 1,818 upstream SVGs and their license. - Website production build passes; generated HTML contains the comparison table inside each of the four NOTE callouts. - Binary inspection confirms 101 SVG payloads by default, 103 with two extras, 111 with ten extras, and 1,830 only with explicit `AllAssets`. | Native resource configuration | Embedded SVG size (KiB) | Binary increase over default (KiB) | | --- | ---: | ---: | | Default (101 icons) | 44.28 | 0.00 | | Default + 2 extras | 45.04 | 15.19 | | Default + 10 extras | 48.09 | 19.19 | | Explicit AllAssets | 731.45 | 1045.16 | 1 KiB = 1,024 bytes. Measured with Rust 1.98.0 on Linux x86_64, release optimization and stripped symbols. Every program retains the same shared-name lookup and runtime path; extra sources fall back to the default and merge/sort/deduplicate their lists. The documentation names the exact icons and explains limitations. ## Checklist - [x] Read the contribution guidelines. - [x] Reviewed the implementation, including AI-generated code. - [x] Ran targeted tests and resource examples. - [ ] Ran the interactive story gallery. - [ ] Tested native macOS and Windows behavior (Linux and WASM compilation validated). | 23 天前 | |
assets: share Lucide icon names and preserve default icons (#3020) ## Description Provide the complete Lucide catalog through `gpui-kit-assets::IconName` so Base and other presentation layers can share it without depending on GPUI Component. The package includes all 1,818 Lucide 1.43.0 SVGs and the 12 retained GPUI Kit icons. Keep the existing application workflow: default `Assets` embeds the original 101 component icons, and applications provide additional icons through their own `AssetSource`. Full native embedding is an explicit `AllAssets` choice. The optional `icon_assets!(ExtraIcons, [...])` macro creates a selected source that can be composed with the default bundle. WASM keeps its existing on-demand CDN loader; selected sources can embed bytes directly. ## Compatibility Existing component imports, exhaustive matches, and `IconName::Search.view(cx)` calls remain valid without additional trait imports. Component retains its original enum as a compatibility adapter; `Icon::new(...)` accepts both this enum and the new shared assets enum. Legacy names can convert into shared names using `.into()`. The extension trait is only an optional convenience for the new shared enum. Preserve `Assets::get`, `Assets::iter`, `Assets::new`, the original default path set, asset-source behavior, and Cargo icon-directory metadata. The complete catalog and default component bundle are generated separately; adding Lucide files does not expand default embedding. ## Documentation and maintenance README and both language versions of Icon / Icons & Assets have a prominent NOTE distinguishing the catalog from default embedding, plus a measured comparison table. A default-plus-10-extra-icons example adds 19,648 bytes to a Linux release/stripped resource program; those extra SVGs total 3,903 bytes. The measurement includes source composition/lookup code and is not a fixed per-icon cost or a RAM estimate. `bun script/sync-lucide.ts` replaces the Python updater. It verifies the pinned archive SHA-256, supports offline `--archive` and read-only `--check`, copies the upstream license, and preserves custom icons and the default bundle selection. ## Validation - `cargo test -p gpui-kit-assets --test icons`: 5 tests covering complete/default catalogs, selected resources, empty selection and native compatibility. - `cargo test -p gpui-kit --test assets`: 2 tests covering shared names and unchanged legacy views/conversions; 1 test also passes with `--no-default-features --features assets`. - `cargo clippy -p gpui-component -p gpui-kit-assets -p gpui-component-story -- --deny warnings`; `cargo fmt --all --check`. - `cargo check -p gpui-component --no-default-features`. - `cargo check -p gpui-kit-assets --lib --example selected_assets --target wasm32-unknown-unknown`. - `cargo package -p gpui-kit-assets --allow-dirty` verifies packaged build generation. - `cargo run -p gpui-kit-assets --release --example extra_assets -- icons/accessibility.svg` and `icons/search.svg` verify application and component fallback paths. - `bun test script/tests/sync-lucide.test.ts`: 14 assertions covering check-only behavior, synchronization, custom-file preservation, count validation and corrupt-archive rejection. Online and offline checks verify all 1,818 upstream SVGs and their license. - Website production build passes; generated HTML contains the comparison table inside each of the four NOTE callouts. - Binary inspection confirms 101 SVG payloads by default, 103 with two extras, 111 with ten extras, and 1,830 only with explicit `AllAssets`. | Native resource configuration | Embedded SVG size (KiB) | Binary increase over default (KiB) | | --- | ---: | ---: | | Default (101 icons) | 44.28 | 0.00 | | Default + 2 extras | 45.04 | 15.19 | | Default + 10 extras | 48.09 | 19.19 | | Explicit AllAssets | 731.45 | 1045.16 | 1 KiB = 1,024 bytes. Measured with Rust 1.98.0 on Linux x86_64, release optimization and stripped symbols. Every program retains the same shared-name lookup and runtime path; extra sources fall back to the default and merge/sort/deduplicate their lists. The documentation names the exact icons and explains limitations. ## Checklist - [x] Read the contribution guidelines. - [x] Reviewed the implementation, including AI-generated code. - [x] Ran targeted tests and resource examples. - [ ] Ran the interactive story gallery. - [ ] Tested native macOS and Windows behavior (Linux and WASM compilation validated). | 23 天前 | |
attachment: Adopt the composer design with built-in remove, retry and progress (#3195) ## Summary The `Attachment` family becomes the composer attachment of the Longbridge design: the card geometry, the status treatment and the controls every composer used to wrap by hand are now the component's defaults, verified against the design board and rendered headlessly at each step. `AttachmentGroup` also learns to fade its edges and to scroll through a caller's handle, which is what a composer row needs. ## Changes - **Group scrolling** — `AttachmentGroup::track_scroll(&ScrollHandle)` lets the application drive the row (paging buttons, "scroll to newest"), and `with_edge_fade(color)` draws a short gradient at an edge only while attachments continue past it, with a 200 ms transition. - **Image rounding** — gpui clips rectangularly, so a media image never got the slot's corner radius and poked out of the card's rounded border; the image now carries the radius itself, including a caller's `.rounded()` refinement. The status scrim does the same. - **Composer geometry as defaults** — a `Medium` chip is 56 px tall, 232 px wide once it carries content, with a 38 px media box, 13 px title, `radius.lg` corners and a full-strength destructive border when failed; the other named sizes scale the same geometry. A vertical attachment without content is an image tile: a square the media fills flush with the border, its corners one border width tighter than the card's. - **Status drawn by the slots** — an icon slot shows a spinner (primary) while in progress and the alert glyph once failed; an image keeps its colors and takes a scrim instead: 35 % with a white spinner while in progress, 55 % with the retry control once failed. A failed attachment that offers no retry reads as a rejection and shows the ban glyph. - **Built-in controls** — `on_remove` rides a small surface-colored disc with a hairline border on the card's upper trailing corner (hover on desktop, always on touch; the card reserves the overhang so rows stay aligned). `on_retry` renders a round button over a failed image or a localized "Retry" link after the typed description. `progress(percent)` turns the spinner into a determinate ring (`ProgressCircle`), draws a 2 px bar along a chip's bottom edge and appends "· 62 %" to the description. The bar is a filled path whose ends trace the inner corner arcs, since gpui clips rectangularly and a rectangle could not hug the rounded corners. `tooltip(text)` shows the failure reason on hover. All key their state on `id(...)`. - **Media glyph size** — an icon child without its own size follows a per-size glyph scale (14 / 16 / 20 / 24 px for `XSmall` … `Large`) instead of the card's text size, and the failed and ban glyphs use the same scale. - Docs (`website/component/attachment.md`, zh-CN), the story and the builder tests follow. Observed on the way, left alone: `ButtonCustomVariant` thins its `color` to 20 % (`mix_oklab(transparent, 0.2)` interpolates alpha the wrong way round), so the remove disc sets its surface on the instance. ## Public API ### gpui-component - `AttachmentGroup::track_scroll(mut self, handle: &ScrollHandle) -> Self` — scroll the row through the caller's handle instead of the group's own state. - `AttachmentGroup::with_edge_fade(mut self, color: impl Into<Hsla>) -> Self` — fade an edge into `color` while it hides attachments. - `Attachment::on_remove(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self` — corner remove control; requires `id(...)`. - `Attachment::on_retry(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self` — retry control while `Failed`; requires `id(...)`. - `Attachment::progress(mut self, percent: f32) -> Self` — determinate ring, bottom bar and percentage while `Uploading` (0–100, clamped). - `Attachment::tooltip(mut self, text: impl Into<SharedString>) -> Self` — hover tooltip on the card; requires `id(...)`. - `IconName::RefreshCw`, `IconName::CircleAlert`, `IconName::Ban` — join the default component icon set (used by the retry and failed glyphs). - Locale keys `Attachment.Remove`, `Attachment.Retry` (en, zh-CN, zh-HK, zh-TW). ### Behavior changes (no signature changes) - `Attachment` defaults: radius `radius_tokens().lg` (was `radius_2xl()`), fixed per-size chip geometry (was content-sized with `min_w_40`), 13 px title at `Medium` (was `text_sm`), failed border at full destructive strength (was 30 %), failed description at full destructive (was 80 %). - `AttachmentMedia`: in-progress and failed images take a scrim instead of dimming to 60 %; an icon slot replaces its children with the status glyph while in progress or failed; images and scrims carry the slot's corner radius. ## Test plan - `cargo test -p gpui-component attachment` (15 tests, incl. the new builder/layout tests) and `cargo test -p gpui-kit-assets --test icons` (the default bundle now counts 104 icons) - `cargo clippy -p gpui-component -p gpui-component-story` - Headless renders of every composer state (hovered tile, uploading, 62 % progress, failed, rejected, empty; chips complete / uploading / failed / rejected) compared against the design board. --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> | 6 天前 | |
assets: share Lucide icon names and preserve default icons (#3020) ## Description Provide the complete Lucide catalog through `gpui-kit-assets::IconName` so Base and other presentation layers can share it without depending on GPUI Component. The package includes all 1,818 Lucide 1.43.0 SVGs and the 12 retained GPUI Kit icons. Keep the existing application workflow: default `Assets` embeds the original 101 component icons, and applications provide additional icons through their own `AssetSource`. Full native embedding is an explicit `AllAssets` choice. The optional `icon_assets!(ExtraIcons, [...])` macro creates a selected source that can be composed with the default bundle. WASM keeps its existing on-demand CDN loader; selected sources can embed bytes directly. ## Compatibility Existing component imports, exhaustive matches, and `IconName::Search.view(cx)` calls remain valid without additional trait imports. Component retains its original enum as a compatibility adapter; `Icon::new(...)` accepts both this enum and the new shared assets enum. Legacy names can convert into shared names using `.into()`. The extension trait is only an optional convenience for the new shared enum. Preserve `Assets::get`, `Assets::iter`, `Assets::new`, the original default path set, asset-source behavior, and Cargo icon-directory metadata. The complete catalog and default component bundle are generated separately; adding Lucide files does not expand default embedding. ## Documentation and maintenance README and both language versions of Icon / Icons & Assets have a prominent NOTE distinguishing the catalog from default embedding, plus a measured comparison table. A default-plus-10-extra-icons example adds 19,648 bytes to a Linux release/stripped resource program; those extra SVGs total 3,903 bytes. The measurement includes source composition/lookup code and is not a fixed per-icon cost or a RAM estimate. `bun script/sync-lucide.ts` replaces the Python updater. It verifies the pinned archive SHA-256, supports offline `--archive` and read-only `--check`, copies the upstream license, and preserves custom icons and the default bundle selection. ## Validation - `cargo test -p gpui-kit-assets --test icons`: 5 tests covering complete/default catalogs, selected resources, empty selection and native compatibility. - `cargo test -p gpui-kit --test assets`: 2 tests covering shared names and unchanged legacy views/conversions; 1 test also passes with `--no-default-features --features assets`. - `cargo clippy -p gpui-component -p gpui-kit-assets -p gpui-component-story -- --deny warnings`; `cargo fmt --all --check`. - `cargo check -p gpui-component --no-default-features`. - `cargo check -p gpui-kit-assets --lib --example selected_assets --target wasm32-unknown-unknown`. - `cargo package -p gpui-kit-assets --allow-dirty` verifies packaged build generation. - `cargo run -p gpui-kit-assets --release --example extra_assets -- icons/accessibility.svg` and `icons/search.svg` verify application and component fallback paths. - `bun test script/tests/sync-lucide.test.ts`: 14 assertions covering check-only behavior, synchronization, custom-file preservation, count validation and corrupt-archive rejection. Online and offline checks verify all 1,818 upstream SVGs and their license. - Website production build passes; generated HTML contains the comparison table inside each of the four NOTE callouts. - Binary inspection confirms 101 SVG payloads by default, 103 with two extras, 111 with ten extras, and 1,830 only with explicit `AllAssets`. | Native resource configuration | Embedded SVG size (KiB) | Binary increase over default (KiB) | | --- | ---: | ---: | | Default (101 icons) | 44.28 | 0.00 | | Default + 2 extras | 45.04 | 15.19 | | Default + 10 extras | 48.09 | 19.19 | | Explicit AllAssets | 731.45 | 1045.16 | 1 KiB = 1,024 bytes. Measured with Rust 1.98.0 on Linux x86_64, release optimization and stripped symbols. Every program retains the same shared-name lookup and runtime path; extra sources fall back to the default and merge/sort/deduplicate their lists. The documentation names the exact icons and explains limitations. ## Checklist - [x] Read the contribution guidelines. - [x] Reviewed the implementation, including AI-generated code. - [x] Ran targeted tests and resource examples. - [ ] Ran the interactive story gallery. - [ ] Tested native macOS and Windows behavior (Linux and WASM compilation validated). | 23 天前 |
GPUI Kit Assets
Note
The complete catalog does not make existing applications embed every icon.
Assets keeps the original 101 component icons. Applications provide additional
icons through their own AssetSource, as before; they do not need to redeclare
the component icons. Only explicitly registering AllAssets embeds all 1,830
SVGs on native platforms. Depending on the crate or using the shared IconName
alone does not reference every SVG payload.
| Native asset configuration | Embedded SVG data | Binary increase vs. default Assets |
|---|---|---|
| Default component icons (101) | 44.28 KiB | 0 B (baseline) |
| Default + 2 application icons (103) | 45.04 KiB | +15.19 KiB |
| Default + 10 application icons (111) | 48.09 KiB | +19.19 KiB |
Explicit AllAssets (1,830) |
731.45 KiB | +1.02 MiB |
In this example, adding 10 application icons costs about 19 KiB, not the full catalog. Their SVGs total 3,903 bytes; the measured binary increase is 19,648 bytes, including the extra source's lookup/list-composition code, metadata and alignment. These are not fixed per-icon costs or whole-application sizes.
Measured with Lucide 1.43.0 on Linux x86_64, Rust 1.98.0, --release, and stripped
symbols. Each program uses the same IconName lookup and runtime asset path.
The extra source falls back to Assets, and merges, sorts and deduplicates both
sources' lists. The 10 extras are Accessibility, AlarmClock, Archive,
Award, Backpack, Bike, Bird, Camera, Coffee and Compass; the two-icon
case uses the first two. SVG complexity, toolchain and source implementation
change the result.
Binary size is not RAM usage. Selected sources borrow static bytes without a
copy/cache; actual rendering still allocates for parsing, rasterization and
render caches. Runtime shared-name lookup can retain a name/path table, and
Cargo's downloaded package/build artifacts still contain the complete catalog.
On WASM, Assets::new(endpoint) and AllAssets::new(endpoint) use the existing
on-demand CDN loader instead of embedding the complete bundle.
The shared icon names and assets for GPUI Kit, exposed as
gpui_kit::assets. The crate depends on GPUI, not GPUI Component, so Base and
alternative presentation layers can use its complete IconName catalog.
gpui_kit::assets::IconName provides the complete shared catalog without a
Component dependency. gpui_kit::component::IconName remains the original
compatibility enum: existing imports, exhaustive matches and .view(cx) calls
continue to work without a new trait import. Icon::new(...) accepts either
type. A legacy name converts into the shared name with .into().
For the new shared enum, use Icon::new(name).view(cx) when a component entity
is needed, or import gpui_kit::component::IconNameExt to call name.view(cx).
The catalog contains all 1,818 Lucide 1.43.0 icons plus 12 retained GPUI Kit
icons. IconName::ALL enumerates it; names are generated from bundled SVGs
at build time without network access or another crate's source directory.
Default component icons and application extras
Keep the existing registration:
use gpui_kit::assets::Assets;
let app = gpui_kit::application().with_assets(Assets);
On native platforms, this embeds only the original component icons listed in
default-icons.txt. Existing Assets::get, Assets::iter, Assets::new and
AssetSource behavior remain available. Applications can embed additional SVGs
with their own asset source and fall back to Assets for component paths, as
before. See Icons & Assets and
the extra-assets example for source composition.
For selecting bundled extras without copying SVG files, the optional macro creates a separate source:
use gpui_kit::assets::icon_assets;
icon_assets!(ExtraIcons, [Accessibility, AlarmClock]);
Compose ExtraIcons with Assets in your application's AssetSource; it does
not replace the default component bundle automatically. Only the selected SVGs
are referenced on native and WASM, unlisted paths return Ok(None), and loads
borrow static bytes. Selection is explicit at compile time. Optional visibility
is supported (icon_assets!(pub ExtraIcons, [...])). Applications without
Component can register a selected source alone.
Explicit complete bundle
Register AllAssets if you intentionally want every bundled icon available on
native platforms. On WASM, Assets::new(endpoint) and AllAssets::new(endpoint)
use the same existing on-demand CDN loader. Deploy assets/icons under
{endpoint}/assets/icons/. The selected macro source needs no CDN.
Updating Lucide
lucide.json pins the upstream version, archive SHA-256, and canonical icon
count. Update those fields for a new release, then run from the repository root:
bun script/sync-lucide.ts
bun script/sync-lucide.ts --check
Requires Bun with Bun.Archive support. Use
--archive /path/to/archive.tar.gz for offline operation. The script checks
the archive hash, copies every canonical SVG and the upstream license, and
preserves custom/retired filenames. It does not expand the default component
bundle: changes to default-icons.txt are deliberate compatibility decisions.
--check verifies every upstream file byte for byte.
License
Crate code: Apache-2.0. Lucide SVGs: ISC, with the upstream Feather-derived icons under MIT; see LICENSE-LUCIDE for complete attribution.