@naeil/ui 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +31 -3
  2. package/DESIGN.md +10 -2
  3. package/README.md +13 -11
  4. package/THIRD_PARTY_NOTICES.md +4 -2
  5. package/dist/{chunk-XLISHUJZ.js → chunk-5BXZPDHZ.js} +68 -8
  6. package/dist/{chunk-DBE7R4MR.js → chunk-A2DCQVTP.js} +1 -1
  7. package/dist/{chunk-KPE4KKYM.js → chunk-Y5LW3ADW.js} +24 -15
  8. package/dist/components/index.d.ts +3 -3
  9. package/dist/components/index.js +4 -4
  10. package/dist/components/naeil-footer.d.ts +2 -2
  11. package/dist/components/naeil-footer.js +1 -1
  12. package/dist/components/naeil-header.d.ts +23 -8
  13. package/dist/components/naeil-header.js +7 -5
  14. package/dist/components/ui/index.d.ts +2 -2
  15. package/dist/components/ui/index.js +6 -6
  16. package/dist/lib/ui-release.d.ts +1 -1
  17. package/dist/lib/ui-release.js +1 -1
  18. package/dist/lib/utils.js +1 -7
  19. package/dist/naeil-locale/checker.js +1 -1
  20. package/dist/naeil-locale/chrome.d.ts +25 -8
  21. package/dist/naeil-locale/chrome.js +91 -22
  22. package/dist/naeil-locale/{chunk-4U64K4J3.js → chunk-24IL53QO.js} +1 -1
  23. package/dist/naeil-locale/{chunk-U65OQHZY.js → chunk-WT6QXR7O.js} +14 -8
  24. package/dist/naeil-locale/client.js +45 -15
  25. package/dist/naeil-locale/index.js +1 -1
  26. package/dist/naeil-locale/messages.js +2 -2
  27. package/dist/naeil-locale/server.js +6 -6
  28. package/dist/{navigation-D8N1tMTu.d.ts → navigation-CXZapKac.d.ts} +3 -1
  29. package/dist/{site-footer-s113FZgC.d.ts → site-footer-C4jgkGDU.d.ts} +1 -1
  30. package/dist/source/components/naeil-header-core.d.ts +23 -8
  31. package/dist/source/components/naeil-header-core.js +66 -6
  32. package/dist/source/components/naeil-header.d.ts +6 -4
  33. package/dist/source/components/naeil-header.js +4 -2
  34. package/dist/source/components/typography.d.ts +1 -1
  35. package/dist/source/components/typography.js +1 -1
  36. package/dist/source/components/ui/button.js +7 -7
  37. package/dist/source/components/ui/card.js +1 -1
  38. package/dist/source/components/ui/dialog.js +2 -2
  39. package/dist/source/components/ui/navigation.d.ts +3 -1
  40. package/dist/source/components/ui/navigation.js +17 -8
  41. package/dist/source/components/ui/sonner.js +2 -2
  42. package/dist/source/lib/ui-release.d.ts +1 -1
  43. package/dist/source/lib/ui-release.js +1 -1
  44. package/docs/components/README.md +3 -1
  45. package/docs/components/application-layout.md +23 -27
  46. package/docs/components/avatar.md +1 -1
  47. package/docs/components/badge.md +3 -1
  48. package/docs/components/button.md +7 -1
  49. package/docs/components/card.md +5 -1
  50. package/docs/components/checkbox.md +1 -1
  51. package/docs/components/common.md +16 -1
  52. package/docs/components/dialog.md +6 -2
  53. package/docs/components/dropdown-menu.md +1 -1
  54. package/docs/components/input.md +1 -1
  55. package/docs/components/naeil-footer.md +1 -1
  56. package/docs/components/naeil-header.md +41 -12
  57. package/docs/components/naeil-locale.md +36 -0
  58. package/docs/components/navigation.md +10 -4
  59. package/docs/components/select.md +1 -1
  60. package/docs/components/sheet.md +1 -1
  61. package/docs/components/sonner.md +7 -1
  62. package/docs/components/switch.md +1 -1
  63. package/docs/components/tabs.md +1 -1
  64. package/docs/components/textarea.md +1 -1
  65. package/docs/design/public-ui-support.md +3 -1
  66. package/docs/design/v2-migration.md +11 -6
  67. package/docs/package-release.md +21 -11
  68. package/package.json +7 -10
  69. package/src/styles/components.css +29 -0
  70. package/src/styles/globals.css +6 -2
  71. package/src/styles/theme.css +5 -0
  72. package/licenses/Nunito-Sans-OFL.txt +0 -93
  73. package/licenses/React-MIT.txt +0 -21
  74. package/licenses/Storybook-MIT.txt +0 -21
  75. package/licenses/popper-MIT.txt +0 -25
  76. package/licenses/store2-MIT.txt +0 -22
  77. package/licenses/toggle-selection-MIT.txt +0 -21
@@ -35,6 +35,8 @@ Use `createNaeilRequestConfig({namespace: "estimate", messages: {en: () => impor
35
35
 
36
36
  Render complete paths with `localePath` for same-service navigation and `localeHref` for owned service links. Pass those paths to base Next Link/router or anchors without another locale option. The controller performs `router.replace(href, {scroll: false})`, serializes requests and waits for the matching provider arrival. It restores a stable `data-naeil-focus-id`, input `name`, or `id`. Only a successful explicit selection may write preference; history, prefetch and direct visits do not. Storage failure cannot block a path change.
37
37
 
38
+ Compatibility note: timeout releases the pending lock but retains the failed intent so a matching late provider arrival clears the error and applies the normal preference-write opt-in. The full destination (including query and fragment) must match. Cancel, history navigation, departure to another logical route, or a newer selection discards that late-arrival eligibility. `retry()` now uses the latest failed request, including unsupported-route failures and destination options; if the URL already has the requested locale, it clears the error and returns `false` without starting another navigation. A URL change alone never writes preference: a matching provider must commit.
39
+
38
40
  The canonical chrome can be imported from `/naeil-locale/chrome` under the shared provider. Existing `/naeil-header` and `/naeil-footer` remain standalone compatibility adapters and include the small three-language common dictionary. Consumer Link, auth, save guards, frame overrides, desktop/mobile account locks and project data remain consumer-owned.
39
41
 
40
42
  ## AB Storm registration (0.11.0 candidate)
@@ -47,6 +49,40 @@ The inventory was checked against AB Storm source `087e67239db26506a73c51fde7a6d
47
49
 
48
50
  The proxy runs exact existing protocol boundaries first, strips external private markers, strictly classifies UI paths, applies the existing app authorizer, and then runs next-intl. Protected entries without an authorizer fail closed. A marker is only a rendering hint: every protected server data read must independently authorize. RSC denial renders a valid localized access boundary and retains the root draft; it must not send login HTML or redirect an in-progress editor to another document. Keep the root beforeunload guard active during RSC failure and access recovery.
49
51
 
52
+ Compatibility note: a protocol hook returning `NextResponse.next({request: {headers}})` or `NextResponse.rewrite(url, {request: {headers}})` now preserves the complete supplied request header set, including deletions and replacements. Internal locale/access markers are still removed. Plain `NextResponse.next()` without request overrides retains the sanitized incoming headers.
53
+
50
54
  `localePath` is not an auth-return validator. Keep existing exact return/invite/callback/relay origin and envelope validation. Protocol paths stay outside `[locale]`; localized protocol aliases are rejected. Public metadata advertises only available translations. Protected/auth/error UI is noindex without SEO alternates.
51
55
 
