# @codeatlasdev/ui 4.0.0: @codeatlasdev/ui 4.0.0 Page: https://ui.codeatlas.com.br/changelog/4.0.0/. Index: https://ui.codeatlas.com.br/llms/changelog.txt. 21 changesets. 21 changes. This release has no written post; the list below is generated from the changelog. ## In short 1. AppShellLayout renders its content region as
` by default, so a page built on it has a `
` landmark (axe `landmark-one-main`, `region`) and the skip link lands on it. 2. nativeFeel() now has one opt-out class, .ca-selectable, for bot.... `nativeFeel()` now has one opt-out class, `.ca-selectable`, for both the context menu and text selection (#136). 3. caBrandPlugin writes src/generated/brand.ts as soon as the Vite.... `caBrandPlugin` writes `src/generated/brand.ts` as soon as the Vite config resolves (the URLs depend only on a hash of the inputs, so no rendering is needed), not only at build start. ## Upgrade ```bash bun add @codeatlasdev/ui@4.0.0 ``` Across majors: `bunx @codeatlasdev/ui migrate --from --to `, or the MCP tool `get_migration`. ## Changesets ### Major Changes - b99075a: `AppShellLayout` renders its content region as `
` by default, so a page built on it has a `
` landmark (axe `landmark-one-main`, `region`) and the skip link lands on it. It was a plain `div`. Pass `mainId={null}` when your page renders its own `
`: the region is then a plain `div`, never a second landmark. If you wrapped your content in `
` inside the shell, remove it or pass `mainId={null}`. - fdb6798: `nativeFeel()` now has one opt-out class, `.ca-selectable`, for both the context menu and text selection (#136). The context-menu filter used `.selectable` while the selection CSS used `.ca-selectable`, so neither class restored both. The filter and its docs now say `.ca-selectable`, matching the `ca-*` class contract. Clean cutover: `.selectable` was never documented outside a JSDoc line, and no stylesheet ever targeted it, so apps using it must rename it to `ca-selectable` (right-click on a `.selectable` region is now blocked again until they do). ### Minor Changes - 6e39edc: `caBrandPlugin` writes `src/generated/brand.ts` as soon as the Vite config resolves (the URLs depend only on a hash of the inputs, so no rendering is needed), not only at build start. New `codeatlas-ui brand` command and `brandUrls()` / `runBrand()`: render the icons and the module without a Vite run, so a job that only runs `svelte-check` on a fresh clone type-checks (`svelte-kit sync` does not load Vite plugins). - c2d255d: `FormSection` accepts `headingLevel` (`2 | 3 | 4 | 5 | 6`) and `AppSettings`/`AppForm` provide the section heading level like `PageShell`, so `FormSection` and `EmptyState` titles inside them render as `

` under the page `

` (axe `heading-order`) instead of `

`. Outside a page layout the default stays `
`. Only the tag changes, never the look. - af02ce2: `RadioGroup`, `Checkbox`, `Switch` and `Select` accept `name`, so their value is part of `FormData` on a native form submit (progressive enhancement, SvelteKit form actions without a hidden-input workaround). `Select` renders a hidden input carrying the selected value when `name` is set. - e7b85e7: `ogCard` accepts `lang` (BCP 47, default `"en"`, escaped) for the card's ``, so non-English cards get the right hyphenation and locale font selection. - 55ecc1a: `Box`, `Flex`, `Stack` and `Grid` are generic on `as`: `` accepts the form's attributes, and the handler's `currentTarget` is an `HTMLFormElement` (same for `as="a"`, `as="label"`, `as="button"`...). An attribute that does not belong to the tag is a type error. Exports `PolymorphicProps` and `ElementTag`. ### Patch Changes - 153be87: `centsToDisplay` keeps the no-break space `Intl` puts after the currency symbol (`"R$\u00a0123,45"`), so a price no longer wraps between the symbol and the number. `MoneyInput` still shows and parses a plain space in its editable text. - a517102: `toCsv`, `toJson`, `ExportColumn` and `ExportMenu` accept any object row type (`T extends object`), so rows typed with an `interface` no longer need a cast. `key` is still checked against `keyof T`. - 8d25c2f: `caErrorPlugin({ scaffold: true })` writes a valid `src/error.html`: the theme init script now sits in `` instead of inside `