Skip to content

feat(studio): the Renders panel on the shared primitives - #3772

Draft
miguel-heygen wants to merge 1 commit into
feat/studio-u5-primitives-inputsfrom
feat/studio-u13-renders-sweep
Draft

feat(studio): the Renders panel on the shared primitives#3772
miguel-heygen wants to merge 1 commit into
feat/studio-u5-primitives-inputsfrom
feat/studio-u13-renders-sweep

Conversation

@miguel-heygen

Copy link
Copy Markdown
Collaborator

Lands unit U13 (Renders panel sweep) of the Studio design-system foundation. Stacked on the value-controls PR (#3626). Hex ratchet unchanged: the two touched files hold no colour literals; the raw palette classes removed here are the token gate's domain. Bundle +19.2 KiB gzipped (first consumer of Select), inside the 100 KB budget.

What

Unit U13 of the Studio design-system plan: the Renders panel sweep.

  • The Format, Resolution, Frame rate and Quality controls become the shared Select. No native <select> is left in the Renders tab.
  • The panel's Export drops the type-size override it carried in its own className. Both Exports now measure the same.
  • The per-row Download and Delete controls become IconButton, each wrapped in the shared Tooltip carrying what the title attribute used to say.
  • The panel's colours and type sizes move onto the semantic tokens (text-4, bg-input, border-border, danger, accent, text-step-*).
  • SelectOption gains an optional disabled, passed through to Base UI's Select.Item.

Why

R8 asks for exactly one implementation of every control, and no native <select>: a native popup is the operating system's, so its radius, surface and type belong to someone else and no token can reach them.

AE3 asks that the header Export and the Renders Export share height, radius, fill and type size. They did not. The panel's Export carried its own type size in className, and cn resolves that by dropping the size recipe's own step, so the two Exports sat a type step apart. The captured computed-style table, before and after:

Control Height Radius Font size Background
Header Export (before and after) 28px 6px 12px rgb(60, 230, 172)
Renders Export (before) 28px 6px 11px rgb(60, 230, 172)
Renders Export (after) 28px 6px 12px rgb(60, 230, 172)

The disabled flag on SelectOption is not new behaviour, it is preserved behaviour. The Resolution list disables a preset that is not an exact integer upscale of the authored size, because the producer rejects that scale at render time. Without the flag the shared Select would have offered a choice that fails the render.

How

Option lists become data (FORMAT_OPTIONS, QUALITY_OPTIONS, FPS_OPTIONS, and the Resolution list built per render from the composition's dimensions), which is the shape Select takes. Each onCommit keeps the literal-union cast and the persistence side effect its onChange handler had. Frame rate crosses the string boundary explicitly: String(fps) in, Number(next) out.

The quality option list also carried a title field that nothing ever rendered; it is gone.

Test plan

RenderQueue.test.tsx, all through the component's public render, driven with the pointer and key sequences a browser produces:

  • AE3: the Export's class list equals the shared primary/medium recipe exactly, plus w-full. Set equality, not "contains", so an extra class that displaces a recipe class fails. Proved non-vacuous by re-adding the type-size override: the assertion fails naming the dropped step.
  • R8: querySelector("select") returns null.
  • KTD13: the Format trigger is classified by isTypingTarget and by the playback-shortcut selector exactly as a native <select> is, and both are asserted true rather than merely equal.
  • Changing the Format Select persists "mov", the literal union member, not the "MOV (ProRes)" label. Read back through the real store, not a spy.
  • Choosing 4K still submits the canonical landscape-4k preset.
  • On a 1280x720 composition, the 1080p option is offered with its explanation but cannot be committed: highlighting it and pressing Enter leaves the resolution unchanged. Proved non-vacuous by dropping the disabled pass-through.
  • The FFmpeg gate cases are unchanged and still green.

Also run: the full Studio suite (440 files, 4841 tests, green, including the token gate and the hex ratchet), typecheck, the Studio build, oxlint, oxfmt --check, fallow audit --base origin/main --fail-on-issues (exit 0), and the design-shots capture before and after against this branch's base.

Bundle: the app's gzipped JS and CSS go from 1,573,539 to 1,593,184 bytes, +19,645 bytes (+19.2 KiB). This is the first consumer of Select in the shipped app, so it is where Base UI's select entry point lands. Nothing trimmed.

Not covered

  • The ratchet baseline is unchanged, and correctly so. Both touched files already held zero colour literals, so they are absent from the baseline and there is nothing to lower. The raw colours removed here (red-400, neutral-700, bg-red-500/10) are Tailwind palette classes, which the token gate governs, not the hex ratchet. The ratchet test fails on a fall as well as on a rise, and the suite is green, which is the evidence.
  • The thumbnail stays a plain <button>. It is an 80x45 media surface, not a control on the 24/28/32 grid, and IconButton would force it into a square.
  • FormatInfoTooltip stays a local popover. Its content is a heading plus three descriptions, which the one-line shared Tooltip does not carry; the file already says so.
  • FfmpegRequiredNotice.tsx is not in this unit's file list and is untouched. Its amber card still uses palette classes.
  • The inspector (U10) and the timeline (U11) are separate units.

The four native selects become the shared Select, so no OS popup is left in
the panel and the four controls read as the same control as everything
around them. Disabled options survive the move: SelectOption gains a
disabled flag, which is what keeps a resolution the composition cannot
reach out of the keyboard's path while its label still explains why.

Export drops its own type size. cn resolved that override by dropping the
size recipe's step, which is what left the panel Export a type step below
the header's; the computed-style table now reads 28px / 6px / 12px for
both. Its two per-row siblings become IconButton with a Tooltip carrying
what the title attribute used to say.

The panel's colours move to the semantic tokens.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant