Skip to content

Commit 0e91cbf

Browse files
Nigel TatschnerNigel Tatschner
authored andcommitted
feat: PostW5 Wave C — type plateau + Hangar refresh reframe
C1 — type hierarchy plateau (audit v2 §03) - `main h1 { font-size: 28px }` in globals.css drops the default browser 2em (~32px) baseline for every page that doesn't override inline. Inner pages stop competing with top-of-funnel surfaces. - Removed the inline `fontSize: 32` overrides on /admin/sharing and /admin/sharing/audit so those (deeper) pages inherit the smaller baseline. /sharing keeps its inline 32 — it's a top-level user surface and is the only remaining "page tier" h1. - Net result: 2-tier plateau. Top-level pages stay loud (32px via opt-in inline); inner pages settle at 28px by default. Detail pages can opt into a smaller tier later by setting inline `fontSize: 24`. HangarCard — refresh reframe (audit v2 §08) - Dropped the TODO that promised a parallel inline "Refresh now" button to ProfileCard/OrgsCard. That button can't truthfully exist: the server holds zero RSI credentials by design — only the tray (RSI cookie in the OS keychain) can pull a fresh pledges page without breaking that trust boundary. - Replaced with a subtle "Updated via tray · open Devices →" link in the card header, framing the refresh path the user actually has rather than a fake button. Doc comment now explains the constraint instead of marking it pending. Held back (out of audit scope this wave) - C2 (eyebrow reduction) — `ss-eyebrow` appears in 45 files. A bulk delete needs the audit doc's "which to keep" rule to avoid over-pruning the design language. Surfaced as a future audit-by-page rather than guessed here. Checks: pnpm typecheck clean.
1 parent 989fbac commit 0e91cbf

4 files changed

Lines changed: 36 additions & 13 deletions

File tree

apps/web/src/app/admin/sharing/audit/page.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ export default async function AdminSharingAuditPage(props: {
211211
<h1
212212
style={{
213213
margin: 0,
214-
fontSize: 32,
215214
fontWeight: 600,
216215
letterSpacing: '-0.02em',
217216
}}

apps/web/src/app/admin/sharing/page.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ export default async function AdminSharingOverviewPage() {
9393
<h1
9494
style={{
9595
margin: 0,
96-
fontSize: 32,
9796
fontWeight: 600,
9897
letterSpacing: '-0.02em',
9998
}}

apps/web/src/app/globals.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ main {
6565

6666
main h1 {
6767
margin-top: 0;
68+
/* Audit v2 §03 type plateau: drop the default browser 2em (~32px)
69+
down to 28px so inner pages don't compete with top-of-funnel
70+
surfaces. Top-level pages that want the louder 32px set it
71+
inline; detail pages can opt into a smaller tier the same way. */
72+
font-size: 28px;
6873
}
6974

7075
.muted {

apps/web/src/components/HangarCard.tsx

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@ import type { HangarSnapshot } from '@/lib/api';
99
* without launching the tray. The empty state nudges users who haven't
1010
* paired the tray yet, since that's the only writer.
1111
*
12-
* TODO(audit-v2 §08): ProfileCard + OrgsCard got promoted to inline
13-
* "Refresh now" buttons backed by server actions. Hangar can't follow
14-
* suit yet — there's no `refreshHangar()` in `apps/web/src/lib/api.ts`
15-
* because the tray client is the only writer of `/v1/me/hangar`. Once
16-
* a server-side refresh endpoint exists, mirror the ProfileCard
17-
* pattern: import a `refreshHangarAction` from
18-
* `@/app/_actions/refresh-rsi`, gate on owner-side state, and render
19-
* `<RefreshSubmitButton />` in the card header. Until then, the empty
20-
* state's "Pair a device" link is the only refresh affordance.
12+
* No inline "Refresh now" button (unlike ProfileCard / OrgsCard): the
13+
* server holds zero RSI credentials by design — only the tray, running
14+
* on the user's machine and reading the RSI cookie out of the OS
15+
* keychain, can pull a fresh pledges page without breaking that trust
16+
* boundary. So the affordance is a tray-launch hint ("Updated via tray
17+
* · open Devices") rather than a Server Action — the truthful framing
18+
* of where the refresh actually happens.
2119
*/
2220

2321
const SHIP_PREVIEW_LIMIT = 6;
@@ -101,8 +99,30 @@ export function HangarCard({
10199

102100
return (
103101
<section className="ss-card ss-card-pad">
104-
<div className="ss-eyebrow" style={{ marginBottom: 6 }}>
105-
Hangar
102+
<div
103+
style={{
104+
display: 'flex',
105+
justifyContent: 'space-between',
106+
alignItems: 'baseline',
107+
gap: 12,
108+
marginBottom: 6,
109+
}}
110+
>
111+
<div className="ss-eyebrow">Hangar</div>
112+
{/* Truthful refresh affordance — the tray is the only writer
113+
(RSI cookie sits in the OS keychain), so the link points at
114+
the device-pairing surface rather than promising a
115+
web-side refresh that can't exist. */}
116+
<Link
117+
href="/devices"
118+
style={{
119+
fontSize: 11,
120+
color: 'var(--fg-muted)',
121+
textDecoration: 'none',
122+
}}
123+
>
124+
Updated via tray · open Devices →
125+
</Link>
106126
</div>
107127
<h2
108128
style={{

0 commit comments

Comments
 (0)