Uh oh!
There was an error while loading. Please reload this page.
feat(ui): canonical Input/Textarea onto Base UI, retire native ui.tsx Input (#520 item 22) - #555
Merged
Merged
Conversation
… Input (#22 PR10) #22 PR10: collapse the dual Input tracks onto one canonical primitives/input.tsx + primitives/textarea.tsx, retiring the native ui.tsx Input/Textarea. - primitives/input.tsx now wraps Base UI's Input primitive with maka's inputClasses styling ported as the default chrome. Stays a single <input> (no span wrapper) so caller CSS targeting `> input` / `input:focus-visible` still matches. unstyled gives the bare form (bareFieldClasses + data-maka-field-chrome="none") for Field/InputGroup embedding. - primitives/textarea.tsx parallel shape: single <textarea> + inputClasses + textarea sizing. Base UI ships no Textarea, so this is a native textarea. Drops the Base UI Field.Control + span wrapper (caller doesn't use Field). - ui.tsx Input, Textarea, inputClasses, bareFieldClasses retired. inputClasses + bareFieldClasses moved into primitives/input.tsx (exported) so number-field keeps its standalone NumberFieldInput chrome. - InputGroup: InputGroupInput/InputGroupTextarea already pass unstyled (inner field bare, InputGroup owns the chrome — no double chrome). InputGroup CSS updated to key off data-slot="input"/"textarea" (the single element) instead of the retired span data-slot="input-control"/"textarea-control"; dropped the span-only `:contents` / `:before:hidden` rules. - index.ts re-exports primitives/input + primitives/textarea as the canonical Input/Textarea; the 44 usages across 9 settings files keep importing from @maka/ui unchanged. - Contracts: new input-canonical-contract (single element, inputClasses token lock, ui.tsx retired, bare-field shape); field-chrome.test rewritten for the unified shape (drops nativeInput/h-8.5/field-sizing-content assertions that pinned the old primitives/input vs ui.tsx divergence); radius-converge inputClasses tier repointed at primitives/input.tsx. Verification: typecheck clean; @maka/ui test 43/43; @maka/desktop test 2069/2069. Screenshot pixel diff vs main: settings-general and settings-bots light/dark 1280 AE=0 (pixel-identical, both contain Input). settings-data 364 px (edge); settings-appearance/daily-review ~9-10K px in a 12px right-edge column (window edge, not input/textarea); settings-memory ~18K px in a large content block (main-branch composer/sidebar commits #510/#511, not this PR).
…contract
- P2-1: InputGroupInput/Textarea spread props before unstyled and
data-maka-field-chrome so a caller's unstyled={false} cannot re-enable
the inner chrome (would double the border / focus ring). The InputGroup
owns the chrome; the inner control stays bare.
- P2-2: port type="search" WebKit cancel/decoration/results reset into
primitives/input. Main's primitives/input always applied this for
InputGroupInput (search-modal path); the unified Input keeps the
contract for both the @maka/ui Input and InputGroupInput paths.
size/nativeInput/type=file variants audited — no callers in repo
(@maka/ui Input was ui.tsx without these; InputGroupInput never
passed them); removed without a compat layer.
- P3-1: rewrite input-canonical-contract as behavior tests only — no
source regex. Styled/unstyled single element + chrome, InputGroup
force-bare even with unstyled={false}, type="search" webkit reset,
barrel import smoke.
- P3-2: #22 PR10 -> #520 item 22 in comments (the PR流水号 narrative
pointed at the wrong tracker).The canonical Input/Textarea already force data-maka-field-chrome="none"
when unstyled (the {...props} spread precedes the attribute in both
primitives, so a caller cannot override it). The adapter passing it
explicitly was a no-op. Drop the redundant attribute; keep unstyled.
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 freeto 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
#22 PR10: collapse the dual Input tracks onto one canonical
primitives/input.tsx+primitives/textarea.tsx, retiring the nativeui.tsxInput/Textarea.Why
Refs #22 / #520. The renderer had two parallel Input implementations: the native
ui.tsxInput(single<input>+inputClasses,focus-visible:ring-2, used by 44 call sites across 9 settings files) and the Base UIprimitives/input.tsxInput(spandata-slot="input-control"wrapper + inner Base UI Input +ring-[3px], used by InputGroup).bare-field-chrome-contractpinned the native'sdata-maka-field-chrome+border-input+ring-2, so retiring the native was not a clean look-preserving swap — it neededinputClassesported into the Base UI primitive, InputGroup updated to avoid double chrome, and the chrome contract rewritten.Scope
Changed:
primitives/input.tsxnow wraps Base UI'sInputprimitive with maka'sinputClassesstyling ported as the default chrome. Stays a single<input>(no span wrapper) so caller CSS targeting> input/input:focus-visiblestill matches.unstyledgives the bare form (bareFieldClasses+data-maka-field-chrome="none") for Field/InputGroup embedding.primitives/textarea.tsxparallel shape: single<textarea>+inputClasses+ textarea sizing. Base UI ships no Textarea, so this is a native textarea. Drops the Base UIField.Control+ span wrapper (callers don't use Field).ui.tsxInput,Textarea,inputClasses,bareFieldClassesretired.inputClasses+bareFieldClassesmoved intoprimitives/input.tsx(exported) sonumber-fieldkeeps its standaloneNumberFieldInputchrome.InputGroup:InputGroupInput/InputGroupTextareaalready passunstyled(inner field bare, InputGroup owns the chrome — no double chrome). InputGroup CSS updated to key offdata-slot="input"/"textarea"(the single element) instead of the retired spandata-slot="input-control"/"textarea-control"; dropped the span-only:contents/:before:hiddenrules.index.tsre-exportsprimitives/input+primitives/textareaas the canonicalInput/Textarea; the 44 settings usages keep importing from@maka/uiunchanged.packages/uiimports (composer,plan-reminder-panel,skills-panel) + stories repointed at the primitives.input-canonical-contract(single element,inputClassestoken lock,ui.tsxretired, bare-field shape);field-chrome.testrewritten for the unified shape (dropsnativeInput/h-8.5/field-sizing-contentassertions that pinned the old primitives/input vs ui.tsx divergence);radius-convergeinputClassestier repointed atprimitives/input.tsx.Not included:
Verification
npm run typecheck— clean.npm run -w @maka/ui test— 43/43 pass.npm run -w @maka/desktop test— 2069/2069 pass.npm run -w @maka/ui build+npm run -w @maka/desktop build:main— clean.compare):settings-generalandsettings-botslight/dark 1280 AE=0 (pixel-identical, both containInput).settings-data364 px (edge);settings-appearance/settings-daily-review~9-10K px in a 12px right-edge column (window edge, not input/textarea);settings-memory~18K px in a large content block (main-branch composer/sidebar commits feat(sidebar): add project-grouped session view mode #510/feat(composer): workspace picker, git branch switching, and composer defaults persistence #511, not this PR).User-facing impact
None intended. Input/Textarea visuals are preserved by porting
inputClasses(min-h-9, border-input, bg-foreground oklch 0.02, px-3 py-2, shadow-sm, focus-visible:ring-2 ring-offset-2) into the Base UI primitive. The DOM changes from a single<input>(ui.tsx) to a single Base UI<input>— still a single<input>, so caller CSS targeting> inputkeeps matching.Reviewer notes
<input>decision is load-bearing: maka CSS has.settingsRow > input/.settingsField input:focus-visible/.providerEditor input:focusselectors. A span wrapper (the old primitives/input shape) would break the> inputdirect-child selectors. So the Base UI Input primitive is used directly withinputClasseson it, no span.inputClasses+bareFieldClassesare exported fromprimitives/input.tsx(not a shared util) because they are the canonical field chrome andnumber-fieldis the second consumer ofinputClassesfor its standaloneNumberFieldInput.Textareadrops the Base UIField.Controlwrapper because no caller uses Base UIFieldwith it; it's a plain native<textarea>withinputClasses. Base UI ships no Textarea component.Checklist