Integrate Liquid Parchment design language#2
Open
pauljunsukhan wants to merge 19 commits into
Open
Conversation
Adopts a parchment-and-glass material vocabulary across chrome: GlassSurface primitive (tint/intensity/radius/shadow/bloom/pressed), ambient sun + device tilt physics, and a press-leaves-warmth afterglow. Composer becomes a plain Glass card with directional dispersion; empty-state owl gains a breathing radial halo (OwlLight) on web and native. Adds a /gallery route with frozen reference stamps, a viz suite (HeatGrid, Sparkline, RingStat, StatBar, EventDot), and Storybook scaffolding for primitive isolation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the toolbar pencil button (long-press a tile enters global edit mode instead), the tap-to-open-chat shortcut, and per-tile resize/move/ refresh handles. In edit mode tiles shake gently, gain a center pencil (edit prompt), a delete X corner, and the banner offers a Done button. Field-note tiles flatten to plain parchment Glass — no more category tints or left-edge accent stripes — keeping the focus on the content the prompt produced. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Top of board now breathes (paddingTop 18) so the heatmap card no longer kisses the chrome capsule. Small status tiles tighten — display font 17pt with negative tracking so "now" / "91%" / "5" fit without clipping; captions drop to 9pt with shortened mappings (src, ppl, mood, fresh). Mood mini limits to three days at medium so the pill stack no longer spills into the next tile. The back-of-card now renders a clean "guardian read" commentary line keyed off the tile kind, replacing the generic ASCII "what to inspect" frame — placeholder for the assistant streaming this back in production. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The prompt composer used to render as a card at the top of the scroll content. If you long-pressed a tile far down the board and tapped the center pencil, the editor opened off-screen and you had to scroll up to reach it. Now the composer is a backdrop+sheet overlay anchored to the screen, slid in from below the chrome capsule, with the parchment behind dimmed. The web focus outline on the textarea is suppressed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Anchored to viewport center with justifyContent: 'center' so the editor sits naturally where the eye lands when you tap a pencil, regardless of where the tile lives on the board. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Old curve swung opacity 0.78 -> 1.00, a 22% sliver of an already half-transparent halo — easy to miss as static. Widen to 0.55 -> 1.00 with a synchronized 0.94 -> 1.06 scale pulse so the halo physically expands as it brightens. Cycle drops to 4.5s for a more breath-like cadence than the previous 6s drift. Reads as lung, not flicker. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous swing (0.55-1.00 opacity, 0.94-1.06 scale) was correct in DOM but invisible to the eye — warm peach overlay on warm parchment with small modulation reads as static. Bump to a 5x opacity swing and a 40% scale pulse, sync them, drop cycle to 3.6s. Halo now visibly inhales from a faint glow up to full saturation and back, like a slow lung. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two design fixes that move the halo from "clipped sticker" toward ambient light: 1. CSS radial-gradient defaults to farthest-corner extent — fades to 0 at the diagonal of the bounding box, leaving a visible rectangular shoulder at edge midpoints. Switch to `closest-side` so the gradient ends at an inscribed circle; corners are simply transparent. Native SVG path uses r=0.5 for the same effect. 2. Single sin-pulse reads as mechanical. Layer two phases at 7s and 12s — incommensurate periods whose interference pattern never quite repeats. Caustics' trick applied to a single light source. Pull the loud channel back to opacity 0.55-1.00 and scale 0.95-1.06; the restraint plus the multi-frequency wander is what sells "alive at rest" rather than the swing magnitude. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Four small fixes that all read as "designed", not "happens to render": * Chromatic rim opacities pulled down ~60% (top 0.96 → 0.42, bottom 0.46 → 0.18, sides 0.46 → 0.18) and stroke 1.6 → 1.0. The rim was meant to be a refraction hint half-cropped to a hairline; at the previous saturations it landed as a visible coral stripe on small surfaces. Now it's a faint warm/cool edge that reads as a real bevel rather than a stray line. * ShellHeader switches tint="amber" radius=999 → tint="plain" radius="lg". Pulls the chrome capsule into the same vocabulary as composer + tiles so the whole app speaks one curve language instead of "pill on top, cards on bottom". * Drawer's bottom-nav border-top removed. The line above "Field Notes" read as an accidental separator, not an intentional rule. * Chat markdown's code_inline overrides the library default's box — transparent background, no border, just deepAccent + underline so a filename or path renders as a plain link instead of a boxed sticker. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The header was using tint="plain" which flattens the directional tint, specular sheen, and chromatic rim — the very effects that make Liquid Parchment surfaces feel alive. Switch to tint="gold" radius="xl" intensity="medium": the chrome capsule now actively reads sun direction (warm left, cool right), catches a diagonal specular streak, and keeps a soft chromatic edge. xl (18) instead of lg (14) gives the chrome a different curve from cards — hierarchy by radius. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… artifact The gold/xl/strong header looked active but violated three of Apple's HIG principles for Liquid Glass (iOS 26): 1. Tint should feel like ONE colored wash, not a gradient with bright/ dark halves. Gold's hot rgba(248,196,72,0.26) -> cold rgba(120,84,28, 0.16) span had enough contrast that the cool stop on the right edge read as a *separate surface* — what looked like an "inner pill" around the edit icon was actually the cold side of the directional tint. 2. Hierarchy comes from blur depth, not tint contrast. Apple's larger surfaces are MORE opaque, smaller surfaces clearer; here the chrome capsule is the largest single surface so it should lean opaque. Kept radius="xl" but bumped intensity to "strong" for that real frosted-glass body. 3. Buttons sit ON the glass, not in their own backdrop. The IconButton children already have no background, so the visible "pill" was purely from #1; eliminating directional tint contrast removes it. Switched to: tint="plain" — uniform warm-cream wash, no hot/cold split intensity="strong" — heavier blur, more material presence rim={false} — no chromatic edge fighting the body specular={false} — no diagonal sheen creating visible regions Result: a single, restful glass capsule that elevates the content underneath instead of competing with it. Sources consulted: - Apple HIG navigation bars + tab bars (iOS 26 / Liquid Glass) - Hierarchy/Harmony/Consistency principles (createwithswift) - Tab bar anti-patterns ("don't design junk", Bootcamp/Medium) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Critical: every <Svg> inside GlassSurface (directional tint, specular
sheen, chromatic rim) was rendering at 300x150 — react-native-svg's
default size when no explicit width/height attrs are set. The
StyleSheet.absoluteFill style positions the element to fill the parent
but does not cascade dimensions into the SVG attribute layer; the
parent's CSS sizes the box but the SVG paints into its own viewBox.
On surfaces ≤300x150 (every tile in field notes, the composer, button
pills) this happened to be invisible because the SVG already covered
the whole surface. On the ShellHeader (336x48), the tint and rim
clipped at x=312, leaving the right ~24px of the capsule unpainted —
which read as a separate "inner pill" around the edit icon. The
exact UX bug Apple's HIG warns about.
Adding width="100%" height="100%" forces the SVG to fill its parent
in pixels, not the implicit 300x150 default. Verified via DOM probe:
all four SVGs (tint, specular, two rim Rects) now report 336x48 to
match the header.
Side effect: the ShellHeader can drop its `rim={false} specular={false}`
overrides — the previous "we're disabling these because they look
broken" was actually just the clipping bug. The full Liquid Glass
material physics now read correctly across the whole capsule.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shellInner row used alignItems: 'center' which floated the buttons to the vertical middle of an expanding composer — when the textarea grew to 6+ lines the + and send sat halfway up the message body, away from where the eye expects controls. Switch to alignItems: 'flex-end' so the buttons stick to the bottom of the capsule regardless of text height. Same pattern as iMessage / Slack / GitHub. Drop the now-redundant alignSelf: 'center' on leadingBtn and sendBtn so they inherit the parent's flex-end. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous flex-end change made buttons hug the bottom of a 44px input area, leaving them visibly low in the empty/single-line state (button bottom at row bottom, not row center). Lower MIN_INPUT_HEIGHT to layout.iconHit (36) so the input's natural single-line height matches the button height — flex-end then renders identical to alignItems: 'center' in that state. Multi-line behavior is unchanged: text grows up, buttons stay anchored to the bottom. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The home screen IS the new-chat surface; the SquarePen "new chat" button in the right slot was a noop in context — same screen, same empty composer. Removing it leaves the header with just the menu button, matching the visual restraint of the rest of the chrome. The header itself is already consistent across screens (same ShellHeader component on /, /dashboard, /chat/[id], /settings); each screen contributes its own right-slot actions, no longer shadowed by a useless self-link on the home screen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ng pulse
The previous +/send buttons were Lucide icons (three stroked lines)
on flat colored circles — two off-the-shelf pieces stuck together.
Replaced with a single integrated control that earns its place in
the Liquid Parchment system:
* Each disc is a real <GlassSurface> (radius=999 pill), so the same
ambient sun + directional tint + chromatic rim machinery the rest
of the app uses applies to the buttons too. Not a flat fill colored
disc anymore.
* Glyphs are designed FILLED paths, not stroked icon-set imports:
- Send: pointed tip, weighted shoulders, 6-unit stem, drawn into
a 36-viewBox so it sits cleanly in the disc.
- Stop: rounded square at the same scale.
- Plus: two overlapping rounded rects so the caps feel cut, not
stroked.
* Three states for the trailing button (idle / send / thinking) drive
the disc tint: plain → gold → teal. When the agent is responding
("thinking"), a soft halo ring expands outward and fades in a 1.4s
loop, while the disc itself breathes a subtle 4% scale at half that
period. The same stop-square glyph stays put so the affordance
doesn't change — only the motion tells you guardian is working.
* AttachmentButton is the leading-edge sibling: same GlassSurface
recipe, plain tint, weak intensity, designed plus glyph. The two
buttons read as one designed pair instead of "icon set on a circle".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…edit The previous send/+ design used solid filled discs with custom SVG glyphs — fine in isolation, but next to the menu / share / edit icons in the top capsule it read as "default messaging app", not "guardian's quiet notebook". The chrome icons are stroked Lucide at ~1.6-1.8; filled discs clash with that serif-refined language. Replaced both buttons with stroked Lucide icons at 2.0 stroke (slightly bolder than the menu chrome — these are primary controls in the composer's row, the family is the same but with a bit more weight). No background disc, no GlassSurface — just the icon on the chrome. Color follows state: idle → placeholder muted (low contrast: "can't send") send → text full (full contrast: "press me") thinking → deepAccent + slow opacity breath (in progress) The thinking state swaps the arrow for a filled stop square so the affordance changes too, not just the color. Dashboard edit-mode also gets tap-to-dismiss: tapping a tile body in edit mode now exits edit mode (pencil + delete X intercept first since they're nested pressables), and a backdrop pressable on the empty board area dismisses too. Drag-to-rearrange still pending. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The top capsule was reading as heavy on every flat-parchment screen. On a backdrop with no atmospheric content for the BlurView to refract, even weak intensity left a visible plain-tinted pill that competed with the page rather than receding into it. The user-facing fix is what should have been the structural one all along: there is no capsule. The header is now just menu / title / right-slot floating directly on the parchment. Same content, same layout — just no glass pane behind it. Page is the material; chrome is the icons. The composer at the bottom keeps its capsule because there it WRAPS an editable surface where the capsule has a job (hosting the input). Up top there was no input to host — just three icons and a title — so the capsule was ornament that had become noise. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lass plain tint has a low-saturation cool-paper cold stop (rgba(212,222,232, 0.22)) that reads as a graphite-pencil smudge on parchment — the mid-tone grays drag the surface from "glass" toward "paper with shadow". cool tint anchors the cold stop in a lighter blue and the hot stop in a pale daylight cast; combined with intensity="weak" (the StatusPill primitive's recipe — the cleanest glass elsewhere in the system) the chrome reads as a crystalline pane rather than a smudged sheet. The rim and specular still fire so the bevel + sun-catch keep the surface alive without the muddy mid-tones. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
(drawer)/index.tsxand(drawer)/chat/[id].tsx./galleryroute with frozen reference stamps so chrome compositions stay in lock-step with the running app.Note on conflicts
This branch is ~4 commits behind
origin/main. There is significant overlap with recent chat / dashboard / design-token work on main, so this needs a careful review and rebase before merge.Test plan
npx tsc --noEmitpasses/(new chat) renders empty-state owl with warm halo and plain-card composer/chat/[id]empty state renders the same halo/gallerychrome-composition stamps match the running app🤖 Generated with Claude Code