Skip to content

design(web): Living Interface - the room replaces the dashboard#71

Merged
knzeng-e merged 2 commits into
feat/production-preview-assetsfrom
design/living-interface
Jul 7, 2026
Merged

design(web): Living Interface - the room replaces the dashboard#71
knzeng-e merged 2 commits into
feat/production-preview-assetsfrom
design/living-interface

Conversation

@knzeng-e

@knzeng-e knzeng-e commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Stacked on #70 (base: feat/production-preview-assets), per request. Tracked as docs/backlog/22-living-interface.md; full rationale in docs/design/dotify-living-interface.md.

The argument

The console design was disciplined, but it read as a dashboard: 81 hairline-bordered boxes, 4-8px corners, panels declaring their edges. A dashboard is a tool you operate; Dotify's philosophy says a listening room is a place you inhabit. Same argument as the product's Web3 stance: infrastructure (keys, policies, chains) disappears behind the human experience. Borders are the UI equivalent of exposed plumbing.

Five gestures (one scoped CSS layer)

  1. Light replaces the line. Panel borders go transparent; separation now comes from tonal layering (--surface-lit/deep) and from the playing track's aura tinting every major surface (color-mix on --aura-a/b/accent). The room's color IS the structure.
  2. Geometry relaxes. Radius tokens move from console (4-8px) to human (12-22px); grid gaps and padding open up.
  3. Floating layers become deep glass. Topbar dissolves into a scrim; the player dock becomes an aura-tinted floating glass capsule; modals become deep translucent slabs; the bottom nav loses its rule line.
  4. Chat becomes a conversation. Asymmetric bubbles; your own messages aura-tinted and right-aligned. The request queue deliberately stays a curated list (it is a queue, not a dialogue) with the host veto quiet until hover/focus - those rules are dormant until the queue PR (feat(web): room collaborative request queue with host veto #68) merges, so it lands already dressed.
  5. Motion breathes on one curve. One easing (cubic-bezier(0.22, 1, 0.36, 1)), two tempos (160ms interaction / 420ms entrance), staggered rise when a view opens, all disabled under prefers-reduced-motion.

What deliberately did not change

  • Identity: palette (deep blue core, cyan action, restrained pink), Hanken Grotesk, the aura engine, all product language. docs/index.html stays aligned, so no Pages update needed.
  • Behavior/markup/copy/tests: the layer is pure CSS appended to styles.css, cascade-ordered, zero !important.
  • Honesty: every lit pixel maps to real state - the aura is the actual playing track, bubbles are real people, nothing renders that the backend did not produce.
  • Allowed borders: inputs, dividers, code fields, and status pills keep their hairlines (the design system's sanctioned border uses).

Verification

  • build (tsc + vite) clean, lint 0 errors (3 pre-existing warnings), test:unit 75/75, fmt:check clean.
  • Reduced-motion audited: every animation and hover-lift in the layer is disabled under prefers-reduced-motion.
  • Not done: a visual/screenshot pass in a running browser - reviewers should npm run dev:listen and walk Home, a room with chat, and a modal. The layer is additive CSS, so reverting is deleting one block.

Pre-existing unrelated contracts/ working-tree changes are excluded, as with the previous PRs.

The console design read as a dashboard: 81 hairline-bordered boxes, 4-8px
corners, panels declaring their edges. The philosophy says a listening room
is a place you inhabit, and infrastructure should disappear behind the human
experience. Borders are exposed plumbing.

One scoped CSS layer (appended block, cascade-ordered, no !important) makes
five gestures:

- Light replaces the line: panel borders go transparent; separation comes
  from tonal layering and from the playing track's aura tinting every major
  surface (color-mix on --aura-a/b/accent).
- Geometry relaxes: radius tokens retuned from console (4-8px) to human
  (12-22px); gaps and padding open up.
- Floating layers become deep glass: topbar dissolves to a scrim, player
  dock becomes an aura-tinted glass capsule, modals become deep translucent
  slabs, bottom nav loses its rule line.
- Chat becomes a conversation: asymmetric bubbles, self messages aura-tinted
  and right-aligned; the request queue stays a curated list, host veto quiet
  until hover/focus (rules dormant until the queue PR merges).
- Motion breathes: one easing curve, two tempos (160/420ms), staggered rise
  on view open, everything off under prefers-reduced-motion.

Purely presentational: no markup, behavior, copy, or test changes. Identity
(palette, type, aura engine) and the honesty rule are untouched. Rationale in
docs/design/dotify-living-interface.md, tracked as ticket 22.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@knzeng-e knzeng-e self-assigned this Jul 7, 2026
@knzeng-e

knzeng-e commented Jul 7, 2026

Copy link
Copy Markdown
Owner Author

@claude please review this. Sois critique des choix, designs et UX, je veux la plus fluide, la plus sobre mais la plus belle / stylées des Dapp du monde

@claude

claude Bot commented Jul 7, 2026

Copy link
Copy Markdown

Claude finished @knzeng-e's task in 6m 20s —— View job


Review: Living Interface

  • Read trigger comment and PR context
  • Read backlog ticket + design doc
  • Read full diff on web/src/styles.css
  • Check CLAUDE.md constraints (borders, quotes, App.tsx, etc.)
  • Critical UX/design review
  • Post final review

Verdict

The direction is right and the writing in the design doc is honest about tradeoffs — that's rare. But I traced the actual cascade instead of trusting the narrative, and the execution has two concrete gaps that contradict the PR's own thesis ("light replaces the line"). Neither is cosmetic nitpicking; both are things a "most sober, most fluid" DApp cannot ship with. Not blocking on principle, but I'd fix both before merge.

1. Real bug: modal padding regresses on mobile

web/src/styles.css:7629-7633 (pre-existing, inside @media (max-width: 760px)):

.modal-card {
  width: min(100%, calc(100dvw - 1.5rem));
  padding: 1rem;
}

The new block appends, unconditionally, at web/src/styles.css:9365-9372:

.modal-card {
  ...
  padding: 1.5rem;
}

Same specificity, later in source order, no media guard → on every viewport ≤760px (and ≤420px, styles.css:7654-7658), the new rule wins the cascade and the "compact mobile" padding is silently discarded. The result: bigger padding exactly where width is tightest, on WalletModal, CreateRoomModal, and every other .modal-card. This is the "walk a modal on your phone" case the PR itself flags as unverified in a browser — worth checking, because I'm fairly confident it regresses.

Fix this →

2. Design inconsistency: the "border removal" list is incomplete relative to the token retune

The block redefines --radius-lg, --radius-container, etc. globally (styles.css:9294-9299), so every consumer of those tokens jumps from the 4-8px "console" scale to 12-22px — but only ~7 selectors also get border-color: transparent. Several surfaces share the exact same original rule as things that were de-bordered, and now sit with a visibly bigger radius and their original hairline still on:

  • .home-listening-hero (styles.css:3715-3716) — border: 1px solid rgba(255,255,255,0.105) kept, radius jumps 8→22px. Used in ListenView.tsx (Home).
  • .artist-profile-hero (styles.css:4052-4053) — same pattern, ArtistProfileView.tsx.
  • .room-live-card (styles.css:5461-5462), .commons-step / .commons-live-join (styles.css:5860-5861), .solo-room-invite (styles.css:5999-6000) — all in RoomsView.tsx, i.e. exactly the "room" surfaces the philosophy is about.
  • .metric, .rooms-live-panel, .rooms-join-panel (styles.css:6369-6374) — styled in the same shared rule as .doc-panel (border: 1px solid rgba(101,139,165,0.16)), but .doc-panel is in the new de-border list and these three siblings aren't. So a .doc-panel next to a .metric tile will now visually diverge: one is glass, the other is a bigger-radius box with the old hairline.
  • .player-view-grid .cover (styles.css:3942-3946) keeps a 0 0 0 1px rgba(255,255,255,0.11) inset ring (a border simulated via box-shadow, not caught by any border-color rule) around the exact same enlarged radius.

Net effect: on Home, Rooms, and Player — the three surfaces the PR explicitly asks reviewers to walk — some cards go full "light replaces the line" and their immediate neighbors keep a hard edge at a now-much-rounder corner. That's a more visible tell of an unfinished pass than any single border would have been on its own, because it reads as inconsistent rather than as a deliberate "allowed border" (inputs/dividers/pills are a coherent exception; a stat tile sitting next to a de-bordered panel is not).

Fix this →

Smaller notes (not blocking)

  • Stagger only covers the first 3 grid children (content-grid > :nth-child(2/3), styles.css:9484-9490). Intentional per the comment ("stagger the first ranks"), but on a catalogue grid with a dozen cards, everything past rank 3 pops in simultaneously — worth a quick look in the browser to confirm it doesn't read as "first 3 animate, rest snap."
  • .side-rail-item[data-active='true'] is defined twice: once inside a min-width media query (styles.css:7350, sets background + color: var(--color-primary)) and once unconditionally in the new block (styles.css:9402, sets background via aura color-mix + an inset ring). They compose rather than one cleanly replacing the other — the active nav item ends up with an aura-tinted background and the old green text color. Probably fine, but worth eyeballing since the two weren't designed together.
  • The PR is honest that a real browser pass wasn't done — given the two cascade-order issues above were only found by tracing specificity/source-order (not by reading either rule in isolation), that visual pass matters more here than usual. I'd actually load Home + a room + a modal at ≤420px before merging.

What's genuinely good

  • The aura-tinting via color-mix on real playing-track colors keeps the "honesty rule" intact — nothing decorative that isn't backed by real state.
  • One easing curve, two tempos, and full prefers-reduced-motion coverage on every transform-based animation — this is the kind of restraint that actually reads as "sober" rather than "understyled."
  • No !important anywhere; the whole layer really is just cascade order, which makes it revertable in one block as claimed.
  • Scoping the change to design tokens (--radius-*, --surface-lit/deep) instead of one-off per-component overrides is the right architecture — issue [Sprint 0][P0] Backend key service skeleton #2 above is a gap in coverage of that architecture, not a flaw in the architecture itself.

Bottom line: good taste, right instinct, not yet finished — the two issues above are exactly the kind of thing that turns "beautiful room" into "beautiful room with three panels that still look like a spreadsheet." Worth another pass before merge.

@knzeng-e knzeng-e added enhancement New feature or request frontend P2 labels Jul 7, 2026
Two cascade-order gaps found by tracing specificity, plus the stagger note:

- Mobile modal padding regressed: the block's unconditional
  `.modal-card { padding: 1.5rem }` sat after the `@media (max-width: 760px)`
  compact-padding rule at equal specificity, so it silently won on the
  tightest screens. Gate the roomier padding behind `min-width: 761px`.
- Border-removal coverage was incomplete relative to the global radius
  retune: several surfaces consumed the enlarged radius tokens but kept their
  hairlines, so de-bordered glass panels sat beside bigger-radius framed
  boxes on Home, Rooms, and Player. Extend the treatment to `.metric` /
  `.rooms-live-panel` / `.rooms-join-panel` (match their `.doc-panel`
  sibling), transparent the edges on the hero and room cards
  (`.home-listening-hero`, `.artist-profile-hero`, `.room-live-card`,
  `.commons-step`, `.commons-live-join`, `.solo-room-invite`) while keeping
  their bespoke aura backgrounds, and drop the simulated 1px inset ring on
  `.player-view-grid .cover` while keeping its aura glow.
- Extend the content-grid entrance stagger through rank 5+ so a view reads
  as one cascade instead of "first ranks animate, rest snap."

Still pure CSS, cascade-ordered, no !important. Build/lint/test/fmt green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@knzeng-e knzeng-e left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

reviewed

@knzeng-e
knzeng-e merged commit f8aa7d4 into feat/production-preview-assets Jul 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request frontend P2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant