Skip to content

feat(v2): Connectors and Tools rows in Direction A — marks, one worded act, mono kicker - #1782

Merged
lilyshen0722 merged 3 commits into
mainfrom
wave/connectors-direction-a
Sep 20, 2026
Merged

lilyshen0722 merged 3 commits into
mainfrom
wave/connectors-direction-a

Conversation

@lilyshen0722

Copy link
Copy Markdown
Contributor

Artboard first

Drawn and read before this cut: Connectors, quieter v3 — https://claude.ai/artifact/4GvYVrBNoFSHukdCZDEcsu (rendered 1440 and 390 frames in Sharpen 70220/70221). ux-lead's read (70159–70161, 70216–70218) is applied; the two Sam calls are drawn as the reviewer recommended: Revoke as the ✕, providers as rows with Add.

What changes on the page

rule before after
1 · categories are marks relay mode was a sentence in the row; the live dot was cobalt a 16px glyph (attention / mirror / off), sentence in title + aria-label; the dot is ink / hollow / dashed / grey
2 · only the deciding act is a word Manage was a bordered word; "Choose a pod" on provider rows Manage is the 32px gear (44 on the phone), word in title + aria-label; provider rows say Add; Revoke in the aside is the ✕ beside Change access and still confirms
3 · meta is mono chips "added 23 days ago" in its own column pod · verb age mono-11 kicker above line 1 on every row; the column is gone; at 390 the mode word rides the kicker

Files: V2ConnectorsPage.tsx, V2ConnectorTools.tsx, icons/glyphs.tsx (gear act, relay marks), v2.css, en.json (six keys, all with defaultValue fallbacks — zh-CN follows the open zh-CN coverage row).

Proof

  • V2ConnectorsPage.test.tsx: Direction A: a linked row carries a mono kicker, a relay mark with its sentence in the label, and Manage as the gear; age assertions moved to the kicker.
  • V2ConnectorTools.test.tsx: Manage buttons are the gear with the word in the label; the age column is gone and the kicker carries · granted.
  • v2-layout-invariants.test.ts: three-track row grid, ink dot (not accent, no status colour), mono-11 kicker, mode word hidden above 760 and shown under it, gear 32 / 44.
  • 168/168 across the three suites; tsc --noEmit 0 errors; eslint 0 errors.

Screenshots at 1440 / 720 / 390 from the fixture build, before and after, follow in the next commit (ux-lead gates at all three).

🤖 Generated with Claude Code

https://claude.ai/code/session_01W7WB68pA8L2nkvSqZPx37w

@lilyshen0722

Copy link
Copy Markdown
Contributor Author

Evidence committed at ec6dc666: docs/design/evidence/connectors-direction-a-{before,after}-{1440,720,390}.png — fixture build (same seeded rows both sides: a linked Telegram with relay on, an unlinked GitHub App, Slack and Telegram as provider rows, the not-yet row; one GitHub grant to Sharpen, Calendar not granted), DPR 2, before = origin/main, after = this branch.

Measured on the page (.v2-connectors innerText and DOM):

before after
kickers 0 6
relay marks (role img) 0 1
worded buttons 14 12
glyph-only buttons with a label 0 2
gear height 1440 / 720 / 390 32 / 44 / 44
fonts under 11px (390) 0 0

Gates asked: ux-lead at 1440/720/390 (Sharpen), Wren's read and Vera's exact-head clearance (Connectors lane). Pressed by me only on both.

@lilyshen0722

Copy link
Copy Markdown
Contributor Author

Recut for Vera's hold at 3084de5a (rebased onto current main, after #1778):

  1. Locale-safe kickers. shortAge(date) derives the age from the timestamp through time.age.{justNow,minutes,hours,days}; each verb line is a key with an {{age}} slot (connectors.age.added|started|since|paused|slackAnswered, tools.grantedAge). No .replace(/ ago$/) anywhere; the visible en strings are unchanged (added 23d, granted 6d), so the committed pair still shows the pixels.
  2. Manifest. zh-CN.json carries every new key path; translationKeys.test.ts is 4/4. The Chinese values (添加 · 无 Pod · 暂未支持 · 提醒 · 镜像 · 中继已关 · {{age}}前添加 … · 刚刚 / {{n}}分钟 / {{n}}小时 / {{n}}天) follow the locked glossary (Pod stays Pod) and are for Sam's native-speaker read; change any of them freely, the test needs the paths.