56
+ Compatibility note: literal backslashes in UI query strings and fragments are preserved by `resolveLocaleUrl` and `localePath`; backslashes in the pathname remain invalid. Encoded locale and protocol-prefix segments are rejected using the registered locale and protocol inventories, including consumer `protocolPrefixes`. This also applies to dynamic UI segments; use the literal spelling of reserved segments.
57
+
58
+ ## Proxy matcher and public files
59
+
60
+ The proxy passes these unlocalized prefixes (exact path or descendants) through without locale rewriting: `/api`, `/auth`, `/_next`, `/_vercel`, `/.well-known`, `/health`, `/invite`, `/return`, `/webhook`, `/images`, `/fonts`, plus the service's `protocolPrefixes`. Exact registered `uiProtocolExceptions`, such as Estimate's `/auth/complete`, remain UI routes. The built-in exact public files are `/favicon.ico`, `/favicon.svg`, `/icon.svg`, `/apple-icon.png`, `/robots.txt` and `/sitemap.xml`. Compatibility note: `/favicon.svg` is now included so Estimate's error-document favicon passes through the same proxy that emitted it.
61
+
62
+ Other public files, including manifests, Open Graph images and extra icons, must be excluded by the consumer's matcher or explicitly passed by its protocol hook or service `protocolPrefixes`. Unknown paths are otherwise rejected with 404, even when they contain a file extension. A protocol hook runs before classification; keep its allowlist exact and preserve existing auth/invite/return checks.
63
+
64
+ The site uses the following catch-all matcher and passes its additional public files in the protocol hook. This is the recommended starting point when existing security checks must run on every request:
65
+
66
+ ```ts
67
+ // proxy.ts — retain existing protocol/security checks before this asset branch.
68
+ import { NextResponse, type NextRequest } from "next/server";
69
+ import { createNaeilLocaleProxy } from "@naeil/ui/naeil-locale/server";
70
+
71
+ async function protocol(request: NextRequest) {
72
+ const path = new URL(request.url).pathname;
73
+ // App-owned examples; replace these with the application's actual public files.
74
+ if (path.startsWith("/svg/") || ["/manifest.webmanifest", "/og.png"].includes(path)) {
75
+ return NextResponse.next();
76
+ }
77
+ return undefined;
78
+ }
79
+
80
+ export default createNaeilLocaleProxy({ service: "main", protocol /*, authorize: existingAuthorizer */ });
81
+ export const config = { matcher: ["/:path*"] };
82
+ ```
83
+
84
+ Keep the existing authorizer when integrating this example. If the matcher excludes assets instead, those requests bypass both the locale proxy and its protocol hook; exclude only paths that need neither. Passing a path through does not create or serve the file: the consumer still owns its static asset or handler.
85
+
86
+ ## Activation
87
+
52
88
  Receiver deployment and sending are separate gates. `preferenceWritesEnabled` defaults to false. Before first exposure, validate a separate receiver-compatible fallback or the previous build's safe rejection of new paths. After all required receiver and auth receipts pass, enable the reviewed cross-service links and explicit preference writes. Keep package, source, hosted Docs, app identities, activation times and rollback receipts separate. Home and Baby are outside this migration.
@@ -1,6 +1,6 @@
1
1
  # Navigation and SiteFooter
2
2
 
