Repository navigation
Arena 11.1.0: locale, Angular forms, confirmations, the icon rail and the Tailwind theme sheet - #40
Merged
Merged
Conversation
…tes their defaults into both layers ArenaLocale declares every word a component draws of its own and the locale dates are formatted in, each field carrying the word drawn today. generate:api-types emits ARENA_DEFAULT_LOCALE from those defaults into LocaleDefaults.generated.ts in each layer, and check:api diffs it through buildApiModules like the type modules. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
… same way in both layers Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…it reads any other provider Angular provides ARENA_LOCALE through provideArenaLocale; React through ArenaLocaleProvider and useArenaLocale. Both merge a partial over ARENA_DEFAULT_LOCALE with the same arenaMergeLocale, which check:shared-arithmetic holds identical. Both npm pages say what the locale answers and in which order a word resolves, and consumer-install's budget moves to what the Angular page now measures. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
… English it still draws Red on purpose: every case names the words its component still draws in English, which is the checklist the rest of this phase works through, and the Angular test surface does not compile until the calendar's formatters take the locale, which the next commit does. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…own words from it arenaFormatDate and arenaRangeTitle take the locale in both layers, and dateFormatter keys its cache by locale and options. Today, the nav arrows' names, the region and grid names and the event's Actions button read the locale; hour labels keep h23 and weekStartsOn stays a member. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…locale Toast, sheet, alert, tag, skeleton, switch, avatar and pagination read their close, dismiss, remove, loading, confirmation, presence and page-arrow words from the provided locale. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…nswer when they are absent
ArenaSpinner.label, ArenaErrorState.title, ArenaConfirmDialog.eyebrow, confirmLabel and
cancelLabel, ArenaBulkActionBar.noun and ArenaCommandPalette.placeholder carry no contract
default; each layer resolves the member, then the locale. The table's empty fallback, the
confirmation's required-text prompt and the bulk bar's count, clear and toolbar words read the
locale too, the count through the {count} and {noun} template.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…e, and the palette's dialog is named Command palette The palette's dialog name read ArenaCommand palette, a rename that reached a string; its locale default is Command palette. The sentinel suite types into the palette through the native value setter, so React's change tracking sees it, and treats the select's caret glyph as neutral. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…om the locale; its numbers stay the chart's own arenaPointTable takes its first heading as a parameter in both layers, and each chart passes the locale's word for its table and its accessible name; the doughnut's legend name follows its shape. Number formatting stays valueFormat's. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
The point-table suite passes the heading arenaPointTable now takes, and every sentinel case is green in both layers. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
copy-is-english becomes copy-is-direct. Its body is shortened to pay for the sentence saying Arena's own words follow the locale, because the router carrying it is budgeted. The design contract's Language line separates Arena's documentation and defaults, which are English, from a product's copy, which is in the product's language. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…draws Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
… to the npm page The sentence every Words paragraph repeated, and the chart family's note on numbers, are the npm page's to state once; check:duplication held the copies to that. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
@angular/forms joins the Angular envelope and the optional peers, pinned as a devDependency. check:architecture holds both optional peers to their own entry point and walks the package root's import closure, failing any file in it that imports either; the stack page's peer table gains the row, and consumer-stack's budget moves to what the page now measures. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…ot importing forms ArenaControlBinding holds the bound flag, the value and the disabled state a form writes, and the callback a control reports through. It imports nothing from @angular/forms, and INTERNAL records it and the double-binding warning as a seam no consumer leans on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…ng when a form binds it Input, textarea, select, checkbox, radio group and switch provide ArenaControlBinding. While it is bound a control draws the form's value over its own member, draws disabled when either says so, and reports every change it emits through the binding as well; a switch with confirm reports nothing on requestChange. Binding the control's own value member as well warns once. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…iven forms frameworks/angular/forms/ holds one ControlValueAccessor per data-entry control, selected by formControl, formControlName or ngModel on the control's own element, and ARENA_FORM_CONTROLS for one imports line. Each writes and reads through the control's ArenaControlBinding and marks the control touched when focus leaves it; a number input reports a number, or null when emptied. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…imary by name SECONDARY_ENTRY_POINTS gains forms. Staging rewrites a secondary entry point's relative imports of the primary to the package's own name, so ng-packagr compiles one ArenaControlBinding and the forms module imports it; check:packages fails a secondary entry point with no exports key. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…na binds to Angular forms and where a project's own air comes from The Angular npm page gains a reactive-forms section, and each data-entry control's prompt says which directive binds it and what it carries. The adoption tree gains a node asking what the code around Arena brings: markup styled with CSS of its own takes the tokens and css/rhythm.css, and an Angular project binding forms takes the forms entry point, whose peer joins the dependency table. The tree's budget and consumer-install's move to what those pages now measure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…hecks Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
Each page gains a row beside the toast queue and a short section with the block that renders the one open request; each ArenaConfirmDialog prompt points a caller asking from code at the queue. consumer-install's budget moves to what the Angular page now measures. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…the restatement Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…evice's safe area fillBelow takes an ArenaBreakpoint. Each layer measures the dialog's own scrim and, below the named breakpoint, draws the manifest's fill variant: the panel takes the whole screen with no radius and no shadow, the head and foot stick and pay their edge's inset, the body scrolls, and width is ignored. React measures in an inner frame mounted only while open; Angular reads the breakpoint only when fillBelow is set. SCALE_USES records the panel's shadow-none. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…pares nodes the layer's way Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…ps repeating the word When a tooltip opens it reads its trigger's accessible name; if that name already contains the label, the bubble wraps its text in an aria-hidden span. The trigger still references the tooltip with aria-describedby, as the tooltip pattern requires, and the description it contributes is empty, which is what Chromium's accessibility tree exposes for that shape. The test is one pure function per layer, held identical by check:shared-arithmetic. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…name its rows had ArenaSideNav.collapsed narrows the list to a rail whose width is the control height plus the row's padding on each side, a derivation the manifest writes so density moves it, animated over the state duration and not at all under reduced motion. An item draws its icon alone with its label as its visually hidden name and as a composed ArenaTooltip, a badge becomes a hidden dot whose count joins the name, a section keeps its label as the group's hidden name under a separator, and a collapsible's items render at the rail level with the label as their group name and no trigger. An item with no icon is refused while collapsed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
… name Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
… compare nodes the layer's way Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
… function decides how many it draws calendar-detail-line-h is the time label's line box, 16px in both layers measured in Chromium, declared beside the calendar's other script tokens and excluded from the Tailwind scale with its reason. arenaVisibleDetails draws none while the time label is shed and one more per line of height above calendarTimeMinH, the same body in both layers. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…d always announces ArenaCalendarEvent.details draws one truncated line per entry under the time label, as many as arenaVisibleDetails allows. An activatable chip's name is the title, the date, the time and every detail; an inert chip keeps the lines it sheds in its text, visually hidden. The manifest's detail slot sits on the time label's step, recorded in SCALE_USES, and the witness plugin paints both new parts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
… can say names them The review event runs two hours and carries two details, so both layers' kitchen-sink pages draw a chip with details. MemberForms' R1 paragraph stops listing the event's members as a closed set, and the calendar and event prompts say what details are for and how they shed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…ut in the layer does Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…sumer's own compile Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…ailwind compiles css/tailwind-theme.css is written beside the other sheets and outside arena.css's import chain, and each assembler declares the theme's sources among what it reads. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…piles it the way a consumer would No packaged sheet but css/tailwind-theme.css carries a compile-time directive, and that one is named in COMPILED_BY_CONSUMER with its reason. Each packaged copy equals a fresh assembly, and a consumer sheet compiled with Tailwind v4 against it resolves bg-base-100 and p-4 to Arena's tokens, keeps a key declared below the import, reaches no default palette, and emits the self-reference inside @layer theme, which holds because arena.css's token sheets load unlayered, which the gate asserts too. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…wind theme sheet and its utilities Each npm page's css table gains the row, naming the utilities the sheet exports beside the theme. The page reference says markup written with Tailwind reads the same tokens and spends the rhythm steps as gap utilities, and node 10 of the adoption tree gains the Tailwind row. consumer-page, consumer-install and consumer-coldstart move to what their stops now measure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…ay that layer names no other layer Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
…nd can be collapsed to a rail Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8
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.
Arena 11.1.0. A minor: new component surface in both layers, nothing removed.
What lands
generate:api-typeswrites into both layers; a consumer provides the locale once, sentences with a value are one template filled the same way in both layers, and the calendar formats every date in the provided locale. A suite renders every component under a sentinel locale and lists any English it still draws.ArenaBreakpointrestates thebpgroup andcheck:script-tokensholds it.check:packagescompiles it the way a consumer would.Verified
bun run check --releaseafterbun run build:release: 87 of 87 steps ran and passed, none from the cache.bun scripts/check/arena/check-release.tsafter tagging: Release OK, andv11.1.0is the tip ofdevelop.Arena developgreen for the tagged commit on ubuntu, macOS and Windows.🤖 Generated with Claude Code
https://claude.ai/code/session_01SKvjMtCxY2Hd4dFtJtQ6x8