Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/test-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
paths:
- "website/**"
- "themes/**"
- "Cargo.toml"
- "script/build-website-versions"
- "script/snapshot-website"
- "script/test-snapshot-website"
Expand Down Expand Up @@ -40,7 +41,9 @@ jobs:
SHOWCASES_DIR: ${{ github.workspace }}/.showcases
run: |
../script/test-snapshot-website
bun run test:docs
bun run test:showcases
bun run build
bun run test:seo
bun run test:links
bun run test:versioned-examples
12 changes: 12 additions & 0 deletions script/build-website-versions
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ mkdir -p "$repo_root/website/dist"

git -C "$repo_root" worktree add --detach "$work_dir/main" origin/main >/dev/null

# Documentation writes `{{gpui_pre_version}}` for the GPUI snapshot; each
# build resolves it from the Cargo.toml of the revision it documents, because
# the temporary website copies have no workspace manifest next to them.
gpui_pre_version() {
git -C "$repo_root" show "$1:Cargo.toml" 2>/dev/null \
| sed -nE 's/^gpui[[:space:]]*=.*package[[:space:]]*=[[:space:]]*"gpui-pre".*version[[:space:]]*=[[:space:]]*"=?([^"]+)".*/\1/p' \
| head -n 1
}

snapshot_website() {
local tag=$1
local target=$2
Expand All @@ -78,6 +87,7 @@ ln -s "$repo_root/website/node_modules" "$latest_dir/node_modules"
echo "Building $latest_release at /"
(
cd "$latest_dir"
GPUI_PRE_VERSION="$(gpui_pre_version "$latest_release")" \
PUBLIC_SITE_VERSION="$latest_release" \
PUBLIC_SITE_LATEST_VERSION="$latest_release" \
PUBLIC_SITE_INDEXABLE=true \
Expand All @@ -100,6 +110,7 @@ echo "Building main at /versions/main"
(
cd "$main_dir"
ln -s "$repo_root/website/node_modules" node_modules
GPUI_PRE_VERSION="$(gpui_pre_version origin/main)" \
PUBLIC_SITE_VERSION=main \
PUBLIC_SITE_LATEST_VERSION="$latest_release" \
PUBLIC_SITE_INDEXABLE=false \
Expand Down Expand Up @@ -134,6 +145,7 @@ for tag in "${release_tags[@]:1}"; do
echo "Building $tag at /versions/$tag"
(
cd "$version_dir"
GPUI_PRE_VERSION="$(gpui_pre_version "$tag")" \
PUBLIC_SITE_VERSION="$tag" \
PUBLIC_SITE_LATEST_VERSION="$latest_release" \
PUBLIC_SITE_INDEXABLE=false \
Expand Down
3 changes: 3 additions & 0 deletions website/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ Chinese. Monospace prefers `ui-monospace` / SF Mono and falls back to
- **Body** — 1rem, line-height 1.7; docs prose is capped at `46rem`.
- **Kicker / label** — 0.66–0.68rem mono, uppercase, wide tracking, muted.
Small mono labels, not colour, mark structure.
- **Maturity labels** (`maturity` frontmatter) sit between a page title and its
standfirst as the same mono labels on a hairline border. Preview and
Experimental are not warnings, so they take no status colour.

Two constraints that are easy to get wrong:

Expand Down
28 changes: 28 additions & 0 deletions website/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,31 @@ with `bun install --frozen-lockfile --cwd ../../gpui-kit-showcases` before build
The release workflow fetches the latest approved catalog automatically; see the
[Showcase contribution guide](https://github.com/longbridge/gpui-kit-showcases/blob/main/CONTRIBUTING.md)
for app submissions and full-window screenshot instructions.

## Writing documentation

The site is published once per version: the latest release at `/`, `main` at
`/versions/main`, and older releases at `/versions/<tag>`. Pages must keep the
reader in the version they are reading.

- **Link to the Markdown file with a relative path**, such as
`[Entity](./entity.md)` or `[Dialog](../component/dialog.md)`. The build
resolves it inside the current version. A site-root path such as
`/docs/entity` points at the default version and is rejected by
`bun run test:docs`. A Chinese page links the Chinese page when one exists.
- **Write `{{gpui_pre_version}}` for the GPUI snapshot version**, in prose,
code and links alike, for example
`https://docs.rs/gpui-pre/{{gpui_pre_version}}/gpui/struct.Window.html`.
The value comes from the `gpui` entry in the workspace `Cargo.toml`, so a
snapshot bump updates every page in both locales. `bun run test:docs`
rejects the pinned version written out by hand; a deliberate reference to
another snapshot is listed in `tests/doc-sources.test.ts`.
- **Mark maturity in the frontmatter** of a page whose capability is not on
the stable desktop path: `maturity: [preview]`, `[experimental]`,
`[showcase-only]`, or `[platform-dependent]`, combined as needed. Unmarked pages are Stable. The
labels render under the title and link to their definitions on the
documentation home. Both locales must carry the same value.

`bun run test:links` checks every link in a finished build, and
`bun run test:versioned-examples` repeats that check for a build at
`/versions/test/`, where a link that leaves the version fails.
20 changes: 13 additions & 7 deletions website/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { rehypeHeadingIds, unified } from '@astrojs/markdown-remark';
import { remarkCallouts } from './src/lib/remark-callouts.js';
import { remarkComparisonStatus } from './src/lib/remark-comparison-status.js';
import { remarkDocLinks } from './src/lib/remark-doc-links.js';
import { remarkDocVariables } from './src/lib/doc-variables.js';
import { remarkMaturity } from './src/lib/remark-maturity.js';
import { remarkSnippets } from './src/lib/remark-snippets.js';
import { rehypeHeadingAnchors } from './src/lib/rehype-heading-anchors.js';
import { wasmExamplesDevServer } from './src/lib/wasm-middleware.js';
Expand Down Expand Up @@ -56,12 +58,16 @@ export default defineConfig({
outDir: resolve(process.cwd(), process.env.SITE_OUT_DIR || './dist'),
output: 'static',
trailingSlash: 'never',
redirects: {
...componentRedirects,
...legacyDocRedirects,
'/docs/ui-testing': '/docs/test',
'/zh-CN/docs/ui-testing': '/zh-CN/docs/test',
},
// Astro places each source below `base` but writes the destination as
// given, so a versioned build would redirect into the default version.
redirects: Object.fromEntries(
Object.entries({
...componentRedirects,
...legacyDocRedirects,
'/docs/ui-testing': '/docs/test',
'/zh-CN/docs/ui-testing': '/zh-CN/docs/test',
}).map(([from, to]) => [from, `${BASE.replace(/\/$/, '')}${to}`]),
),

integrations: [
vue({ devtools: false }),
Expand All @@ -72,7 +78,7 @@ export default defineConfig({
// Astro 7 made Sätteri the default processor; the remark/rehype pipeline is
// opt-in now, and the math plugins only run on it.
processor: unified({
remarkPlugins: [remarkMath, remarkSnippets, remarkCallouts, remarkComparisonStatus, [remarkDocLinks, { base: BASE }]],
remarkPlugins: [remarkMath, remarkSnippets, remarkCallouts, remarkComparisonStatus, remarkDocVariables, remarkMaturity, [remarkDocLinks, { base: BASE }]],
rehypePlugins: [rehypeMathjax, rehypeHeadingIds, rehypeHeadingAnchors],
}),
shikiConfig,
Expand Down
2 changes: 1 addition & 1 deletion website/component/collapsible.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,6 @@ Collapsible::new()
.content(options)
```

The content remains mounted while closed so it can be measured and immediately reverse if toggled mid-animation. Without `motion_id`, the component keeps the immediate mount/unmount behavior. See the [GPUI Base Motion guide](/base/motion) for timing, reduced-motion, and performance details.
The content remains mounted while closed so it can be measured and immediately reverse if toggled mid-animation. Without `motion_id`, the component keeps the immediate mount/unmount behavior. See the [GPUI Base Motion guide](../base/motion.md) for timing, reduced-motion, and performance details.

[Collapsible]: https://docs.rs/gpui-component/latest/gpui_component/collapsible/struct.Collapsible.html
2 changes: 1 addition & 1 deletion website/component/dock.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Dock builds application workspaces from draggable tab groups, nested splits, and

`gpui-base` owns the data model, layout calculation, and drag-and-drop behavior. `gpui-component` supplies the polished controls and visual language. Use `gpui_kit::component::dock` when you want a Dock ready to fit into a real application.

For the renderer-independent architecture and custom-renderer API, see [Dock — gpui-base](/base/dock).
For the renderer-independent architecture and custom-renderer API, see [Dock — gpui-base](../base/dock.md).

## Create a dock area

Expand Down
12 changes: 6 additions & 6 deletions website/component/focus-trap.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: A utility element that traps keyboard focus within a container, pre

Focus trap utility for constraining keyboard focus within a specific container. Essential for modal dialogs, sheets, and overlay components to provide proper keyboard navigation accessibility.

**Note:** [Dialog](/component/dialog) and [Sheet](/component/sheet) components have focus trap built-in. You only need to manually use `focus_trap()` for custom modal-like components.
**Note:** [Dialog](./dialog.md) and [Sheet](./sheet.md) components have focus trap built-in. You only need to manually use `focus_trap()` for custom modal-like components.

## Import

Expand Down Expand Up @@ -245,12 +245,12 @@ impl Render for ModalView {

## See Also

- [Root View System](/component/root) - Manages focus trap behavior at the window level
- [Dialog](/component/dialog) - Uses focus trap automatically
- [Sheet](/component/sheet) - Uses focus trap automatically
- [Root View System](./root.md) - Manages focus trap behavior at the window level
- [Dialog](./dialog.md) - Uses focus trap automatically
- [Sheet](./sheet.md) - Uses focus trap automatically
- [focus-trap-react](https://github.com/focus-trap/focus-trap-react) - Similar concept for React applications

[Root]: https://docs.rs/gpui-component/latest/gpui_component/struct.Root.html
[FocusTrapElement]: https://docs.rs/gpui-component/latest/gpui_component/trait.FocusTrapElement.html
[Dialog]: /component/dialog
[Sheet]: /component/sheet
[Dialog]: ./dialog.md
[Sheet]: ./sheet.md
2 changes: 1 addition & 1 deletion website/component/hover-card.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ HoverCard component for displaying rich content that appears when the mouse hove

This is most like the [Popover] component, but triggered by hover instead of click, and with timing controls for a smoother user experience.

On iOS and Android, tap the trigger to open or close the card. Tapping outside closes it; tapping inside keeps it open. Hover delays do not apply. Tooltip hints remain disabled; see [Mobile](/docs/mobile).
On iOS and Android, tap the trigger to open or close the card. Tapping outside closes it; tapping inside keeps it open. Hover delays do not apply. Tooltip hints remain disabled; see [Mobile](../docs/mobile.md).

## Import

Expand Down
8 changes: 4 additions & 4 deletions website/component/text-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ description: Renders Markdown and HTML text with optional custom Markdown plugin

`TextView` renders formatted text in GPUI. It supports Markdown and simple HTML, text selection, code block actions, and custom Markdown plugins for project-specific syntax.

The canonical implementation now lives in `gpui-base`; this module remains a compatibility re-export and provides component-theme adaptation. Base-only setup, complete default styling, and opt-in syntax highlighting are documented on [GPUI Base TextView](/base/text-view).
The canonical implementation now lives in `gpui-base`; this module remains a compatibility re-export and provides component-theme adaptation. Base-only setup, complete default styling, and opt-in syntax highlighting are documented on [GPUI Base TextView](../base/text-view.md).

TextView is selectable by default and uses the shared window selection engine from `gpui-base`. Use `.selectable(false)` only when selection must be disabled. See [GPUI Base Text Selection](/base/text-selection) when integrating plain text or a custom renderer with the same selection.
TextView is selectable by default and uses the shared window selection engine from `gpui-base`. Use `.selectable(false)` only when selection must be disabled. See [GPUI Base Text Selection](../base/text-selection.md) when integrating plain text or a custom renderer with the same selection.

## Import

Expand Down Expand Up @@ -93,7 +93,7 @@ reduced motion. Nothing animates unless the view opts in.

Pass a `TextViewMotion` through `.motion(...)` to choose the duration or
easing yourself, or to reveal each chunk word by word; see
[GPUI Base TextView](/base/text-view#retained-state-and-streaming-updates).
[GPUI Base TextView](../base/text-view.md#retained-state-and-streaming-updates).

### Highlight ranges

Expand Down Expand Up @@ -215,7 +215,7 @@ following the finger while it stays down. Lifting it opens an edit menu with
Dragging a handle moves that end while the other stays put; `Select All`
selects the view that was pressed, and its handles keep working on the result.

The handles and the menu are drawn by [`Root`](/component/root) for the whole
The handles and the menu are drawn by [`Root`](./root.md) for the whole
window selection, so they cover a selection that spans several views. A tap
elsewhere clears them, and the menu steps aside while the content scrolls
under a finger.
Expand Down
1 change: 1 addition & 0 deletions website/component/title-bar.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: TitleBar
description: A custom window title bar component with window controls and custom content support.
maturity: [platform-dependent]
---

# TitleBar
Expand Down
2 changes: 1 addition & 1 deletion website/component/tooltip.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ A versatile tooltip component that displays helpful information when hovering ov

## Mobile behavior

On iOS and Android, tooltips managed by the GPUI Base overlay are disabled. Shared components may keep their tooltip configuration, but mobile actions still need visible or accessible labels. Direct GPUI `.tooltip()` calls, including the basic `div()` example below, bypass this overlay and are not disabled by this policy. See [Mobile](/docs/mobile) for integration guidance.
On iOS and Android, tooltips managed by the GPUI Base overlay are disabled. Shared components may keep their tooltip configuration, but mobile actions still need visible or accessible labels. Direct GPUI `.tooltip()` calls, including the basic `div()` example below, bypass this overlay and are not disabled by this policy. See [Mobile](../docs/mobile.md) for integration guidance.

## Import

Expand Down
2 changes: 1 addition & 1 deletion website/docs/action.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ order: -2.62

An **Action** represents an operation the application can perform. A shortcut, menu item, command palette, button, or another Action handler can all dispatch the same typed value. GPUI routes it to the part of the [Element](./element) tree that owns the command. An [Event](./event) serves the other direction: it reports something that happened after state changed.

The [GPUI Action source](https://docs.rs/crate/gpui-pre/0.3.6/source/src/action.rs) defines the macro, trait, and registry described here.
The [GPUI Action source](https://docs.rs/crate/gpui-pre/{{gpui_pre_version}}/source/src/action.rs) defines the macro, trait, and registry described here.

This page explains command definition and dispatch. Start with [Focus](./focus) if you have not yet created a keyboard target; see [KeyBinding](./keybinding) for key notation, context matching, and keymap setup.

Expand Down
6 changes: 3 additions & 3 deletions website/docs/animation.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ GPUI Kit offers three levels of motion. Choose by **what owns the changing value
| Level | Use it for | State and policy |
| --- | --- | --- |
| GPUI `Animation` and `AnimationExt` | An element entering, pulsing, or running a fixed series while mounted | GPUI retains playback under the wrapper's [`ElementId`](./element_id); the caller chooses duration, easing, and visual property. |
| [GPUI Base Motion](/base/motion) | A target that changes during motion, an exit before unmount, keyframes, or measured reveal | Base retains each channel under a stable key and requests frames through [Window](./window) while active; the caller chooses the visual result. |
| [GPUI Base Motion](../base/motion.md) | A target that changes during motion, an exit before unmount, keyframes, or measured reveal | Base retains each channel under a stable key and requests frames through [Window](./window) while active; the caller chooses the visual result. |
| GPUI Component motion | A styled control whose appearance follows the theme | `cx.theme().motion_tokens()` supplies semantic timing, easing, springs, and distances; components compose these with GPUI or Base. |

The application owns the semantic state: whether a dialog is open, which tab is selected, or where a slider points. An animation samples that state for presentation. Keep the result understandable at both endpoints and when motion is disabled.
Expand Down Expand Up @@ -113,7 +113,7 @@ The excerpt shows the lifecycle decision; the [full example](https://github.com/

## GPUI's element animation

`Animation::new(duration)` creates a one-shot, linear animation. `AnimationExt::with_animation(id, animation, animator)` wraps an `IntoElement`; the callback receives that element and an eased progress value. GPUI calls it during layout, applies the returned element's style, and requests another frame until the animation ends. The callback may change any property supported by that element, such as opacity or a transform. See the [GPUI 0.3.6 animation source](https://docs.rs/gpui-pre/0.3.6/src/gpui/elements/animation.rs.html) for the wrapper's playback rules. Here `gpui-pre` is the publication and version-alignment package name for GPUI; it is not an additional application layer.
`Animation::new(duration)` creates a one-shot, linear animation. `AnimationExt::with_animation(id, animation, animator)` wraps an `IntoElement`; the callback receives that element and an eased progress value. GPUI calls it during layout, applies the returned element's style, and requests another frame until the animation ends. The callback may change any property supported by that element, such as opacity or a transform. See the [GPUI {{gpui_pre_version}} animation source](https://docs.rs/gpui-pre/{{gpui_pre_version}}/src/gpui/elements/animation.rs.html) for the wrapper's playback rules. Here `gpui-pre` is the publication and version-alignment package name for GPUI; it is not an additional application layer.

```rust
use std::time::Duration;
Expand Down Expand Up @@ -280,7 +280,7 @@ Base also provides the following choices:
| Delay repeated items | `Stagger` | Computes a delay by index and origin; it does not own the list or its IDs. |
| Expand content of unknown height | `MotionReveal` | Measures the child and clips its visible height by caller-supplied progress. It does not sample or animate progress itself. |

See the [Base Motion guide](/base/motion) for the full signatures, validation rules, examples, and benchmark. Its `Transition` is distinct from the older `gpui_kit::base::animation::EffectTransition`, which wraps GPUI `with_animation` to apply predefined fade, slide, width, and height effects. For new target-driven work, use `base::motion` primitives and apply the sampled value yourself.
See the [Base Motion guide](../base/motion.md) for the full signatures, validation rules, examples, and benchmark. Its `Transition` is distinct from the older `gpui_kit::base::animation::EffectTransition`, which wraps GPUI `with_animation` to apply predefined fade, slide, width, and height effects. For new target-driven work, use `base::motion` primitives and apply the sampled value yourself.

## GPUI Component: semantic motion policy

Expand Down
2 changes: 1 addition & 1 deletion website/docs/assets.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,6 @@ On WebAssembly, `Assets::new(endpoint)` and `AllAssets::new(endpoint)` use the s

[rust-embed]: https://docs.rs/rust-embed/latest/rust_embed/
[IconName]: https://docs.rs/gpui-kit-assets/0.6.5/gpui_kit_assets/enum.IconName.html
[Icon]: https://docs.rs/gpui-component/0.6.5/gpui_component/struct.Icon.html
[Icon]: https://docs.rs/gpui-component/latest/gpui_component/struct.Icon.html
[assets]: https://github.com/longbridge/gpui-kit/tree/main/crates/assets/assets/icons
[gpui-kit-assets]: https://docs.rs/crate/gpui-kit-assets/0.6.5
Loading
Loading