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
7 changes: 7 additions & 0 deletions skills/gpui-kit-design-guides/references/design-guides.md
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,13 @@ In a segmented control, the selected fill and unselected surface must share
the container's silhouette. Neither may square off an end corner or make a
boundary appear heavier than its peers.

Show a selected navigation item, list row, or tab through the item's own
surface: a selected fill, stronger foreground, or heavier weight. Do not add a
leading-edge bar or one-sided border as the selection marker. It is a web
template habit, not a desktop convention; it breaks the item's rounded
silhouette and adds a second, competing edge to a column that already aligns
on its text.

For destructive actions, distinguish between reversible and irreversible work.
Prefer undo or a temporary notification for reversible changes. Use an
`AlertDialog` when the consequence is serious and cannot be undone; name the
Expand Down
6 changes: 5 additions & 1 deletion website/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,13 @@ site and the documented components share one palette.
Rules that follow from this:

- **The brand colour is near-black (near-white in dark mode).** It is used for
primary buttons, focus rings and the active sidebar indicator — never as an
primary buttons and focus rings — never as an
"accent" to add interest, because it is the same value as body text. Section
kickers and captions use `--muted-foreground` instead.
- **The active sidebar item is a fill, not a bar.** It takes `--sidebar-accent`
(stronger than the `--secondary` hover fill) and a heavier weight. Never mark
it — or any selected item — with a leading-edge bar or one-sided border; see
the selection rule in the Design Guides.
- **Never use `--brand` as a background behind text you did not also invert.**
Text selection in particular uses `--selection`: black text on a near-black
selection is unreadable.
Expand Down
7 changes: 7 additions & 0 deletions website/docs/design-guides.md
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,13 @@ In a segmented control, the selected fill and unselected surface must share
the container's silhouette. Neither may square off an end corner or make a
boundary appear heavier than its peers.

Show a selected navigation item, list row, or tab through the item's own
surface: a selected fill, stronger foreground, or heavier weight. Do not add a
leading-edge bar or one-sided border as the selection marker. It is a web
template habit, not a desktop convention; it breaks the item's rounded
silhouette and adds a second, competing edge to a column that already aligns
on its text.

For destructive actions, distinguish between reversible and irreversible work.
Prefer undo or a temporary notification for reversible changes. Use an
`AlertDialog` when the consequence is serious and cannot be undone; name the
Expand Down
21 changes: 20 additions & 1 deletion website/src/components/Sidebar.astro
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,27 @@ export interface Props {

const { items, currentPath, lang = 'en' } = Astro.props;

function isActive(link: string): boolean {
function matches(link: string): boolean {
return currentPath === link || currentPath.startsWith(link + '/');
}

function links(items: SidebarItem[]): string[] {
return items.flatMap(item => [
...(item.link ? [item.link] : []),
...(item.items ? links(item.items) : []),
]);
}

// A section root such as `/docs` prefixes every page under it, so only the
// longest matching link is current; otherwise two items light up at once.
const activeLink = links(items)
.filter(matches)
.sort((a, b) => b.length - a.length)[0];

function isActive(link: string): boolean {
return link === activeLink;
}

---

<aside class="docs-sidebar" aria-label={lang === 'zh-CN' ? '文档导航' : 'Documentation navigation'}>
Expand All @@ -38,6 +55,7 @@ function isActive(link: string): boolean {
<a
href={sub.link}
class={`sidebar-item${sub.link && isActive(sub.link) ? ' active' : ''}`}
aria-current={sub.link && isActive(sub.link) ? 'page' : undefined}
>
{sub.text}
</a>
Expand All @@ -50,6 +68,7 @@ function isActive(link: string): boolean {
<a
href={item.link}
class={`sidebar-item${item.link && isActive(item.link) ? ' active' : ''}`}
aria-current={item.link && isActive(item.link) ? 'page' : undefined}
>
{item.text}
</a>
Expand Down
19 changes: 16 additions & 3 deletions website/src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -1502,7 +1502,12 @@ html.dark .astro-code span {
.sidebar-item {
display: block;
margin-inline: -0.5rem;
padding: 0.28rem 0.5rem;
/* A transparent border, with the fill clipped inside it, leaves a 2px gap
between the hover and active fills of adjacent items. The padding gives
the pixel back so rows keep their height and text stays aligned. */
padding: calc(0.28rem - 1px) calc(0.5rem - 1px);
border: 1px solid transparent;
background-clip: padding-box;
border-radius: var(--radius-control);
color: var(--foreground);
font-size: 0.8125rem;
Expand All @@ -1511,8 +1516,16 @@ html.dark .astro-code span {
transition: color 140ms ease, background 140ms ease;
}

.sidebar-item:hover { background: var(--secondary); }
.sidebar-item.active { color: var(--foreground); font-weight: 650; }
.sidebar-item:hover { background-color: var(--secondary); }
/* The current page has to be found at a glance after scrolling a long
article, so it takes the sidebar accent fill (stronger than hover), not
weight alone. */
.sidebar-item.active,
.sidebar-item.active:hover {
background-color: var(--sidebar-accent);
color: var(--sidebar-accent-foreground);
font-weight: 650;
}

.sidebar-subgroup-title {
padding: 0.28rem 0.5rem;
Expand Down
2 changes: 2 additions & 0 deletions website/zh-CN/docs/design-guides.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ GPUI flex child 即使设置 `flex_1()`,也可能因为长内容拒绝收缩

分段控件的选中填充与未选中表面必须共享容器轮廓。两端不应露出直角,每处边界的视觉厚度也应一致。

导航项、列表行与标签页的选中状态应由条目自身的表面表达:选中填充、更强的前景色或更重的字重。不要用左侧竖条或单侧边框作为选中标记。这是网页模板的习惯,而非桌面惯例:它会打断条目的圆角轮廓,并在本已按文字对齐的列中加入一条相互竞争的边缘。

破坏性操作要区分可逆与不可逆。可逆变更优先 undo 或临时 notification;严重且不可撤销时才使用 `AlertDialog`,确认文案必须写出具体对象和后果。

### 指针约定
Expand Down
Loading