refactor(dev-tweaks): rebuild the panel on a DialKit fork - #285
Open
aimeritething wants to merge 9 commits into
Open
refactor(dev-tweaks): rebuild the panel on a DialKit fork#285aimeritething wants to merge 9 commits into
aimeritething wants to merge 9 commits into
Conversation
Vendor DialKit v1.4.3 (github.com/joshpuckett/dialkit, MIT) into packages/dev-tweaks/src/vendor/dialkit — core + React adapter only — and make it the whole implementation and UI of @workspace/dev-tweaks. The package entry re-exports the DialKit API (useDialKit, useDialKitController, useDialTimeline, DialRoot, DialTimeline) plus a package-owned cssVarOverrides bridge that keeps the old contract: CSS defaults stay the source of truth, inline style carries only overridden values. - Vendored files carry a leading @ts-nocheck and are excluded from Biome and ESLint (see VENDOR.md); re-syncs stay clean overwrites. - apps/ui mounts <DialRoot position="bottom-left"> behind the existing dev/demo build gate; frame mode, the MOCK capsule, and persistence drivers are gone with the old implementation. - Onboarding and horizon tweak defs move to DialKit config tuples with sessionStorage persistence and stable ids. Integer sliders get explicit step 1 — DialKit's inferred step can be coarser than a default (102 with step 5) and its sliders snap values onto the step grid. - Deps: @base-ui/react out, motion in; sideEffects keeps theme.css. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the vendor concept: src/vendor/dialkit becomes src/dialkit, owned and maintained here with no upstream re-sync (VENDOR.md's sync procedure is replaced by ORIGIN.md recording the fork point; the MIT LICENSE stays). Hold the code to the workspace toolchain: - remove every @ts-nocheck header and fix the resulting strict-mode type errors (noUncheckedIndexedAccess guards, React 19 ref/useRef types) - remove the biome.jsonc and eslint ignore carve-outs; fix all lint findings for real (button types, aria on decorative svgs and interactive divs, stable keys, for...of, hoisted regexes, unnested ternaries) — cognitive-complexity and the render-phase ref-mirror pattern are suppressed inline with reasons rather than refactored, keeping the ported logic structurally intact - split DialRoot's enabled gate into a wrapper so hooks no longer sit behind an early return (fixes a real rules-of-hooks hazard) - rename all files to kebab-case per the filenaming convention Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…memory Bring back the interaction model the DialKit swap dropped: - ⌃⌥T toggles the panel globally (the fork's only global hotkey); the root open state is lifted into DialRoot so the hotkey, the bubble, and the header all drive one switch, threaded to Folder/Panel as a controlled `open` prop. - Frame posture returns as the default: the panel docks as a full-height right-edge strip while the page's own <body> insets into a rounded, ringed card (`contain: layout` keeps every portal inside it, <html> carries the scrim). The chrome rides the top layer via popover="manual" so the contained body can't trap it. Below 1024px float is forced; reduced motion zeroes the transitions. - Posture and the bubble's dragged position persist to localStorage (dev-tweaks.ui.v2); a Dock/Float toggle sits in the panel toolbar. - The launcher bubble becomes a dirty indicator behind the new `launcher="dirty"` DialRoot option: hidden while closed and clean, visible once any value deviates from its default. Local dev uses it; demo builds (NEXT_PUBLIC_DEV_TWEAKS=1) keep the bubble pinned as the visible entry point — deliberately reinstating the pre-#277 split now that the launcher is a small bubble instead of the old text capsule. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DialRoot renders null until the first useDialKit call site registers, so the showPopover() layout effect used to fire while the popover element did not exist yet and never re-ran — leaving the whole chrome hidden by the UA's [popover] display:none. Gate the effect on "has surfaces" so it re-runs when the root actually mounts. Verified in the running app: ⌃⌥T docks the page (contain: layout keeps portals inside the card, margin-right 32×2+280), the toolbar Dock/Float toggle switches posture, posture persists across reloads, and the launcher bubble appears only while a value deviates from its default. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Keep the fork as implementation (ORIGIN.md + MIT LICENSE) but make @workspace/dev-tweaks speak only "dev tweaks": useDevTweaks, DevTweaksRoot, DevTweaksConfig; move src/dialkit to src/panel; rename CSS, DOM classes, and sessionStorage keys to dev-tweaks-*. Thin the package entry to the hook, the root, config types, and cssVarOverrides. Drop productionEnabled — the app's compile-time gate already decides whether the root mounts.
…r root Both menus portalled to document.body with position: fixed, so in frame posture the contained body clipped them away entirely, and in popover mode the top-layer panel painted over them regardless of z-index. Port them to the select-control pattern (portal into the dev-tweaks root, absolute positioning via getDropdownPosition), re-enable pointer-events for dropdowns portalled directly into the popover root, and read presets/activePresetId through useSyncExternalStore with a stable empty snapshot so preset changes update reactively. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The title row now hosts a unified header-button group — a new dark/light theme toggle (persisted in UI prefs, default now dark), the posture toggle, and close — replacing the scattered toolbar buttons; the root toolbar keeps only the timeline switch. Frame posture widens to 340px. CONTEXT.md gains the Dev Tweaks glossary (Panel Posture, Panel Mode, Launcher). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A mock is a remote control for a mode whose truth lives outside the panel (a cookie the server also rewrites), not an override value the panel owns. MockStore keeps that boundary: every change writes through the feature's source and is re-loaded from it, external changes arrive via the source's watch with unchanged echoes deduped, and mock state never enters the panel's localStorage persistence. The panel renders registered mocks as badged sections ahead of tweaks, and an enabled mock counts as dirty so the launcher warns that pages show fixture data. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
main's cost-center work taught the old dev-tweaks store a driver with an external-change subscription so the billing mock cookie could drive a tweaks group. This branch had already replaced that store with the DialKit-fork panel, which now models mocks first-class — so the driver plumbing (store.ts, types.ts, registry.test.tsx) is dropped with the old store, and billing-dev-mock.tsx becomes a DevTweaksMockSource over the same cookie: load/set parse and write the unchanged cookie protocol, set still drops the SWR cache, and watch keeps the cookieStore/focus/interval fallbacks. The server fixture dispatcher and every /billing surface merge in untouched. Co-Authored-By: Claude Fable 5 <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.
Rebuilds
@workspace/dev-tweakson a fork of DialKit v1.4.3 (MIT), then re-establishes the interaction model and product vocabulary the swap dropped. The old hand-rolled store, panel, and styles are gone; what replaces them is owned code held to this repo's toolchain.What changed
The panel is a fork, not a vendor drop.
src/panelis first-class source — no@ts-nocheck, no Biome or ESLint carve-outs. Strict-mode type errors (noUncheckedIndexedAccess, React 19 ref types) and every lint finding were fixed for real; only cognitive-complexity and the render-phase ref-mirror pattern are suppressed inline with reasons, keeping the ported logic structurally intact.ORIGIN.mdrecords the fork point and the MITLICENSEstays; there is no upstream re-sync procedure.DialRoot's enabled gate moved into a wrapper so hooks no longer sit behind an early return — that was a real rules-of-hooks hazard.The package speaks only "dev tweaks."
useDevTweaks,DevTweaksRoot,DevTweaksConfig; CSS, DOM classes, and sessionStorage keys are alldev-tweaks-*. The entry is thinned to the hook, the root, config types, andcssVarOverrides.productionEnabledis dropped — the app's compile-time gate already decides whether the root mounts.Frame docking is back, as the default posture. The panel docks as a full-height right-edge strip while the page's
<body>insets into a rounded, ringed card (contain: layoutkeeps portals inside it). The chrome rides the top layer viapopover="manual"so the contained body can't trap it. ⌃⌥T toggles globally; posture and the bubble's dragged position persist to localStorage. Below 1024px float is forced, and reduced motion zeroes the transitions.The launcher bubble is a dirty indicator. Hidden while closed and clean, visible once any value deviates from its default. Demo builds (
NEXT_PUBLIC_DEV_TWEAKS=1) keep it pinned as the visible entry point — deliberately reinstating the pre-#277 split now that the launcher is a small bubble rather than the old text capsule.Dev mocks are a first-class panel concept. A mock is a remote control for a mode whose truth lives outside the panel (a cookie the server also rewrites), not an override value the panel owns.
MockStorekeeps that boundary: changes write through the feature's source and re-load from it, external changes arrive via the source'swatchwith unchanged echoes deduped, and mock state never enters the panel's localStorage persistence. Mocks render as badged sections ahead of tweaks, and an enabled mock counts as dirty so the launcher warns that pages show fixture data.Header actions and dropdown portalling. The title row hosts a unified button group — a new dark/light theme toggle (persisted, default dark), the posture toggle, and close — leaving only the timeline switch on the root toolbar. The version and shortcuts menus previously portalled to
document.bodywithposition: fixed, so frame posture clipped them away and the top-layer panel painted over them in popover mode; both now follow the select-control pattern, portalling into the dev-tweaks root.Merge note
main's cost-center work taught the old store a driver with an external-change subscription so the billing mock cookie could drive a tweaks group. That store no longer exists, so the driver plumbing is dropped with it andbilling-dev-mock.tsxbecomes aDevTweaksMockSourceover the same cookie — the cookie protocol is unchanged,setstill drops the SWR cache, andwatchkeeps the cookieStore/focus/interval fallbacks. The server fixture dispatcher and every/billingsurface merge in untouched.Verification
bun typecheckandbun checkpass. Verified in the running app: ⌃⌥T docks the page, the Dock/Float toggle switches posture, posture survives reloads, and the bubble appears only while a value deviates from its default.CONTEXT.mdgains the Dev Tweaks glossary (Panel Posture, Panel Mode, Launcher).🤖 Generated with Claude Code