feat(M7): pages, Liquid Glass dock + UI library#11
Merged
Conversation
Build out Milestone 7 against the supplied PencilKit-style design frames: a Liquid Glass component library, the bottom drawing dock, the iOS color picker, multi-page boards, and a light/dark theme toggle. packages/ui (Liquid Glass library) - Theme system (useTheme/applyTheme/getInitialTheme): light + dark token sets on [data-theme], persisted to localStorage, defaulting to OS preference. - Glass primitives: GlassPanel, GlassButton, Popover (portal + speech-bubble tail), Sheet (bottom sheet on narrow screens), Segmented, Slider (opacity track), Swatch (rainbow ring variant). - Faithful SVG drawing instruments (pen, fineliner, highlighter, eraser, pencil, marker) that lift when active. - Single design-system stylesheet exported as @notux/ui/styles.css. Dock (Frames 1 & 2) - Bottom-centered glass dock replaces the old left ToolPalette: instruments + rainbow color swatch + "+" tray (select/shapes/text/import/theme toggle). - Per-instrument settings (dockStore) — each instrument remembers its color, width and opacity and pushes resolved values into toolStore so the canvas tools pick them up. Active instrument lifts; tapping it opens a width-preset + opacity popover. Color picker (Frame 3) - Grid + Sliders tabs, opacity slider, saved swatches (persisted), and the EyeDropper API where supported. Pages - Synced ordered page list in the Yjs doc (sync/pageList.ts) with seeding that migrates existing single-page boards. pageStore mirrors shapeStore's Yjs-binding/revision pattern; active page is local per-user. Board threads the active pageId into CanvasStage/SelectionInspector; navigator pill + tray for add/switch/rename/delete/reorder. Stroke pipeline - Add opacity + style to ToolOptions/YStroke/DraftStroke; PenTool writes them (the old highlighter x4 size hack is removed); StrokeRenderer/OverlayLayer apply style-specific paint (highlighter = multiply) without double-applying the Group opacity already handled in ShapesLayer. Theming - CSS tokens moved into the UI library; canvas Konva layers read theme colors via cssVar() and re-render on toggle. Inspector/home restyled to tokens.
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.
Milestone 7, built against the three supplied Apple PencilKit / iOS-style design frames: the Liquid Glass UI library, the bottom drawing dock, the color picker, multi-page boards, and a light/dark theme toggle.
What's in it
@notux/ui— Liquid Glass library (was an empty stub)useTheme/applyTheme/getInitialTheme): light + dark token sets on[data-theme], persisted tolocalStorage, defaulting to OS preference; applied before first paint (no flash).GlassPanel,GlassButton,Popover(portal + speech-bubble tail),Sheet(bottom sheet on narrow screens),Segmented,Slider(opacity track),Swatch(rainbow-ring variant).@notux/ui/styles.css.Dock (Frames 1 & 2)
ToolPalette: instruments + rainbow color swatch + a "+" tray (select / shapes / text / import / theme toggle).dockStore): each instrument remembers its color, width and opacity and pushes resolved values intotoolStoreso the canvas tools pick them up. The active instrument lifts; tapping it opens a width-preset + opacity popover.Color picker (Frame 3)
localStorage), and theEyeDropperAPI where supported. (Spectrum tab intentionally omitted per the agreed scope.)Pages
packages/sync/src/pageList.ts) with seeding that migrates existing single-page boards (keepspage-0content selectable).pageStoremirrorsshapeStore's Yjs-binding/revisionpattern; the active page is local per-user.Boardthreads the activepageIdintoCanvasStage/SelectionInspector; a navigator pill + tray handles add / switch / rename / delete / reorder.Stroke pipeline
opacity+styletoToolOptions/YStroke/DraftStroke;PenToolwrites them;StrokeRenderer/OverlayLayerapply style-specific paint (highlighter =multiply) without double-applying the Group opacity already handled inShapesLayer. The old highlighter ×4 size hack is removed (widths are now WYSIWYG).Theming
cssVar()helper and re-render on toggle. Inspector + home restyled to tokens.Scope decisions (confirmed with the requester)
Verification
pnpm -r typecheck— all 5 packages clean.pnpm build— full production build succeeds (Vite, 340 modules;@notux/uiCSS bundled).tsc, run on Node against realyjs): fresh-seed, idempotent seeding, migration of existingpage-0boards, multi-page migration, add / rename / reorder / delete (delete also drops the page's shapes), and cross-Y.Docreplication (the multiplayer path). 11/11 pass.selectInstrumentpushes the resolved preset intotoolStore; per-instrument color/width/opacity memory survives switching; eraser → eraser tool; highlighter width is no longer ×4. 10/10 pass.Notes
Pagetype / DB table already existed but was unused; this PR syncs page metadata via Yjs (consistent with how shapes sync). Server-side page persistence and live page thumbnails are left as follow-ups.ToolPalette.tsxand its CSS were removed (superseded by the dock); its image/PDF import logic moved into the dock's "+" tray.Generated by Claude Code