Repository navigation
@codeatlasdev/ui@2.2.0
Minor Changes
-
d9087e8: Accessible tokens and states, solved per preset and scheme by the generator (every built-in and brand preset, light and dark):
- Disabled controls no longer fade with
opacity. Button (all variants, including the newdestructiveandglassdisabled looks), IconButton, Checkbox, Switch, Slider, Tabs, ToggleGroup, SegmentedControl, Pagination, PinInput, NumberField, RadioGroup, Select, Combobox, TextField, TextArea, date fields and the data-table controls draw the disabled state from--ca-text-disabled,--ca-action-disabled-bgand--ca-outline-default. A loading button keeps its enabled look. --ca-text-disabledis now guaranteed >= 3:1 on every surface and on the disabled fill, and documented (comment,tokens.jsondescription, docs) as the label of disabled controls only.lint:tokensflagscolor: var(--ca-text-disabled)outside a disabled selector.- New
--ca-outline-control(>= 3:1 on every surface and on the 5% field tint, WCAG 1.4.11).--ca-field-border-colordefaults to it, so TextField, TextArea, Select, Combobox, NumberField, PinInput and the date fields, plus the Checkbox and Radio boxes, reach 3:1.--ca-outline-subtlestays for dividers. Overridable like any--ca-*token. - New
--ca-semantic-error-contrast, the pair of--ca-semantic-error-fill.Button variant="destructive"reads it instead of a literal white.defineThemederives it from a customcolors.*.error. - Menus, popovers, pickers and panels are near-opaque by default (
--ca-overlay-bg/--ca-panel-bgare 94% of--ca-surface-overlay, the blur is kept), so label contrast no longer depends on the page behind. The old tints are--ca-overlay-bg-glassand--ca-panel-bg-glass. Thefrostedstyle keeps the opaque default. --ca-focus-ringis solved per preset and scheme (>= 3:1 on every surface and on the hover/selected fills) and every focusable component reads it (it was a literal--ca-brand-mainin about 20 components; the date fields now draw a real 2px ring instead of a 40% tint). New--ca-state-indicator(same guarantee) for the switch track, slider range and segmented thumb edge.lint:tokensrejects a literal--ca-brand-mainin a focus rule.prefers-contrast: moreandforced-colorskeep working: the contrast block also lifts--ca-outline-controland--ca-text-disabled.tokens.jsonentries now carry adescriptiontaken from the comment above the declaration.
Migration: apps that doubled the class to patch these (
.ca-btn.ca-btn:disabled,.ca-tf__wrap.ca-tf__wrap,.glass-overlay.glass-overlay,.ca-btn--destructive.ca-btn--destructive, a global:focus-visibleredraw) can delete those overrides.Bundle budget:
styles/core.css+61 B gzip andstyles/global.css+277 B gzip (limits raised to the measured 9639 / 12594 B). The cost is the three solved tokens (--ca-focus-ring,--ca-outline-control,--ca-semantic-error-contrast) and the twoprefers-contrast: morelifts in 16 preset blocks, which carry the guarantees above. - Disabled controls no longer fade with
-
d9087e8: Component CSS now lives in
@layer ca.components, declared last in the kit's layer order, so the documented contract is true: an unlayered app rule with the same single-class selector (.ca-btn:disabled,.ca-tf__wrap,.ca-tooltip-content,.ca-dialog__body) overrides the kit, with no doubled classes and no!important. Every component<style>block,Dialog/dialog.cssandDate/date.cssare wrapped, and each starts with the full@layerorder statement so bundler chunk order cannot demote the layer. The order incore.csschanged toca.reset, ca.tokens, ca.themes, ca.base, ca.materials, ca.utilities, ca.components. The redundant!importanton the error state of TextField, TextArea, NumberField and Combobox was removed (it would have beaten app CSS now that it sits in a layer). Behavior change: app rules that previously lost to a kit rule of equal or higher specificity now win; apps can delete their.ca-btn.ca-btn/!importantworkarounds. Layered app CSS (for example Tailwind@layer components) must be declared after the kit order statement to outrank it. -
d9087e8: i18n: open locales and request-scoped language (fixes #46).
Localeis nowstring(BCP 47).registerLocale(id, messages)adds any language with a partial dictionary; missing keys fall back to English, and region tags resolve to the base language (es-MX→es).getLocales()andgetMessages(locale, override?)are exported.- New
<I18nProvider locale messages?>: the language lives in Svelte context, so concurrent SSR requests never share it, and it stays reactive to prop changes.useLocale()anduseT()read it from components. setLocaleis now a no-op on the server (with a dev warning), because the module state it wrote was shared across every concurrent request. SSR apps must useI18nProvider; client-only apps keepsetLocale. A provider always wins oversetLocale.createErrorHandlerno longer reads global locale state. It takeslocale(a tag or(event) => tag) for the fallback message.
Migration:
- SSR (SvelteKit) apps: replace
setLocale(x)in the root layout with<I18nProvider locale={x}>…</I18nProvider>. Before, the server-rendered HTML used the locale of whichever request calledsetLocalelast. - Custom language via
setLocale("en", fullOverride): callregisterLocale("es", dictionary)and uselocale="es"/setLocale("es"). Date and number formatting can now follow the real locale. createErrorHandler(): addlocaleif the fallback message must not be English.- Removed export: the internal global
t()is gone (it was never exported from the package root). Library code usesconst t = useT()at component init.
Patch Changes
-
d9087e8: Fix the component descriptions in
components.json, theca-ui-mcpserver and the skill'sAPI.md: the manifest no longer takes the first JSDoc found in a component (usually a prop's, e.g.TextFieldread@deprecated Use description instead). Only a detached component-level doc comment counts, and tag-only comments are skipped.bunx @codeatlasdev/ui initnow supports SvelteKit 3: it reads the installed Kit version, never writes the removed$libimport (uses#lib/theme.tsor a relative path), and reports the changes it does not make for you (svelte.config.jsmoved intosveltekit({ ... }),tsconfig.jsonextending$app/tsconfig). The installation guide and the agent skill gain a SvelteKit 3 section and import the theme invite.config.tswith its.tsextension. -
d9087e8:
Select: an option whosevalueis""(e.g. "All projects") is now a real selection. The trigger shows that option's label instead of the placeholder and drops the placeholder styling, so filters no longer need a sentinel value. The placeholder shows only whenvalueisundefinedor matches no option.onchange("")was already delivered and is now covered by a test. Withrequired, a selected""option counts as a selection.