feat(studio): inspector fields, toggles and sections on the shared primitives - #3774
Draft
miguel-heygen wants to merge 1 commit into
Draft
Conversation
The inspector's value control is a box now, not bare text with an underline drawn around it. CommitField wears the same fieldBase every other Studio field wears, so the metric input measures 28px high with a 6px radius and a real border where it measured 17px, no radius and no background. The label moves outside that box, which is the whole of R10: a boundary that differs from the label. SliderControl, SegmentedControl and SelectField become the shared Slider, Tabs and Select. The segmented strip gains arrow keys, Home and End from Tabs; the aria-pressed buttons it replaces answered no key but Tab. The native select is gone, so no OS popup is left in the classic panel. Each one still fires one telemetry event per commit boundary, now proven through a real section rather than the primitive alone. FlatToggle becomes the shared Toggle, and that migration found a defect in the primitive: Base UI renders the switch as a span, so Toggle's disabled:opacity-40 compiled to a rule that could never match and a disabled switch drew at full opacity with a pointer cursor. It is data-[disabled] now, with a test at the primitive that fails without it. The Layout section stops printing its own "3D Transform" label above a component that already renders a collapsible header with the same words, so the heading appears once (R9). Section and the 3D header expand on the duration-expand token, which zeroes itself under prefers-reduced-motion. Colour literals: 470 to 468.
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.
Lands the first inspector sweep PR (U10a: primitives, layout, text, sections, the 3D Transform heading) of the Studio design-system foundation. Stacked on the Renders sweep (#3772). Ratchet 470 to 468. Bundle +7.0 KB gzipped. Stops at a seam: the flat slider and select row keep their hand-rolled implementations and move in the next PR.
What
Lands U10a, the first of the inspector sweep PRs: the inspector's shared value
controls move onto the design system's primitives, and the doubled "3D Transform"
heading is gone.
CommitFieldis a boxed field. It wears the samefieldBaseasInput,NumberFieldandSelect, so the inspector's metric input and every otherStudio field are one control with one look.
MetricFieldandDetailFieldput their label outside that box.SliderControlbecomes the sharedSlider,SegmentedControlthe sharedTabs,SelectFieldthe sharedSelect,FlatTogglethe sharedToggle.FlatRowdrops the underline it drew around the value; the field's own box isthe boundary now, and the value tier tints it.
already renders one.
Sectionand the 3D Transform header expand on theduration-expandtoken.Also fixes a defect in the shared
Togglethat this migration surfaced: Base UIrenders the switch as a
<span role="switch">, sodisabled:opacity-40compiledto a real rule that could never match and a disabled switch drew at full opacity
with a pointer cursor. It is
data-[disabled]:now, with a test beside theprimitive that fails without the fix.
Why
Two requirements from the design-system contract.
R10 asks that inspector inputs read as inputs, with a boundary that differs from
their label. They did not: a value was bare text on the panel background, and the
metric input measured 17px high with no radius and no background. You could not
tell a value from its own label until you clicked one.
R9 asks that "3D Transform" render once for a selected element. It rendered twice:
the Layout section printed a static label directly above a component whose own
header carries the same words and is the one that collapses.
R8 and KTD7 want one implementation per control. The hand-rolled range input,
segmented strip and native
<select>were three more. The segmented strip inparticular carried
aria-pressedbuttons with no keyboard handling, so the onlyway through it was Tab, one segment at a time; on
Tabsit answers arrow keys,Home and End.
How
The public prop signatures of the migrated primitives do not change, so their
twenty-odd consumers across the inspector pick up the new look and the new
keyboard behaviour without a line of their own changing. That is what keeps this
PR small while the visible change is panel-wide.
Telemetry keeps its contract: one event per commit boundary, never per
intermediate value. Each migrated control passes the tracker the section already
holds as
onTrack, and the assertions run through a real section rather than theprimitive alone, because the section is what holds the tracker.
data-flat-row-valueis deleted rather than moved. The boxed field alreadycarries
data-testid="inspector-field", so a second hook on the same element wasone more thing to keep in step.
Test plan
Studio suite, from
packages/studio, with a capped worker pool:bunx vitest run --poolOptions.forks.maxForks=4— 440 files, 4845 tests, green.Baseline on the branch point was 440 files / 4841 tests, so the delta is the
four tests added here and no test removed or weakened.
bun run typecheck— clean.bun run --filter @hyperframes/studio build— succeeds.bunx oxlintandbunx oxfmt --checkon the changed files — clean.bunx fallow audit --fail-on-issues— exit 0 against both the base branch andthe trunk; no finding in a file this PR touches.
PASS: studio loaded with schema-valid API fixtures and no runtime errors.New tests, each proven to fail against the unfixed code:
label put back.
Sectionexpands onduration-expand. Fails with a hard-coded duration.Selecttrigger classifies the way the native<select>did onboth hotkey selector lists, asserted true-and-equal so two falses cannot agree
and prove nothing.
Togglewears its disabled look on the attribute Base UI sets.Screenshots and computed styles, before and after, from the sweep's capture
script. The row this unit is judged on:
rgb(22, 22, 24)28px and 6px are what both Export buttons already measure, so the inspector field
now sits inside the same three-height, three-radius set the sweep is aiming at.
Every other row in the table is identical before and after.
Bundle, gzipped across the app's chunks: 1,571,013 bytes before, 1,578,200 after.
A delta of 7,187 bytes (about 7.0 KB) for the first inspector consumers of
SliderandToggle, against the 100 KB budget for the set. Reported, nottrimmed.
Not covered
FlatSliderandFlatSelectRowkeep their hand-rolled implementations.Both are large pointer-capture and native-select state machines with about
thirty tests each pinned to their exact DOM, and converting them would have
taken this PR well past a reviewable size. They are the next sweep PR's, and
the flat inspector therefore still shows one underlined row (Weight) beside the
boxed ones until then.
grading, canvas menu, media, motion and overlays keep their own colours and
controls. Those are the later inspector PRs.
rgb(0, 0, 0)CSS fallback for a computed style, which is a browser defaultrather than a design value. The other three are shadow presets that have no
matching token yet; adding tokens belongs to the unit that owns the token file.
motion-path toggle appears in some captures and not others, on the base branch
as well as this one (present in one of two base runs, absent in two runs here).
Its visibility is gated on an async runtime probe of the preview iframe, so it
races the screenshot. Anyone diffing the inspector screenshots should expect it
and not read it as a regression.
measured against the trunk will report the whole stack instead.