feat: author the auth kit and password field as Layouts - #229
Closed
pathscale wants to merge 11 commits into
Closed
Conversation
added 11 commits
August 14, 2026 00:20
AuthFieldGroup was exported from the package but absent from the Layout manifest, so the application compiler rejected every consumer that imported it. Presentation moves from inline Tailwind into the recipe, and the gap axis becomes a declared presentation prop rather than a local class record.
The gap and full-width sizing move out of inline utilities and into the recipe, so a consumer no longer restates the form's spacing to match it.
Delegates to Alert with status=danger as before. The type scale is the recipe's now rather than a call-site class.
Mirrors AuthErrorMessage: Alert with status=success, role=status and aria-live=polite so a screen reader announces it without stealing focus.
Drops the variant translation helper: the four variants it accepted were already named exactly as Button names them, so it forwards instead of mapping.
The align and variant axes become declared presentation parameters instead of two local class records, so the combination is resolved from one compiled table.
Per-item disabled state moves to a data-disabled attribute styled by the recipe rather than a class ternary at each branch. The selectors match =true explicitly: a recipe reports both directions, so a bare presence selector would also match the enabled case.
The header, headings, title, description and branding regions become named slots, so a consumer can target them without reaching for the Tailwind classes that used to be inlined here. bodyClass still merges over the body slot.
Met and unmet appearance moves onto data-passed and into the recipe, so the two states are described in one place instead of a class ternary per row.
The visibility helpers move to PasswordField.interactions.ts, following the split Slider already uses, and the tests import them from there. Deferring the post-toggle restore also moves into that module. A .layout.tsx template resolves free identifiers against props, so a bare queueMicrotask in the template compiles to props.queueMicrotask, which typechecks as unknown and fails.
The inventory still called these thin Tailwind-utility wrappers, which stopped being true when they gained recipes. Names the presentation parameters and AuthCard's slots so a consumer can find them without reading the source.
Contributor
|
🚀 Preview deployment is ready! You can view the preview at: https://pr-ui-preview-229.surge.sh |
Merged
Owner
Author
|
Superseded by #230, which contains every commit from this branch. Closing so there is one branch and one PR for 2.2. |
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.
What
The auth kit and password field were exported from
@pathscale/uibut were never authored as Layouts. They are the only components in the library without a recipe, and they are absent fromdist/layouts.manifest.json.That combination is worse than it sounds: because they are exported, an application imports them normally and typechecks fine, then the application compiler hard-fails the build.
Ten components are ported: AuthCard, AuthErrorMessage, AuthFieldGroup, AuthFooterLinks, AuthForm, AuthPoweredBy, AuthSubmitButton, AuthSuccessMessage, PasswordField, PasswordRequirements. (
password-rulesis a function barrel with no component and needs nothing.)Public API
Unchanged. Every prop keeps its name, type and default, so no consumer edit is required. What changed is where presentation lives:
ALIGN_CLASS/GAP_CLASSrecords become recipe axes (gap,align,variant) resolved from one compiled table..cssfile, matching every other component here.AuthFooterLinksdisabled,PasswordRequirementspassed) moves ontodata-*attributes styled by the recipe instead of a class ternary at each branch.AuthCardgains named slots:header,headings,title,description,branding,body,footer.AuthSubmitButtondrops its variant translation helper. The four variants it accepted were already named exactly asButtonnames them, so it forwards rather than mapping.PasswordField's pure helpers move toPasswordField.interactions.ts, following the splitSlideralready uses. They remain exported from the component's barrel, and the existing tests import them from the new path.Two things worth knowing for the next port
A
.layout.tsxtemplate resolves free identifiers against props. A barequeueMicrotask(...)in a template compiles toprops.queueMicrotask(...), which then fails typecheck asunknown.documentis on the known-globals list;queueMicrotaskis not. The deferred restore moved into the interactions module for this reason, which is the better split anyway.Adding a component forces a full regeneration, and a full pass reports every diagnostic in the library. The 1,819 pre-existing ones are recorded in
layouts.lint-baseline.json, so only genuinely new diagnostics fail. New components have to satisfy the rules the baseline is suppressing elsewhere: declare arootslot, render every slot declared, and keep the recipe a statically analyzable object literal (noCLASSES.basereferences, which is whatSkeletonandSpinnerare baselined for).Verification
bun run checkgreen: 102 components pass contract checks, 0 new diagnostics.tsc --noEmitclean.rslib buildgreen. Manifest goes from 231 to 241 components, all ten"kind": "embedded".Note
docs/ui-usage.mddescribed the auth kit as "thin Tailwind-utility wrappers". That is updated in the same change, as the working agreement requires.