3
- This guide targets the **@naeil/ui 0.6.0**; release identities and publication evidence are recorded in the [release record](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.6.0). These are generic product-menu primitives. Applications inheriting the actual naeil.dev brand/catalog/control composition use the canonical opt-in [NaeilHeader](naeil-header.md) from `@naeil/ui/naeil-header`, with fixed positioning, a 65px height, the shared application frame and official artwork URL dependency.
3
+ See [release identities and publication status](../package-release.md#publication-and-deployment) for the current published release. These are generic product-menu primitives. Applications inheriting the actual naeil.dev brand/catalog/control composition use the canonical opt-in [NaeilHeader](naeil-header.md) from `@naeil/ui/naeil-header`, with fixed positioning, a 65px height, the shared application frame and official artwork URL dependency.
4
4
 
5
5
  `Navigation` and `SiteFooter` are React-only exports from `@naeil/ui/ui` (also `@naeil/ui/components/ui/navigation` and `@naeil/ui/components/ui/site-footer`). They require shared theme/components CSS and the normal consumer font/Tailwind setup. They do not import Next, next-intl, authentication, product routes or message dictionaries.
6
6
 
@@ -36,19 +36,25 @@ These are composition snippets: `pathname`, controls, brand and `guardedNavigate
36
36
 
37
37
  `Navigation` accepts links and one level of labeled groups, optional description/icon/badge, `toolbar`, `mobileToolbar` and `mobileFooter`. Brand is a slot; the component does not invent a home destination or label. Groups use Radix Popover with actual links (Tab navigation, Escape and focus return); they are not action menus. Mobile uses a modal Radix Dialog with scroll locking, trapped focus and a labeled close control. The sheet closes on destination selection, currentHref changes or a return to desktop.
38
38
 
39
+ `mobileOpen?: boolean` controls the mobile sheet; omit it for internal state. `onMobileOpenChange?: (open: boolean) => void` observes internal changes or requests controlled changes. External prop updates emit no request; a parent that delays or rejects closure can receive another close request. Modified/middle clicks preserve the sheet. Desktop dismissal depends on the desktop navigation gaining width; an empty menu retains the open sheet until close, overlay, Escape or route change.
40
+
41
+ `omitEmptyNavigation?: boolean` opts into omitting empty navigation landmarks and dismissing toolbar-only sheets on desktop crossing. Its default `false` preserves B1 empty-menu behavior.
42
+
43
+ `NavigationSheetAction` is a public React context exported only from the deep entry `@naeil/ui/components/ui/navigation`. Its value is `undefined` outside a controlled mobile toolbar. Within that toolbar, calling the context function with `action: () => void` returns `{ menuClosed: () => void, cancel: () => void }`. Call `menuClosed()` after the nested menu releases focus to request sheet closure; the action waits for both layers and focus handoff. `cancel()` cancels the queued action. Reopening, another dismissal or unmounting also cancels it. The shared account control already uses this coordination; ordinary navigation links need no context integration. See [the source](https://github.com/naeil-dev/naeil-ui/blob/main/src/components/ui/navigation.tsx).
44
+
39
45
  Desktop groups open on mouse hover without moving keyboard focus. Leaving both the trigger and panel closes the hover preview after the standard 180ms token duration, allowing travel across the portal gap. Entering the panel cancels the pending close. Mouse clicks keep the menu open while the pointer remains in the trigger/panel and do not pin it: leaving still dismisses it. Keyboard-activating a hovered trigger takes over the open menu and focuses its first link; subsequent keyboard activation, Escape, outside interaction or navigation dismisses it. A menu being used with keyboard focus remains open when the pointer leaves. Mouse dismissal preserves the previous focus; keyboard activation retains Radix focus return. Touch uses click/tap, and the mobile sheet behavior is unchanged. Reduced motion disables visual transitions while retaining pointer travel tolerance.
40
46
 
41
47
  Container queries select desktop layout at 48rem of available header content width. Navigation, main and footer share a maximum 1600px outer frame and `clamp(16px, 2.4vw, 40px)` gutters by default. Use `ui-app-frame` on main; do not wrap Navigation or SiteFooter in another padded frame. Reading/settings sections inside main retain their 640px cap. The [application layout guide](application-layout.md) covers composition and consistent root token overrides. Header height uses `ui.navigation-height` (64px); toolbar controls should remain short, with volatile counts in the content area. Navigation itself is in document flow; `className` can make it sticky or fixed. Fixed consumers must reserve its height in page composition. A narrow form must not constrain the header. Explicit className/style remain consumer overrides.
42
48
 
43
- `SiteFooter` supports `brand`, `description`, `groups: [{ id, label, links }]`, `meta`, children, `Link`, `containerClassName`, `variant="full|compact"` and `onNavigate(event, item)` (0.7.0 candidate, including explicit external anchors). Each link group is a labeled navigation landmark. Translated titles, destinations, legal/version text and social links belong to the consumer. A product may place a compact footer in its mobile sheet; a full marketing footer is not mandatory in a dashboard.
49
+ `SiteFooter` supports `brand`, `description`, `groups: [{ id, label, links }]`, `meta`, children, `Link`, `containerClassName`, `variant="full|compact"` and `onNavigate(event, item)` (available since 0.7.1, including explicit external anchors). Each link group is a labeled navigation landmark. Translated titles, destinations, legal/version text and social links belong to the consumer. A product may place a compact footer in its mobile sheet; a full marketing footer is not mandatory in a dashboard.
44
50
 
45
51
  Desktop reserves `ui.navigation-brand-width` (160px) for the brand, followed by the existing 16px row gap. With matching frame, viewport and font conditions, `.naeil` and `.naeil Home` therefore start their first menu at the same position. Mobile keeps intrinsic brand width. For a larger custom brand, override `--ui-navigation-brand-width` on the header or shared product frame; use the same value across related compositions and ensure the brand fits the reserved area.
46
52
 
47
53
  ## Compatibility
48
54
 
49
- Menu groups accept `columns?: 1 | 2` (default 1). The candidate sample uses 2 for the website project catalog and 1 for Home's functional menu; the mobile sheet remains one column. Menu widths use `ui.navigation-menu-width` (320px) and `ui.navigation-menu-wide-width` (640px), capped by available space. Group links share a 40px icon area, 16px icon-to-copy gap, title/description hierarchy and badges beside the title. Supply decorated brand artwork through `icon`; the shared package does not own product illustrations. Current group links use background, semibold title and a check indicator, retaining `aria-current` and keyboard focus without underlining descriptions.
55
+ Menu groups accept `columns?: 1 | 2` (default 1). The sample uses 2 for the website project catalog and 1 for Home's functional menu; the mobile sheet remains one column. Menu widths use `ui.navigation-menu-width` (320px) and `ui.navigation-menu-wide-width` (640px), capped by available space. Group links share a 40px icon area, 16px icon-to-copy gap, title/description hierarchy and badges beside the title. Supply decorated brand artwork through `icon`; the shared package does not own product illustrations. Current group links use background, semibold title and a check indicator, retaining `aria-current` and keyboard focus without underlining descriptions.
50
56
 
51
- Existing `Nav` and `Footer` imports and props remain. `Nav` adapts the canonical NaeilHeader, which renders this generic core; `Footer` composes SiteFooter. `Nav` retains its fixed positioning and uses the shared 1600px application frame; menus gain keyboard/focus support, an opaque shared surface, 16px labels and a 64px minimum row. Its `projects` prop replaces the old default inventory; the old naeil projects remain the fallback for existing consumers. Optional `labels`, `className` and `containerClassName` support localization and frame overrides. Remove old `max-w-7xl` or `px-6` frame overrides to adopt the new defaults.
57
+ Existing `Nav` and `Footer` imports and props remain. `Nav` adapts the canonical NaeilHeader, which renders this generic core; `Footer` composes SiteFooter. `Nav` retains its fixed positioning and uses the shared 1600px application frame; menus gain keyboard/focus support, an opaque shared surface, 16px labels and a 64px minimum row. Its `projects` prop replaces the default inventory; the fallback is the single-project naeil-ui catalog from [the shared catalog source](https://github.com/naeil-dev/naeil-ui/blob/main/src/components/naeil-header-data.ts), available since 0.7.2. Optional `labels`, `className` and `containerClassName` support localization and frame overrides. Remove old `max-w-7xl` or `px-6` frame overrides to adopt the new defaults.
52
58
 
53
59
  `Footer` adds `brandSlot`, `description`, `groups`, `socialSlot`, `meta`, `variant`, `className` and `containerClassName`. Use empty groups or null description/socialSlot to omit defaults. Existing linksExternal behavior remains for the default naeil links. Custom groups define their own absolute destinations and external/target settings.
54
60
 
@@ -10,7 +10,7 @@ Select/Value/Group alias Radix parts. Root: `value`/`defaultValue`/`onValueChang
10
10
 
11
11
  Inherited [Select 2.2.6 declaration](https://unpkg.com/@radix-ui/react-select@2.2.6/dist/index.d.ts).
12
12
 
13
- The [shared usage contract](common.md) covers setup, inherited/native prop typing, themes, density, font delivery and overrides. [Wrapper source](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/src/components/ui/select.tsx) is the API authority.
13
+ The [shared usage contract](common.md) covers setup, inherited/native prop typing, themes, density, font delivery and overrides. [Wrapper source](https://github.com/naeil-dev/naeil-ui/blob/main/src/components/ui/select.tsx) is the API authority.
14
14
 
15
15
  ## Composition
16
16
 
@@ -1,6 +1,6 @@
1
1
  # Sheet
2
2
 
3
- Use Sheet for supporting detail or evidence that belongs at the edge of the current task. AB Storm's repeated 480px evidence panel is the demonstrated composition need. Prefer an inline panel for ordinary editing and [Dialog](dialog.md) for a centered interruption. This is an additive, unpublished component in this checkout; it is not part of the previously published guides' release baseline.
3
+ Use Sheet for supporting detail or evidence that belongs at the edge of the current task. AB Storm's repeated 480px evidence panel is the demonstrated composition need. Prefer an inline panel for ordinary editing and [Dialog](dialog.md) for a centered interruption. Available since 0.12.0. See [release identities and publication status](../package-release.md#publication-and-deployment) for the current published release.
4
4
 
5
5
  ## API and wrapper defaults
6
6
 
@@ -10,7 +10,7 @@ Accepts Sonner `ToasterProps`. Wrapper defaults: theme from next-themes (falls b
10
10
 
11
11
  Inherited [Sonner 2.0.7 declarations](https://unpkg.com/sonner@2.0.7/dist/index.d.ts). Installed Sonner implements polite notifications and Alt+T as its default focus hotkey; these are primitive behaviors, not new wrapper defaults.
12
12
 
13
- The [shared usage contract](common.md) covers setup, inherited/native prop typing, themes, density, font delivery and overrides. [Wrapper source](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/src/components/ui/sonner.tsx) is the API authority.
13
+ The [shared usage contract](common.md) covers setup, inherited/native prop typing, themes, density, font delivery and overrides. [Wrapper source](https://github.com/naeil-dev/naeil-ui/blob/main/src/components/ui/sonner.tsx) is the API authority.
14
14
 
15
15
  ## Composition
16
16
 
@@ -35,3 +35,9 @@ Sonner creates its notification region; meaningful text should convey status wit
35
35
  Demonstrate success/info/warning/error, loading updated by the same id, and an action. Toaster has no disabled/loading prop; those belong to toast calls and initiating controls. With no notifications it renders no message. Keep long multilingual text wrap-safe, use mobileOffset deliberately, avoid duplicate toasters and move persistent errors/retry to the page. Custom style/icons/animations need contrast and reduced-motion verification.
36
36
 
37
37
  Check this example in light/dark, comfortable/compact and mobile, including long Korean, English and Japanese text. Consumer overrides remain supported; follow the [shared override and acceptance guidance](common.md#styling-themes-and-overrides). Actual engine results and manual limits are in the [support matrix](../design/public-ui-support.md).
38
+
39
+ ## Touch target compatibility (2026-11-12)
40
+
41
+ Styled toast dismiss and action/cancel controls now have at least 44px pointer targets. Pseudo-elements preserve the existing visible 20px dismiss and 24px action heights; action/cancel width is at least 44px. The close target extends inward from the toast corner to stay inside mobile viewport offsets. This can add a few pixels to very short action labels. Keep space between actions, and recheck target overlap with custom toast content, offsets, stacking or styles. Unstyled/custom toast rendering owns its target sizing.
42
+
43
+ Toaster also honors next-themes `forcedTheme` before its configured/system theme, keeping the dismiss icon legible when a preview or consumer forces dark mode. Explicit consumer `theme` still overrides this default.
@@ -8,7 +8,7 @@ Export: `Switch`. Forwards Radix Root props: `checked`/`defaultChecked`/`onCheck
8
8
 
9
9
  Inherited [Switch 1.2.6 declaration](https://unpkg.com/@radix-ui/react-switch@1.2.6/dist/index.d.ts).
10
10
 
11
- The [shared usage contract](common.md) covers setup, inherited/native prop typing, themes, density, font delivery and overrides. [Wrapper source](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/src/components/ui/switch.tsx) is the API authority.
11
+ The [shared usage contract](common.md) covers setup, inherited/native prop typing, themes, density, font delivery and overrides. [Wrapper source](https://github.com/naeil-dev/naeil-ui/blob/main/src/components/ui/switch.tsx) is the API authority.
12
12
 
13
13
  ## Composition
14
14
 
@@ -10,7 +10,7 @@ The wrappers set only slots/classes. Installed [Radix Tabs 1.1.13 declarations](
10
10
 
11
11
  `forceMount` retains children and makes inactive panels present too. Consumers must explicitly hide inactive content, for example `hidden={value !== 'draft'}`, so it cannot receive focus or appear as a second visible panel. Root has no group-wide `disabled` prop; disable individual triggers. Keep matching values, generated IDs/roles and focus handlers intact.
12
12
 
13
- The [shared usage contract](common.md) covers setup, inherited/native prop typing, themes, density, font delivery and overrides. [Wrapper source](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/src/components/ui/tabs.tsx) is the API authority.
13
+ The [shared usage contract](common.md) covers setup, inherited/native prop typing, themes, density, font delivery and overrides. [Wrapper source](https://github.com/naeil-dev/naeil-ui/blob/main/src/components/ui/tabs.tsx) is the API authority.
14
14
 
15
15
  ## Composition
16
16
 
@@ -8,7 +8,7 @@ Export: `Textarea`. Accepts `React.ComponentProps<"textarea">`, including React
8
8
 
9
9
  The wrapper sets only slot/classes; **omitted `rows` retains the native two-row default**. It defaults to vertical resizing, full available width, 16px text, 25px line height and 8px vertical padding. Root density supplies the existing 40/36px minimum, raised to at least 44px on mobile/coarse pointers; rows and text determine the actual multiline height. It has no fixed control height or content autosizing. Consumer `rows`, resizing classes, padding and styles remain available. No label, error, value, validation or disabled default is invented.
10
10
 
11
- The [shared usage contract](common.md) covers setup, inherited/native prop typing, themes, density, font delivery and overrides. [Wrapper source](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/src/components/ui/textarea.tsx) is the API authority. Native props are defined by the installed React 19 declarations and HTML textarea behavior.
11
+ The [shared usage contract](common.md) covers setup, inherited/native prop typing, themes, density, font delivery and overrides. [Wrapper source](https://github.com/naeil-dev/naeil-ui/blob/main/src/components/ui/textarea.tsx) is the API authority. Native props are defined by the installed React 19 declarations and HTML textarea behavior.
12
12
 
13
13
  ## Composition
14
14
 
@@ -1,6 +1,8 @@
1
1
  # Public UI support and manual acceptance
2
2
 
3
- This support matrix targets published `@naeil/ui@0.4.0` (2026-10-11); the [release](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.4.0) and [publication report](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/naeil-brand-0.4.0-publication.md) identify its source, npm archive, independent brand 1.1.1 and deployed Docs/site. Current documentation covers 13 component families plus Brand / Logo. Coverage describes the checked examples and dependency versions; native/manual acceptance remains open.
3
+ This support matrix targets published `@naeil/ui@0.4.0` (2026-10-11); the [release](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.4.0) and [publication report](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/naeil-brand-0.4.0-publication.md) identify its source, npm archive, independent brand 1.1.1 and deployed Docs/site. That release’s documentation covered 13 component families plus Brand / Logo; the [maintained component index](../components/README.md) describes the repository API surface. Coverage describes the checked examples and dependency versions; native/manual acceptance remains open.
4
+
5
+ The [owned-service language runtime](../components/naeil-locale.md) documents `/naeil-locale`, `/client`, `/server`, `/messages`, `/checker` and `/chrome`. Owned Next services use provider-backed chrome with exact `next-intl@4.14.8`; standalone React header/footer adapters remain available. These entries have their own release and consumer receipts; the historical foundation matrix below does not certify their routing, authentication or production adoption.
4
6
 
5
7
  ## 0.4.0 publication coverage
6
8
 
@@ -2,21 +2,24 @@
2
2
 
3
3
  이 안내는 `@naeil/ui`의 기본 모양과 재사용 규칙을 설명한다. 패키지 소비와 소비 사이트 배포는 별도 작업이다.
4
4
 
5
- **정확한 0.8.0 npm 게시·archive 일치 검증 완료 — 2026-10-29.** registry 태그는 `latest=0.7.2`, `next=0.8.0`이며 0.8.0 archive는 동결된 139파일과 일치한다. Home API는 0.8.0에 포함된다. 현재 소스의 **0.9.0은 미게시 후보**이며 root 예약 기본값을 추가한다. hosted Docs와 소비 서비스 배포는 별도 기록이다. [릴리스 정책](../package-release.md#publication-and-deployment)을 따른다.
5
+ Home API는 0.8.0부터, 공통 root 예약 기본값은 0.9.0부터 제공한다. 현재 게시 버전과 설치 명령은 [README](../../README.md#use-the-ui), 릴리스·hosted Docs·서비스별 기록은 [릴리스 정책](../package-release.md#publication-and-deployment)을 확인한다.
6
+
7
+ 소유한 Next 서비스는 [공통 언어 런타임](../components/naeil-locale.md)의 `/naeil-locale`, `/client`, `/server`, `/messages`, `/checker`를 사용한다. `NaeilLocaleProvider` 안에서는 헤더·계정·푸터를 `/naeil-locale/chrome`에서 가져온다. `/naeil-header`와 `/naeil-footer`는 독립 React 어댑터로 유지된다. 공유 server/client 경로에는 정확한 `next-intl@4.14.8`이 필요하다.
6
8
 
7
9
  ## 시작하기
8
10
 
9
11
  React 19/ReactDOM 19와 Tailwind 4 앱에서 `/ui` 또는 선택적 `/naeil-header`·`/naeil-footer`를 사용한다. API 키와 Next.js는 필요 없다. 검증한 registry 버전을 고정해 설치한다.
10
12
 
11
13
  ```sh
12
- pnpm add --save-exact @naeil/ui@0.8.0
14
+ pnpm add --save-exact @naeil/ui@VERSION
15
+ # VERSION은 README와 registry에서 확인한 정확한 게시 버전으로 바꾼다.
13
16
  ```
14
17
 
15
- registry의 0.8.0 archive는 동결 릴리스 archive와 바이트가 일치한다. archive에 포함된 안내는 준비 시점의 기록이므로 현재 설치에는 이 유지보수 안내를 따른다. 로컬 개발에서는 저장소에서 `pnpm build:pkg`와 `npm pack --ignore-scripts --pack-destination /tmp`를 실행하고 현재 미게시 후보인 `/tmp/naeil-ui-0.9.0.tgz`를 설치한다. 현재 소스의 개발용 pack은 동결 릴리스 archive와 다르므로 게시 파일을 대체하지 않는다. [독립 React 예제](https://github.com/naeil-dev/naeil-ui/tree/main/examples/react)와 [검증/릴리스 정책](../package-release.md)을 참고한다.
18
+ archive에 포함된 안내는 준비 시점의 기록이므로 현재 설치에는 이 유지보수 안내를 따른다. 로컬 개발에서는 저장소에서 `pnpm build:pkg`와 `npm pack --ignore-scripts --pack-destination /tmp`를 실행하고 출력된 archive를 설치한다. 현재 소스의 개발용 pack은 동결 릴리스 archive와 다를 수 있으므로 게시 파일을 대체하지 않는다. [독립 React 예제](https://github.com/naeil-dev/naeil-ui/tree/main/examples/react)와 [검증/릴리스 정책](../package-release.md)을 참고한다.
16
19
 
17
20
  공통 UI 소비에는 Supabase, 21st 또는 다른 API 키가 필요하지 않다. React/ReactDOM 19는 소비 앱의 peer이며, Next 15/16과 next-intl 4는 호환 경로에 필요한 선택적 peer다. next-themes 0.4와 tailwind-merge 3은 공통 런타임 의존성으로 설치된다. 사이트의 Supabase·MDX·Three 의존성과 코드는 공통 소비 경계에서 제외했다.
18
21
 
19
- 버전을 생략한 설치는 registry의 latest 태그를 따른다. 2026-10-29에 latest는 0.7.2, next는 0.8.0으로 확인했다. Home API를 사용하려면 검증한 0.8.0을 명시한다. 업그레이드 전에 [변경 기록](../../CHANGELOG.md)을 확인한다.
22
+ 버전을 생략한 설치는 registry의 latest 태그를 따른다. 업그레이드 전에 `npm view @naeil/ui dist-tags`와 [변경 기록](../../CHANGELOG.md)을 확인하고 검증한 정확한 버전을 고정한다.
20
23
 
21
24
  Tailwind 4를 사용하는 앱의 전역 CSS에서 공통 스타일을 한 번 불러온다.
22
25
 
@@ -29,7 +32,7 @@ Tailwind 4를 사용하는 앱의 전역 CSS에서 공통 스타일을 한 번
29
32
 
30
33
  이미 Tailwind와 기본 스타일을 구성한 앱은 `@naeil/ui/theme.css`와 `@naeil/ui/components.css`를 함께 불러올 수 있다. 컴포넌트 CSS에는 크기·포커스·밀도·포털·reduced-motion 규칙이 있으므로 theme.css만으로 전체 v2 모양이 완성되지는 않는다.
31
34
 
32
- 0.9.0 후보부터 두 CSS 경로의 `components.css`가 `html { scrollbar-gutter: stable }`과 Radix 이중 보상 제거를 제공한다. classic은 한쪽 공간을 예약하고 overlay는 0px이다. `<html data-naeil-scrollbar-gutter="auto">`를 첫 paint 전에 선언하면 root 예약과 lock 보정을 함께 끈다. theme-only/JS-only는 문서 정책을 바꾸지 않는다. 본문 바깥 여백/custom scroller/helper class는 별도 소비자 통합이나 opt-out이 필요하다. [채택된 계약](https://github.com/naeil-dev/naeil-ui/blob/434b7d07235316097ca3a55265ee02c1422b0cfd/docs/superpowers/specs/2026-10-29-page-root-scrollbar-gutter.md)과 [layout guide](../components/application-layout.md)의 비교·fallback·일본어 320px F3 wrap 규칙을 따른다.
35
+ 0.9.0부터 두 CSS 경로의 `components.css`가 `html { scrollbar-gutter: stable }`과 Radix 이중 보상 제거를 제공한다. classic은 한쪽 공간을 예약하고 overlay는 0px이다. `<html data-naeil-scrollbar-gutter="auto">`를 첫 paint 전에 선언하면 root 예약과 lock 보정을 함께 끈다. theme-only/JS-only는 문서 정책을 바꾸지 않는다. 본문 바깥 여백/custom scroller/helper class는 별도 소비자 통합이나 opt-out이 필요하다. [채택된 계약](https://github.com/naeil-dev/naeil-ui/blob/434b7d07235316097ca3a55265ee02c1422b0cfd/docs/superpowers/specs/2026-10-29-page-root-scrollbar-gutter.md)과 [layout guide](../components/application-layout.md)의 비교·fallback·일본어 320px F3 wrap 규칙을 따른다.
33
36
 
34
37
  CSS import를 `layer(ui)` 같은 named layer로 감싸지 않는다. 그러면 dependency의 unlayered `--removed-body-scroll-bar-size`가 이겨 classic에서 15px로 남을 수 있다. opt-out 후 `@layer base { html { scrollbar-gutter: stable; } }`는 패키지 attribute selector보다 약하므로, layer 밖에 `html[data-naeil-scrollbar-gutter="auto"] { scrollbar-gutter: stable; }`를 쓰거나 패키지 import 뒤의 같은 base layer에서 이 attribute selector를 쓴다. 이때 lock 보상은 소비자가 책임진다. Classic modal scrim은 예약된 gutter 띠를 덮지 않으며, 0.9.0에서 scrim 스타일을 바꾸지 않는다. 자세한 예시와 적용 범위는 [layout guide](../components/application-layout.md#width-contract)를 따른다.
35
38
 
@@ -212,9 +215,11 @@ i18n/config
212
215
  i18n/routing
213
216
  ```
214
217
 
218
+ **Server Components:** `@naeil/ui/ui` remains a client component barrel; do not call its `buttonVariants` or `badgeVariants` exports on the server. Use `@naeil/ui/components/ui/button` and `@naeil/ui/components/ui/badge` for those server-side helper calls. Both `@naeil/ui/utils` and `@naeil/ui/lib/utils` provide RSC-safe `cn`.
219
+
215
220
  `components/index` has the same framework requirements as root. `/utils` and `lib/utils` remain aliases for `cn`. `i18n/config` preserves the compatibility locale names; products may instead own their locale list and routing. There are no open-ended component/lib/i18n export patterns. Root, `/ui`, `/utils`, `/theme.css`, `/globals.css` and `/components.css` remain public. `/naeil-header`, `/naeil-footer` and `/release` are explicit dedicated entries; they do not create open-ended component export patterns.
216
221
 
217
- Every excluded source path stays in this repository for the brand/example website. Move any local-source consumer use into the consumer application before upgrading:
222
+ These source paths are not package entries: website-only paths belong to the brand/example website, and unused ones may be removed without a package API change. Move any local-source consumer use into the consumer application before upgrading:
218
223
 
219
224
  | Previously declared source path | Ownership/migration |
220
225
  | --- | --- |
@@ -1,16 +1,24 @@
1
1
  # Package verification and release policy
2
2
 
3
- **Published exact baseline: 0.10.0 — 2026-11-04.** Source/tag `455f2f9aedb108606af2f429c18281260eafd2dd`, frozen archive SHA-256 `a4a1e312f2f608358a10f9019c248af37a8172bb116d3bc506144442cb963fb4`, 175 regular files. Registry bytes matched; verified tags were `latest=0.7.2`, `next=0.10.0`. See the [publication and three-service acceptance receipts](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/shared-language-2026-11-04/implementation-progress.md). Historical releases, archives and receipts remain immutable; hosted Docs require their own receipt. The retained [local runner](https://github.com/naeil-dev/naeil-ui/blob/main/docs/rollout/local-runner.md) is a **0.7.x-only, contract 1** release/recovery tool, outside the current 0.10.0 deployment and recovery procedure. UI v2 names a design generation, not an npm major. Version-scoped installation is in the [README](../README.md#use-the-ui).
3
+ **Publication receipt: 0.12.0 published 2026-11-10; registry tags verified 2026-11-11.** Source/tag `e03af076b725d742c4b319aca5ebb2379e2f0258`, frozen archive SHA-256 `7f5f01407c576e3c5fa956cf76ebfb3a8ef59b58619de99da68351974aca721b`, 178 regular files. Registry bytes matched; verified tags are `latest=0.12.0`, `next=0.12.0` ([receipt](https://github.com/naeil-dev/naeil-ui/blob/main/docs/releases/0.12.0/README.md), [GitHub Release](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.12.0)). Earlier baseline 0.10.0 — 2026-11-04: source/tag `455f2f9aedb108606af2f429c18281260eafd2dd`, SHA-256 `a4a1e312f2f608358a10f9019c248af37a8172bb116d3bc506144442cb963fb4`, 175 files, tags then `latest=0.7.2`, `next=0.10.0`. See the [publication and three-service acceptance receipts](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/shared-language-2026-11-04/implementation-progress.md). Historical releases, archives and receipts remain immutable; hosted Docs require their own receipt. The retained [local runner](https://github.com/naeil-dev/naeil-ui/blob/main/docs/rollout/local-runner.md) is a **0.7.x-only, contract 1** release/recovery tool, outside release and recovery procedures for 0.8.0 and later. UI v2 names a design generation, not an npm major. Version-scoped installation is in the [README](../README.md#use-the-ui).
4
4
 
5
- ## 0.12.0 candidate — shared UI refinements and Sheet
5
+ ## 0.13.0 candidate — audit fixes and owned-service headers
6
6
 
7
- This additive minor API candidate includes PR #42 (`0d1cb08`): optional `closeLabel` for `DialogContent`/`DialogFooter` with unchanged defaults, error versus destructive guidance and checks, NaeilFooter starters using default `full`, compact footer link groups aligned to the top unless overridden with consumer `items-*` classes, and `ui.width-workflow` (896px) / `data-ui-layout="workflow"`. The locale service registration proposal is documentation only. PR #43 (`047de96`) adds public Sheet primitives at `@naeil/ui/ui` and `@naeil/ui/components/ui/sheet`.
7
+ Not published. PR #47 supplies the 2026-11-12 audit fixes: server-safe utility imports, locale request/protocol hardening, pressed/theme/typography/accessibility behavior, package payload cleanup and CI checks. PR #48 adds strict opt-in `service` profiles for `abstorm`, `home`, `estimate` and `jev`, canonical lowercase branding and service-only tabs, plus toolbar-only mobile sheets with desktop focus restoration. Legacy props/output and inferred `NaeilHeaderProps` remain supported through service-first/legacy-last overloads. Deprecated brand/status/toolbar escape hatches remain functional without `service`; see [header profiles](components/naeil-header.md) and [compatibility changes](../CHANGELOG.md).
8
8
 
9
- Use the manual exact-archive procedure below, publish to `next` and preserve `latest=0.7.2` unless separately approved. Exact 0.11.0 is published to `next`; its promotion remains a separate owner action. The intended tag is `v0.12.0` at the frozen source. Package version, generated `/release` metadata and clean React/Next fixture versions move together; the existing Sheet root/deep consumer checks remain required. Freeze after all bundled documentation edits, then record source, digest, inventory and gate results outside the archive in a separate evidence-only commit. Publication, registry verification, consumer adoption, GitHub Release and hosted Docs remain separate maintainer steps; the historical 0.7.x runner and chrome contract 1 are unchanged.
9
+ Package metadata, generated `/release` and clean React/Next fixture versions are 0.13.0. Chrome contract 1 is unchanged because the service branch is opt-in and the omitted-service legacy contract is preserved; the audit's changed visual defaults and dependency/font guidance are listed in the changelog. Freeze all bundled source and guide edits in the source/version commit, then retain the exact archive, full member hashes and final local gates outside the npm payload in a separate evidence-only commit, as for 0.12.0. Rebuild from that frozen Git source and require byte-identical packing.
10
10
 
11
- ## 0.11.0 candidate — AB Storm locale registry
11
+ Registry checked 2026-11-12: `latest=0.12.0`, `next=0.12.0`; 0.13.0 is absent. The owner runs the manual publication command with OTP, publishes the reviewed archive to `next` and preserves `latest` unless separately approved. Intended tag `v0.13.0` must identify the frozen source. Preparation executes none of publication, dist-tag changes, tag/Release creation, workflow dispatch, push/merge, hosted Docs deployment or service adoption; each requires its own maintainer action and receipt. Historical release directories, archives, receipts and the 0.7.x rollout runner stay unchanged.
12
12
 
13
- This additive API candidate registers AB Storm's five protected UI routes and error-document identity. Use the manual exact-archive procedure below, publish to `next` and preserve `latest`; the intended tag is `v0.11.0` at the frozen source. The historical 0.7.x runner transaction and chrome contract 1 remain unchanged. Package version, generated `/release` metadata and clean consumer fixture versions move together. Freeze only after all bundled documentation edits, and record source, digest, inventory and final checks outside the archive. Publication, registry verification, consumer adoption, GitHub Release and hosted Docs remain separate maintainer steps.
13
+ ## 0.12.0 release — shared UI refinements and Sheet
14
+
15
+ This additive minor release includes PR #42 (`0d1cb08`): optional `closeLabel` for `DialogContent`/`DialogFooter` with unchanged defaults, error versus destructive guidance and checks, NaeilFooter starters using default `full`, compact footer link groups aligned to the top unless overridden with consumer `items-*` classes, and `ui.width-workflow` (896px) / `data-ui-layout="workflow"`. The locale service registration proposal is documentation only. PR #43 (`047de96`) adds public Sheet primitives at `@naeil/ui/ui` and `@naeil/ui/components/ui/sheet`.
16
+
17
+ Published 2026-11-10 to `next` and promoted to `latest` on 2026-11-11 with owner approval (see the receipt above). Tag `v0.12.0` identifies the frozen source. Package version, generated `/release` metadata and clean React/Next fixture versions move together. Future releases require a new frozen source/archive and their own gates; maintained guide edits do not replace this archive. Publication, registry verification, consumer adoption, GitHub Release and hosted Docs remain separate receipts.
18
+
19
+ ## 0.11.0 release — AB Storm locale registry
20
+
21
+ Published 2026-11-08, this additive release registers AB Storm's five protected UI routes and error-document identity. Tag `v0.11.0` identifies its frozen source; see the [release](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.11.0). The historical 0.7.x runner transaction and chrome contract 1 remain unchanged. Package publication, consumer adoption and hosted Docs require separate receipts.
14
22
 
15
23
  ## Architecture
16
24
 
@@ -18,6 +26,8 @@ One repository contains the shared package and the separate Next.js brand/exampl
18
26
 
19
27
  Owned services use `@naeil/ui/naeil-footer` for the canonical localized destinations in full/compact variants; generic SiteFooter and legacy Footer retain their APIs. Footer navigation adapters preserve application save/flush decisions and modified-click behavior. `@naeil/ui/release` is server-safe metadata; it contains no application artifact, credential or environment. Applications compile their own allowlisted artifact/source identity. See [the footer contract](components/naeil-footer.md). Historical 0.7.x release plans and transaction recovery use the [local rollout runner](https://github.com/naeil-dev/naeil-ui/blob/main/docs/rollout/local-runner.md); the [rollout records](https://github.com/naeil-dev/naeil-ui/tree/main/docs/rollout) preserve dated evidence and historical policies. Publishing a package, creating an update PR or merging it never establishes complete consumer rollout. Home Console is outside the selected shared-UI rollout.
20
28
 
29
+ The [owned-service language runtime](components/naeil-locale.md) exposes `/naeil-locale` for registered routes/locales, `/server` for request routing/configuration, `/client` for the controller/provider, `/messages` for selected dictionaries, `/checker` for message validation and `/chrome` for provider-backed header/account/footer presentation. Owned Next services under `NaeilLocaleProvider` use `/naeil-locale/chrome`; `/naeil-header` and `/naeil-footer` remain standalone React adapters. The shared server/client runtime requires exact `next-intl@4.14.8`.
30
+
21
31
  Website tools remain development dependencies so maintainers can develop both products. npm tarball consumers install only component runtime dependencies and their host React/ReactDOM. Build entries, package exports and packed checks constrain the public boundary. There is no bundled website action, Supabase helper, Three/hero/cursor module, blog engine or full application message catalog. The opt-in header includes only its three header dictionaries and canonical project catalog. Its 0.7.2 default catalog contains naeil-ui and references the official `https://naeil.dev/images/whale.png` URL and require network access; no image bytes are bundled, and unresolved artwork redistribution provenance remains in [third-party notices](../THIRD_PARTY_NOTICES.md).
22
32
 
23
33
  ## Checks
@@ -133,7 +143,7 @@ The immutable npm archive's bundled guides are the release-preparation snapshot.
133
143
 
134
144
  ### Release procedure
135
145
 
136
- Maintained Storybook resolves relative Markdown guide links against the published `v0.7.2` source `40a3928e24cd2f0141be3e605eed0a75260938fd`. Package releases keep that published guide-link target until a separately reviewed Docs release. That tag is independent of the reviewed Docs deployment SHA. Hosted verification checks that the pinned links resolve; the unpublished `v0.7.0` tag is not a valid target. Historical foundation/source-authority links remain at their original revisions. Freeze subsequent documentation changes separately from immutable release archives.
146
+ Storybook resolves relative Markdown guide and TypeScript source links against `v${version}`, using the version from the package.json being built. Maintained repository guides use relative wrapper-source links so their API authority follows the checkout. The package tag is independent of the reviewed Docs deployment SHA; hosted verification checks links against the build’s package version. Explicit historical evidence links retain their recorded revisions. Freeze subsequent documentation changes separately from immutable release archives; a new version’s links become publicly reachable only when its source tag exists.
137
147
 
138
148
  The authorized 0.3.0 release completed main merge, npm 0.3.0, a GitHub Release and hosted Docs as recorded above. The release maintainer performs external authentication and publication; documentation preparation does not itself execute those operations. The automatic verification workflow does not publish or deploy. Record native/manual observations with their actual scope and carry unrun checks as limitations; do not substitute automated WebKit/axe checks or publication authorization for human certification.
139
149
 
@@ -166,7 +176,7 @@ Package publication, tag, GitHub Release, main merge and Home deployment each re
166
176
 
167
177
  ## Storybook preview artifact
168
178
 
169
- `pnpm build:storybook` builds 17 actual Docs pages: 15 UI families (the 13 primitives plus Navigation and SiteFooter) and Brand / Logo and NaeilHeader. Interactive examples include the complete branded header, JapaneseApplication, canonical footer ReferenceFull/ReferenceCompact and AccountStates. Canonical footer/account examples live within existing stories, without a separate NaeilFooter Docs family. It copies generated documentation notices and approved canonical brand SVGs, bundles locally installed Pretendard/Noto Sans JP and disables Vite publicDir. The artifact check verifies real Docs/story entries, exact MIT/shadcn/font notices, brand references and absence of website public images/SVGs/HTML. It does not claim those excluded site assets have cleared rights.
179
+ `pnpm build:storybook` builds 18 actual Docs pages: 16 UI families (the 14 primitives plus Navigation and SiteFooter) and Brand / Logo and NaeilHeader. Interactive examples include the complete branded header, JapaneseApplication, canonical footer ReferenceFull/ReferenceCompact and AccountStates. Canonical footer/account examples live within existing stories, without a separate NaeilFooter Docs family. It copies generated documentation notices and approved canonical brand SVGs, bundles locally installed Pretendard/Noto Sans JP and disables Vite publicDir. The artifact check verifies real Docs/story entries, exact MIT/shadcn/font notices, brand references and absence of website public images/SVGs/HTML. It does not claim those excluded site assets have cleared rights.
170
180
 
171
181
  CI uploads `storybook-preview` after a successful build; it is a downloadable static artifact, not a hosted deployment. Download/unzip it and serve the extracted directory (containing index.html):
172
182
 
@@ -192,16 +202,16 @@ Select **Publish reviewed UI docs (manual only)** in Actions (or use the command
192
202
  gh workflow run publish-docs-manual.yml --ref main -f reviewed_sha=FULL_REVIEWED_DOCS_COMMIT_SHA -f confirmation=PUBLISH_REVIEWED_DOCS
193
203
  ```
194
204
 
195
- After the reviewed Docs deployment, verify the manager and iframe under `/naeil-ui/`, all 15 UI and 2 Brand Docs pages, their Usage examples, NaeilHeader JapaneseApplication, canonical footer full/compact destinations, and signed-out/signed-in/menu/busy account states. Check the maintained `v0.7.2` guide links (or the separately approved release target), canonical artwork and official image references, local fonts and exact LICENSE/THIRD_PARTY_NOTICES/font notices over HTTP. Retain the deployment URL, Docs source SHA, workflow run and observed results separately from the package source/tag. Hosted Storybook uses simulated data and requires no Supabase project, design API key or external font server. Only the reviewed Storybook directory is uploaded; website public assets stay excluded.
205
+ After the reviewed Docs deployment, verify the manager and iframe under `/naeil-ui/`, all 16 UI and 2 Brand Docs pages, their Usage examples, NaeilHeader JapaneseApplication, canonical footer full/compact destinations, and signed-out/signed-in/menu/busy account states. Check the guide and source links against the tag matching the built package.json version, canonical artwork and official image references, local fonts and exact LICENSE/THIRD_PARTY_NOTICES/font notices over HTTP. Retain the deployment URL, Docs source SHA, workflow run and observed results separately from the package source/tag. Hosted Storybook uses simulated data and requires no Supabase project, design API key or external font server. Only the reviewed Storybook directory is uploaded; website public assets stay excluded.
196
206
 
197
207
  Normal builds are network-independent after dependency installation. Vite collects notices for actual preview modules; checked-in manager notices conservatively cover named embedded packages and versions from Storybook 10.4.6's original source lock. `check-storybook` fails if a named embedded module lacks a full notice. Four vendored tiny modules have no embedded version in that lock/comments; their original npm notice source is explicitly marked, without an exact-version claim. The exact use-composed-ref@1.4.0 tarball/repository provides MIT metadata but no standalone notice; its metadata plus full declared terms are retained without inventing a year/holder. The client-only@0.0.1 React marker retains its exact metadata and the original React MIT notice. Other missing notices fail the build; no generic MIT fallback passes arbitrary packages.
198
208
 
199
209
  For a Storybook dependency upgrade, first build the new preview to obtain fresh manager scripts, then run `python3 scripts/refresh-storybook-notices.py` (read-only npm/source retrieval plus a local notice-file update), review its source/notice changes, and rebuild. The refresh is opt-in and needs network; the build never retrieves legal/reference material silently. Keep all generated `licenses/` JSON/text files with the preview. The standalone React consumer likewise emits exact installed code/font notices with its production output.
200
210
 
201
- ### 0.9.0 frame preparation gates
211
+ ### Historical 0.9.0 frame preparation gates
202
212
 
203
213
  The owner adopted rev 1 on 2026-10-29 for local implementation and verification, including the root opt-out and F3 wrap. Both CSS graphs, theme/JS-only controls, opt-out and false-support branch, short/long route frames, body/content/fixed anchors under nested Radix locks, capture guards, frozen 0.8.0 comparisons and clean installed React/Next production CSS must pass before freezing. The false-support fixture tests a CSS branch, not a real unsupported engine. `build-chrome-fixtures.ts` alone is not clean-consumer proof; `check-consumers.ts` independently installs/builds/exercises both paths in each framework.
204
214
 
205
215
  Run the normal checks above serially, plus the two deterministic Chromium mode jobs using B0's process-local wrappers, `NAEIL_UI_SCROLLBAR_MODE=classic|overlay` and `NAEIL_UI_SCROLLBAR_WRAPPERS=/absolute/wrapper-directory`. Their 15/0px overflow probes and stable-root frame probes must pass; the diagnostic `--enable-automation` flag exposes actual argv through CDP without changing the mode probe. Preserve exact source/archive SHA-256/SRI/inventory and per-gate commands/exit codes outside the archive. Repeat archive-dependent checks using `NAEIL_UI_CHROME_PACKAGE=/absolute/extracted/package` and `NAEIL_UI_EXPECTED_ARCHIVE_SHA256`.
206
216
 
207
- This candidate is not published. npm/dist-tag, version tag, GitHub Release, push/main merge (= naeil.dev production), hosted Docs and Home bump/deploy remain separate approvals. Home keeps its local root rule until an approved exact-version upgrade removes it; rollback restores manifest/lock and local root rule together. Estimate/Jev remain on 0.7.2 and STOP remains in force.
217
+ At the October 29 preparation checkpoint, the candidate was unpublished. The following holds describe that historical checkpoint, not current release or service status. npm/dist-tag, version tag, GitHub Release, push/main merge (= naeil.dev production), hosted Docs and Home bump/deploy remain separate approvals. Home keeps its local root rule until an approved exact-version upgrade removes it; rollback restores manifest/lock and local root rule together. Estimate/Jev remain on 0.7.2 and STOP remains in force.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naeil/ui",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "sideEffects": [
@@ -178,7 +178,7 @@
178
178
  "scripts": {
179
179
  "dev": "next dev",
180
180
  "build": "next build",
181
- "build:pkg": "pnpm check:messages && pnpm build:release && pnpm check:brand && tsup && tsup --config tsup.deep.config.ts && tsup --config tsup.locale.config.ts && tsx scripts/fix-locale-declarations.ts && tsx scripts/copy-locale-json.ts && tsx scripts/fix-deep-imports.ts && pnpm build:tokens && node scripts/build-release-entry.mjs && pnpm check:locale:package",
181
+ "build:pkg": "pnpm check:messages && pnpm build:release && pnpm check:brand && tsup && tsup --config tsup.deep.config.ts && tsup --config tsup.locale.config.ts && tsx scripts/fix-locale-declarations.ts && tsx scripts/copy-locale-json.ts && tsx scripts/fix-deep-imports.ts && pnpm build:tokens && node scripts/build-release-entry.mjs && node scripts/build-utils-entry.mjs && pnpm check:locale:package",
182
182
  "start": "next start",
183
183
  "lint": "eslint",
184
184
  "test": "vitest run",
@@ -214,20 +214,16 @@
214
214
  "radix-ui": "^1.4.3",
215
215
  "sonner": "^2.0.7",
216
216
  "tailwind-merge": "^3.5.0",
217
- "tw-animate-css": "^1.4.0",
218
217
  "@formatjs/icu-messageformat-parser": "3.5.1",
219
218
  "server-only": "0.0.1"
220
219
  },
221
220
  "devDependencies": {
222
221
  "@axe-core/playwright": "^4.13.0",
223
- "@axe-core/react": "^4.11.1",
224
222
  "@fontsource/noto-sans-jp": "^5.3.0",
225
223
  "@mdx-js/loader": "^3.1.1",
226
224
  "@mdx-js/react": "^3.1.1",
227
225
  "@next/mdx": "^16.2.1",
228
226
  "@playwright/test": "^1.63.0",
229
- "@react-three/drei": "^10.7.7",
230
- "@react-three/fiber": "^9.6.1",
231
227
  "@storybook/addon-a11y": "10.4.6",
232
228
  "@storybook/addon-docs": "10.4.6",
233
229
  "@storybook/nextjs-vite": "10.4.6",
@@ -238,7 +234,6 @@
238
234
  "@types/node": "^20",
239
235
  "@types/react": "^19",
240
236
  "@types/react-dom": "^19",
241
- "@types/three": "^0.183.1",
242
237
  "eslint": "^9",
243
238
  "eslint-config-next": "16.1.7",
244
239
  "eslint-config-prettier": "^10.1.8",
@@ -246,7 +241,6 @@
246
241
  "next": "16.1.7",
247
242
  "next-intl": "4.14.8",
248
243
  "pretendard": "^1.3.9",
249
- "prettier": "^3.8.1",
250
244
  "react": "19.2.3",
251
245
  "react-dom": "19.2.3",
252
246
  "reading-time": "^1.5.0",
@@ -256,9 +250,9 @@
256
250
  "storybook": "10.4.6",
257
251
  "style-dictionary": "^4.4.0",
258
252
  "tailwindcss": "^4",
259
- "three": "^0.183.2",
260
253
  "tsup": "^8.5.1",
261
254
  "tsx": "^4.21.0",
255
+ "tw-animate-css": "^1.4.0",
262
256
  "typescript": "^5",
263
257
  "vitest": "^4.1.0"
264
258
  },
@@ -270,7 +264,10 @@
270
264
  "docs/package-release.md",
271
265
  "CHANGELOG.md",
272
266
  "THIRD_PARTY_NOTICES.md",
273
- "licenses/",
267
+ "licenses/Pretendard-OFL.txt",
268
+ "licenses/Noto-Sans-JP-OFL.txt",
269
+ "licenses/Lato-OFL.txt",
270
+ "licenses/react-remove-scroll-bar-MIT.txt",
274
271
  "docs/components/",
275
272
  "docs/design/public-ui-support.md",
276
273
  "docs/design/public-ui-stage3-verification.md",
@@ -740,3 +740,32 @@ html:root [data-naeil-chrome][lang] .naeil-header-brand-suffix {
740
740
  background: GrayText;
741
741
  }
742
742
  }
743
+
744
+ /* Sonner keeps its compact visuals; reserve non-overlapping pointer targets.
745
+ Unlayered selectors match Sonner's injected, unlayered default styles. */
746
+ [data-sonner-toaster] [data-sonner-toast][data-styled="true"] [data-button] {
747
+ position: relative;
748
+ }
749
+ [data-sonner-toaster] [data-sonner-toast][data-styled="true"] [data-button]::after,
750
+ [data-sonner-toaster] [data-sonner-toast][data-styled="true"] [data-close-button]::after {
751
+ content: "";
752
+ position: absolute;
753
+ min-width: var(--ui-touch-target);
754
+ min-height: var(--ui-touch-target);
755
+ width: 100%;
756
+ height: 100%;
757
+ left: 50%;
758
+ top: 50%;
759
+ transform: translate(-50%, -50%);
760
+ }
761
+
762
+ /* Anchor the close target inward so mobile offsets do not clip it. */
763
+ [data-sonner-toaster] [data-sonner-toast][data-styled="true"] [data-close-button]::after {
764
+ left: 0;
765
+ top: 0;
766
+ transform: none;
767
+ }
768
+ [data-sonner-toaster][dir="rtl"] [data-sonner-toast][data-styled="true"] [data-close-button]::after {
769
+ left: auto;
770
+ right: 0;
771
+ }
@@ -1,9 +1,13 @@
1
1
  @import "tailwindcss";
2
- @import "tw-animate-css";
3
2
  @import "./theme.css";
4
3
  @import "./components.css";
5
4
 
6
- @custom-variant dark (&:is(.dark *));
5
+ @custom-variant dark {
6
+ &:where(.dark, .dark *) { @slot; }
7
+ @media (prefers-color-scheme: dark) {
8
+ &:where(:root:not(.light), :root:not(.light) *) { @slot; }
9
+ }
10
+ }
7
11
 
8
12
  @layer base {
9
13
  * {
@@ -65,6 +65,11 @@
65
65
  --text-2xl: 1.5rem;
66
66
  --text-3xl: 2rem;
67
67
  --text-4xl: 2.25rem;
68
+ --text-xs--line-height: 1.25rem;
69
+ --text-sm--line-height: 1.375rem;
70
+ --text-base--line-height: 1.5625rem;
71
+ --text-xl--line-height: 1.8125rem;
72
+ --text-3xl--line-height: 2.625rem;
68
73
  --font-weight-normal: 400;
69
74
  --font-weight-medium: 500;
70
75
  --font-weight-bold: 700;
@@ -1,93 +0,0 @@
1
- Copyright 2016 The Nunito Sans Project Authors (https://github.com/Fonthausen/NunitoSans)
2
-
3
- This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
- This license is copied below, and is also available with a FAQ at:
5
- http://scripts.sil.org/OFL
6
-
7
-
8
- -----------------------------------------------------------
9
- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
- -----------------------------------------------------------
11
-
12
- PREAMBLE
13
- The goals of the Open Font License (OFL) are to stimulate worldwide
14
- development of collaborative font projects, to support the font creation
15
- efforts of academic and linguistic communities, and to provide a free and
16
- open framework in which fonts may be shared and improved in partnership
17
- with others.
18
-
19
- The OFL allows the licensed fonts to be used, studied, modified and
20
- redistributed freely as long as they are not sold by themselves. The
21
- fonts, including any derivative works, can be bundled, embedded,
22
- redistributed and/or sold with any software provided that any reserved
23
- names are not used by derivative works. The fonts and derivatives,
24
- however, cannot be released under any other type of license. The
25
- requirement for fonts to remain under this license does not apply
26
- to any document created using the fonts or their derivatives.
27
-
28
- DEFINITIONS
29
- "Font Software" refers to the set of files released by the Copyright
30
- Holder(s) under this license and clearly marked as such. This may
31
- include source files, build scripts and documentation.
32
-
33
- "Reserved Font Name" refers to any names specified as such after the
34
- copyright statement(s).
35
-
36
- "Original Version" refers to the collection of Font Software components as
37
- distributed by the Copyright Holder(s).
38
-
39
- "Modified Version" refers to any derivative made by adding to, deleting,
40
- or substituting -- in part or in whole -- any of the components of the
41
- Original Version, by changing formats or by porting the Font Software to a
42
- new environment.
43
-
44
- "Author" refers to any designer, engineer, programmer, technical
45
- writer or other person who contributed to the Font Software.
46
-
47
- PERMISSION & CONDITIONS
48
- Permission is hereby granted, free of charge, to any person obtaining
49
- a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
- redistribute, and sell modified and unmodified copies of the Font
51
- Software, subject to the following conditions:
52
-
53
- 1) Neither the Font Software nor any of its individual components,
54
- in Original or Modified Versions, may be sold by itself.
55
-
56
- 2) Original or Modified Versions of the Font Software may be bundled,
57
- redistributed and/or sold with any software, provided that each copy
58
- contains the above copyright notice and this license. These can be
59
- included either as stand-alone text files, human-readable headers or
60
- in the appropriate machine-readable metadata fields within text or
61
- binary files as long as those fields can be easily viewed by the user.
62
-
63
- 3) No Modified Version of the Font Software may use the Reserved Font
64
- Name(s) unless explicit written permission is granted by the corresponding
65
- Copyright Holder. This restriction only applies to the primary font name as
66
- presented to the users.
67
-
68
- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
- Software shall not be used to promote, endorse or advertise any
70
- Modified Version, except to acknowledge the contribution(s) of the
71
- Copyright Holder(s) and the Author(s) or with their explicit written
72
- permission.
73
-
74
- 5) The Font Software, modified or unmodified, in part or in whole,
75
- must be distributed entirely under this license, and must not be
76
- distributed under any other license. The requirement for fonts to
77
- remain under this license does not apply to any document created
78
- using the Font Software.
79
-
80
- TERMINATION
81
- This license becomes null and void if any of the above conditions are
82
- not met.
83
-
84
- DISCLAIMER
85
- THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
- OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
- COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
- INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
- DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
- FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
- OTHER DEALINGS IN THE FONT SOFTWARE.