172/172 across the two component suites, the layout invariants and the manifest test; tsc and eslint clean.

@samxu01
samxu01 force-pushed the wave/connectors-direction-a branch from ec6dc66 to 3084de5 Compare September 19, 2026 20:30

@lilyshen0722 lilyshen0722 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX-GATE: PASS @ 3084de5 — fixture build at 1440 / 720 / 390 (mock API, worktree at the head; interdiff from ec6dc66 is the kicker's key-and-timestamp composition only, re-measured on the new bundle).

1440. 11 rows on the three-track grid (140 / 502 / 120), no age column. Every row carries the Plex Mono 11 lowercase kicker (sharpen · added 6d, no pod · not connected, connectors v2 · started 2d, not yet, sharpen · granted 6d, not granted); mode word display:none. Relay mark 16×16 with the sentence in title + aria-label (attention · escalations reach the channel, relay off · messages stay in the pod); Tools write-mode glyph titled read / read and write, ask first. Gear 32×32, title + aria Manage; word acts 32 tall (Add 50, Ask 49, New code 85, Pick a pod 88). Dots: live ink #101828 (+pulse on the live Telegram and the GitHub grant), idle #e4e7ec, empty hollow #98a2b3, revoked filled grey, not-yet dashed. Nothing under 11px; no green; no cobalt inside a row. Grant aside: Change access 115×36 + ✕ (path M18 6 6 18M6 6l12 12, title + aria Revoke) → Yes, revoke it 110×40 / Keep it 68×36.

720 and 390. Rows 89–170 tall (min 72 holds); gear 44×44 in row 1 beside the name; a row's word act is full width (662 / 332) and 44 tall; the mode word rides the kicker (… · attention, … · relay off, … · nothing asks first, … · every write asks first) and the mark is hidden; no horizontal overflow (scrollWidth = viewport at both); Tools head, search and All / Granted / Not yet segments present; aside ✕ 44×44 Revoke. Min font 11 at both.

Non-blocking, for the follow-up row:

  1. At 1440 the aside ✕ measures 32×36 — the flex row stretches it to Change access's height. The rule names a 32 square; align-self: center (or accept 36) — under 760 it is a correct 44 square.
  2. After 3084de5 the not-enabled catalog row's kicker is just no pod (was no pod · —). Better than the dash; not enabled would give it a verb like every other row. Nit.
  3. On connected rows the mark sits alone on line 3 (detail is empty) — reads as the v3 chip line; taste only.
  4. Pre-existing, not this PR: Discord · WhatsApp wraps in the 140 name column at 1440 and butts the sentence.

Captures at the three widths posted in Sharpen.

@lilyshen0722

Copy link
Copy Markdown
Contributor Author

zh-CN gate: Sam passed the 13 Chinese strings as written ("All good", 2026-09-19 ~20:35Z, in his session with Wave). The native-speaker hold on this PR is cleared; remaining gates are Vera's stamp at 3084de5a and ux-lead's at 1440/720/390.

@lilyshen0722

Copy link
Copy Markdown
Contributor Author

Rebased onto main 8bfca7b7 → head c586c70f; patch-id 21aeb8474392 unchanged from 3084de5a (ux-lead's PASS and Wren's read carry; evidence PNGs untouched). Correction to my previous comment: Sam's pass on the zh-CN strings was at 23:56Z, not 20:35Z. Waiting on Vera's stamp at this head.

@samxu01
samxu01 force-pushed the wave/connectors-direction-a branch from 3084de5 to c586c70 Compare September 19, 2026 23:57
lilyshen0722 and others added 3 commits September 19, 2026 17:07
…d act, mono kicker

The ruled direction (Sam, 2026-09-11) applied to the shipped Connectors
page, drawn first as the "Connectors, quieter" artboard (v3, ux-lead's
pixel read applied, Sharpen 70159–70161 and 70216–70218).

Rule 1, categories are marks. Relay mode on a linked channel row is a
16px glyph (attention / mirror / off) with the sentence in title and
aria-label; the state dot is ink filled, hollow, dashed or grey, never
cobalt. The Tools write-mode glyph already followed this.

Rule 2, only the deciding act is a word. Manage is the 32px gear on both
lists (44 on the phone, right-aligned), the word in title and aria-label;
Add, Pick a pod, New code and Ask keep their words. A provider row's act
says Add, since the pod is chosen in the aside. In the grant aside,
Revoke is the ✕ beside Change access (the Deny precedent) and still asks
to confirm.

Rule 3, meta is mono chips. Every row carries `pod · verb age` in mono 11
above line 1 (`rewire live demo · added 23d`, `sharpen · granted 6d`,
`no pod · not connected`); the age column is gone. At 390, where
tooltips do not exist, the mode word rides the kicker instead of the
glyph; a row's word act is full width and rows keep one height.

Tests: the linked row's kicker, mark (role img + label) and gear are
pinned on both pages; ages are asserted on the kicker; the layout
invariants pin the three-track grid, the ink dot, the mono-11 kicker,
the hidden mode word and the 32/44 gear. 168/168 across the three suites;
tsc and eslint clean.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7WB68pA8L2nkvSqZPx37w
…de line, with evidence

From the first fixture capture: at 390 the gear sat above the row and the
not-enabled row's Ask kept its old placement, because the new act rules
were declared before the older phone rule in the same media block. They
now follow it; the selection button is pinned to row 1 so the 44px gear
shares it beside the name; a row's word act is full width under the
sentence; the kicker keeps clear of the gear. The Tools row no longer
pairs the write-mode glyph with its words — the audience is the sentence,
the glyph carries the mode, and the words ride the 390 kicker.

Evidence (fixture build, DPR 2, before = main, after = this branch), at
1440 / 720 / 390, under docs/design/evidence/connectors-direction-a-*.png.
Measured on the after page: 6 kickers, 1 relay mark, gear 32px at 1440
and 44px at 720/390, nothing under 11px; worded buttons 14 → 12.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7WB68pA8L2nkvSqZPx37w
…es carry its keys

Vera's hold (Connectors 70299/70300): the kickers stripped " ago" off
already-rendered English, which breaks under any other locale, and six
keys were added to en.json without zh-CN.json, so the migration manifest
test went red (identical base key paths).

Now `shortAge(date)` turns the timestamp into a unit-suffixed number
through `time.age.*` keys ("23d", "5m", "just now") and each verb line is
a key with an `{{age}}` slot (`connectors.age.added|started|since|paused|
slackAnswered`, `tools.grantedAge`); the kicker composes the pod name and
that line and never touches rendered text. A row with no age (the
not-enabled row's dash) carries only the pod.

zh-CN carries every new key path. The Chinese values follow the locked
glossary (Pod stays Pod, 你 register, no English left in the 中文 UI) and
are marked for Sam's native-speaker read on the PR; the manifest test
needs the paths, not the final wording.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7WB68pA8L2nkvSqZPx37w
@samxu01
samxu01 force-pushed the wave/connectors-direction-a branch from c586c70 to dc117c0 Compare September 20, 2026 00:09
@lilyshen0722
lilyshen0722 merged commit ba3306f into main Sep 20, 2026
14 checks passed
samxu01 pushed a commit that referenced this pull request Sep 20, 2026
#1782)

#1782 landed on main as ba3306f and rule 3 renders the grant age as
`pod · granted 1h` — the `ago` suffix is gone (main's own assertions at
this file were updated in the same PR). These two are the TASK-135 tests
added by this branch, so they were the only ones left asserting the old
string; they fail on the merged tree without this. Mutation-checked:
reverting both to 'granted 1h ago' reds exactly these two.
samxu01 pushed a commit that referenced this pull request Sep 20, 2026
…s its blocker (TASK-140)

Two of the four Direction A follow-ups from ux-lead's #1782 gate.

1. The Revoke ✕ measured 32×36 at 1440. The button carries
   `.v2-connector-aside__secondary` as well as `--icon`, and that rule sets
   `min-height: 36px` — and min-height beats height, so the icon rule's own
   `min-height: 32px` never applied. The first cut of this fix composed the
   selector but set only `height: 32px`, and the gate caught it still measuring
   32×36 (computed min-height 36px): the override has to land on the MINIMUM.
   Both are set now, and the ≤760 rule gets the same treatment so the 44px thumb
   target is not left to be clamped by a 36px floor.

2. A not-enabled catalog row's kicker read `no pod`. The row has no connection
   at all, so the pod slot named something that does not exist and read as a
   missing pod rather than a disabled provider. It now reads `not enabled`
   (en + zh-CN).

Deliberately NOT here, left for ux-lead rather than decided unilaterally:

- the `Discord · WhatsApp` wrap at 1440, whose cause is the 140px name track in
  the connector row grid — pinned as artboard geometry by
  v2-layout-invariants:1732 — and where the obvious CSS (nowrap) is the
  one-line-ellipsis-of-an-identifier pattern this repo already rejected.
- the mark alone on the row's third line, a taste call by construction.

Evidence: V2ConnectorsPage + v2-layout-invariants + V2ConnectorTools = 3 suites
169/169. Mutation-proved alone: dropping `min-height: 32px` reds exactly the new
invariant, and reverting the kicker to the unconditional `no pod` reds exactly
the new behaviour test. eslint 0 errors on the touched files.

The guard for 1 is a presence assertion, and its first form pinned `height` while
asserting `min-height` was ABSENT — green while the box was 36 tall. It asserts
the minimum now; the browser gate remains the instrument that can actually see it.
samxu01 pushed a commit that referenced this pull request Sep 20, 2026
#1782)

#1782 landed on main as ba3306f and rule 3 renders the grant age as
`pod · granted 1h` — the `ago` suffix is gone (main's own assertions at
this file were updated in the same PR). These two are the TASK-135 tests
added by this branch, so they were the only ones left asserting the old
string; they fail on the merged tree without this. Mutation-checked:
reverting both to 'granted 1h ago' reds exactly these two.
samxu01 pushed a commit that referenced this pull request Sep 20, 2026
…s its blocker (TASK-140)

Two of the four Direction A follow-ups from ux-lead's #1782 gate.

1. The Revoke ✕ measured 32×36 at 1440. The button carries
   `.v2-connector-aside__secondary` as well as `--icon`, and that rule sets
   `min-height: 36px` — and min-height beats height, so the icon rule's own
   `min-height: 32px` never applied. The first cut of this fix composed the
   selector but set only `height: 32px`, and the gate caught it still measuring
   32×36 (computed min-height 36px): the override has to land on the MINIMUM.
   Both are set now, and the ≤760 rule gets the same treatment so the 44px thumb
   target is not left to be clamped by a 36px floor.

2. A not-enabled catalog row's kicker read `no pod`. The row has no connection
   at all, so the pod slot named something that does not exist and read as a
   missing pod rather than a disabled provider. It now reads `not enabled`
   (en + zh-CN).

Deliberately NOT here, left for ux-lead rather than decided unilaterally:

- the `Discord · WhatsApp` wrap at 1440, whose cause is the 140px name track in
  the connector row grid — pinned as artboard geometry by
  v2-layout-invariants:1732 — and where the obvious CSS (nowrap) is the
  one-line-ellipsis-of-an-identifier pattern this repo already rejected.
- the mark alone on the row's third line, a taste call by construction.

Evidence: V2ConnectorsPage + v2-layout-invariants + V2ConnectorTools = 3 suites
169/169. Mutation-proved alone: dropping `min-height: 32px` reds exactly the new
invariant, and reverting the kicker to the unconditional `no pod` reds exactly
the new behaviour test. eslint 0 errors on the touched files.

The guard for 1 is a presence assertion, and its first form pinned `height` while
asserting `min-height` was ABSENT — green while the box was 36 tall. It asserts
the minimum now; the browser gate remains the instrument that can actually see it.
samxu01 pushed a commit that referenced this pull request Sep 20, 2026
#1782)

#1782 landed on main as ba3306f and rule 3 renders the grant age as
`pod · granted 1h` — the `ago` suffix is gone (main's own assertions at
this file were updated in the same PR). These two are the TASK-135 tests
added by this branch, so they were the only ones left asserting the old
string; they fail on the merged tree without this. Mutation-checked:
reverting both to 'granted 1h ago' reds exactly these two.
samxu01 pushed a commit that referenced this pull request Sep 23, 2026
…s its blocker (TASK-140)

Two of the four Direction A follow-ups from ux-lead's #1782 gate.

1. The Revoke ✕ measured 32×36 at 1440. The button carries
   `.v2-connector-aside__secondary` as well as `--icon`, and that rule sets
   `min-height: 36px` — and min-height beats height, so the icon rule's own
   `min-height: 32px` never applied. The first cut of this fix composed the
   selector but set only `height: 32px`, and the gate caught it still measuring
   32×36 (computed min-height 36px): the override has to land on the MINIMUM.
   Both are set now, and the ≤760 rule gets the same treatment so the 44px thumb
   target is not left to be clamped by a 36px floor.

2. A not-enabled catalog row's kicker read `no pod`. The row has no connection
   at all, so the pod slot named something that does not exist and read as a
   missing pod rather than a disabled provider. It now reads `not enabled`
   (en + zh-CN).

Deliberately NOT here, left for ux-lead rather than decided unilaterally:

- the `Discord · WhatsApp` wrap at 1440, whose cause is the 140px name track in
  the connector row grid — pinned as artboard geometry by
  v2-layout-invariants:1732 — and where the obvious CSS (nowrap) is the
  one-line-ellipsis-of-an-identifier pattern this repo already rejected.
- the mark alone on the row's third line, a taste call by construction.

Evidence: V2ConnectorsPage + v2-layout-invariants + V2ConnectorTools = 3 suites
169/169. Mutation-proved alone: dropping `min-height: 32px` reds exactly the new
invariant, and reverting the kicker to the unconditional `no pod` reds exactly
the new behaviour test. eslint 0 errors on the touched files.

The guard for 1 is a presence assertion, and its first form pinned `height` while
asserting `min-height` was ABSENT — green while the box was 36 tall. It asserts
the minimum now; the browser gate remains the instrument that can actually see it.
samxu01 pushed a commit that referenced this pull request Sep 23, 2026
#1782)

#1782 landed on main as ba3306f and rule 3 renders the grant age as
`pod · granted 1h` — the `ago` suffix is gone (main's own assertions at
this file were updated in the same PR). These two are the TASK-135 tests
added by this branch, so they were the only ones left asserting the old
string; they fail on the merged tree without this. Mutation-checked:
reverting both to 'granted 1h ago' reds exactly these two.
samxu01 pushed a commit that referenced this pull request Sep 23, 2026
…s its blocker (TASK-140)

Two of the four Direction A follow-ups from ux-lead's #1782 gate.

1. The Revoke ✕ measured 32×36 at 1440. The button carries
   `.v2-connector-aside__secondary` as well as `--icon`, and that rule sets
   `min-height: 36px` — and min-height beats height, so the icon rule's own
   `min-height: 32px` never applied. The first cut of this fix composed the
   selector but set only `height: 32px`, and the gate caught it still measuring
   32×36 (computed min-height 36px): the override has to land on the MINIMUM.
   Both are set now, and the ≤760 rule gets the same treatment so the 44px thumb
   target is not left to be clamped by a 36px floor.

2. A not-enabled catalog row's kicker read `no pod`. The row has no connection
   at all, so the pod slot named something that does not exist and read as a
   missing pod rather than a disabled provider. It now reads `not enabled`
   (en + zh-CN).

Deliberately NOT here, left for ux-lead rather than decided unilaterally:

- the `Discord · WhatsApp` wrap at 1440, whose cause is the 140px name track in
  the connector row grid — pinned as artboard geometry by
  v2-layout-invariants:1732 — and where the obvious CSS (nowrap) is the
  one-line-ellipsis-of-an-identifier pattern this repo already rejected.
- the mark alone on the row's third line, a taste call by construction.

Evidence: V2ConnectorsPage + v2-layout-invariants + V2ConnectorTools = 3 suites
169/169. Mutation-proved alone: dropping `min-height: 32px` reds exactly the new
invariant, and reverting the kicker to the unconditional `no pod` reds exactly
the new behaviour test. eslint 0 errors on the touched files.

The guard for 1 is a presence assertion, and its first form pinned `height` while
asserting `min-height` was ABSENT — green while the box was 36 tall. It asserts
the minimum now; the browser gate remains the instrument that can actually see it.
samxu01 pushed a commit that referenced this pull request Sep 23, 2026
#1782)

#1782 landed on main as ba3306f and rule 3 renders the grant age as
`pod · granted 1h` — the `ago` suffix is gone (main's own assertions at
this file were updated in the same PR). These two are the TASK-135 tests
added by this branch, so they were the only ones left asserting the old
string; they fail on the merged tree without this. Mutation-checked:
reverting both to 'granted 1h ago' reds exactly these two.
samxu01 pushed a commit that referenced this pull request Sep 23, 2026
…s its blocker (TASK-140)

Two of the four Direction A follow-ups from ux-lead's #1782 gate.

1. The Revoke ✕ measured 32×36 at 1440. The button carries
   `.v2-connector-aside__secondary` as well as `--icon`, and that rule sets
   `min-height: 36px` — and min-height beats height, so the icon rule's own
   `min-height: 32px` never applied. The first cut of this fix composed the
   selector but set only `height: 32px`, and the gate caught it still measuring
   32×36 (computed min-height 36px): the override has to land on the MINIMUM.
   Both are set now, and the ≤760 rule gets the same treatment so the 44px thumb
   target is not left to be clamped by a 36px floor.

2. A not-enabled catalog row's kicker read `no pod`. The row has no connection
   at all, so the pod slot named something that does not exist and read as a
   missing pod rather than a disabled provider. It now reads `not enabled`
   (en + zh-CN).

Deliberately NOT here, left for ux-lead rather than decided unilaterally:

- the `Discord · WhatsApp` wrap at 1440, whose cause is the 140px name track in
  the connector row grid — pinned as artboard geometry by
  v2-layout-invariants:1732 — and where the obvious CSS (nowrap) is the
  one-line-ellipsis-of-an-identifier pattern this repo already rejected.
- the mark alone on the row's third line, a taste call by construction.

Evidence: V2ConnectorsPage + v2-layout-invariants + V2ConnectorTools = 3 suites
169/169. Mutation-proved alone: dropping `min-height: 32px` reds exactly the new
invariant, and reverting the kicker to the unconditional `no pod` reds exactly
the new behaviour test. eslint 0 errors on the touched files.

The guard for 1 is a presence assertion, and its first form pinned `height` while
asserting `min-height` was ABSENT — green while the box was 36 tall. It asserts
the minimum now; the browser gate remains the instrument that can actually see it.
samxu01 pushed a commit that referenced this pull request Sep 23, 2026
#1782)

#1782 landed on main as ba3306f and rule 3 renders the grant age as
`pod · granted 1h` — the `ago` suffix is gone (main's own assertions at
this file were updated in the same PR). These two are the TASK-135 tests
added by this branch, so they were the only ones left asserting the old
string; they fail on the merged tree without this. Mutation-checked:
reverting both to 'granted 1h ago' reds exactly these two.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant