@naeil/ui 0.2.0 → 0.4.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 (109) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/DESIGN.md +194 -0
  3. package/LICENSE +21 -0
  4. package/README.md +77 -53
  5. package/THIRD_PARTY_NOTICES.md +51 -0
  6. package/dist/{chunk-SYI3IKIC.js → chunk-QKVN6Q6C.js} +102 -19
  7. package/dist/components/index.d.ts +17 -8
  8. package/dist/components/index.js +1278 -251
  9. package/dist/components/ui/index.d.ts +27 -5
  10. package/dist/components/ui/index.js +288 -33
  11. package/dist/source/components/brand-artwork.generated.d.ts +162 -0
  12. package/dist/source/components/brand-artwork.generated.js +1103 -0
  13. package/dist/source/components/footer.d.ts +15 -0
  14. package/dist/source/components/footer.js +128 -0
  15. package/dist/source/components/index.d.ts +11 -0
  16. package/dist/source/components/index.js +26 -0
  17. package/dist/source/components/locale-switcher.d.ts +17 -0
  18. package/dist/source/components/locale-switcher.js +66 -0
  19. package/dist/source/components/logo.d.ts +18 -0
  20. package/dist/source/components/logo.js +91 -0
  21. package/dist/source/components/nav.d.ts +39 -0
  22. package/dist/source/components/nav.js +375 -0
  23. package/dist/source/components/theme-provider.d.ts +6 -0
  24. package/dist/source/components/theme-provider.js +45 -0
  25. package/dist/source/components/theme-toggle-icon.d.ts +5 -0
  26. package/dist/source/components/theme-toggle-icon.js +62 -0
  27. package/dist/source/components/theme-toggle.d.ts +5 -0
  28. package/dist/source/components/theme-toggle.js +34 -0
  29. package/dist/source/components/typography.d.ts +12 -0
  30. package/dist/source/components/typography.js +49 -0
  31. package/dist/source/components/ui/avatar.d.ts +14 -0
  32. package/dist/source/components/ui/avatar.js +137 -0
  33. package/dist/source/components/ui/badge.d.ts +13 -0
  34. package/dist/source/components/ui/badge.js +76 -0
  35. package/dist/source/components/ui/button.d.ts +14 -0
  36. package/dist/source/components/ui/button.js +88 -0
  37. package/dist/source/components/ui/card.d.ts +13 -0
  38. package/dist/source/components/ui/card.js +135 -0
  39. package/dist/source/components/ui/checkbox.d.ts +7 -0
  40. package/dist/source/components/ui/checkbox.js +58 -0
  41. package/dist/source/components/ui/dialog.d.ts +20 -0
  42. package/dist/source/components/ui/dialog.js +182 -0
  43. package/dist/source/components/ui/dropdown-menu.d.ts +28 -0
  44. package/dist/source/components/ui/dropdown-menu.js +282 -0
  45. package/dist/source/components/ui/index.d.ts +19 -0
  46. package/dist/source/components/ui/index.js +131 -0
  47. package/dist/source/components/ui/input.d.ts +6 -0
  48. package/dist/source/components/ui/input.js +49 -0
  49. package/dist/source/components/ui/select.d.ts +16 -0
  50. package/dist/source/components/ui/select.js +197 -0
  51. package/dist/source/components/ui/sonner.d.ts +6 -0
  52. package/dist/source/components/ui/sonner.js +80 -0
  53. package/dist/source/components/ui/switch.d.ts +7 -0
  54. package/dist/source/components/ui/switch.js +54 -0
  55. package/dist/source/components/ui/tabs.d.ts +10 -0
  56. package/dist/source/components/ui/tabs.js +57 -0
  57. package/dist/source/components/ui/textarea.d.ts +6 -0
  58. package/dist/source/components/ui/textarea.js +46 -0
  59. package/dist/source/i18n/config.d.ts +6 -0
  60. package/dist/source/i18n/config.js +12 -0
  61. package/dist/source/i18n/routing.d.ts +371 -0
  62. package/dist/source/i18n/routing.js +17 -0
  63. package/dist/source/lib/design/modal-inert.d.ts +6 -0
  64. package/dist/source/lib/design/modal-inert.js +73 -0
  65. package/dist/source/lib/utils.d.ts +5 -0
  66. package/dist/source/lib/utils.js +8 -0
  67. package/dist/tokens.ts +217 -0
  68. package/docs/components/README.md +21 -0
  69. package/docs/components/avatar.md +47 -0
  70. package/docs/components/badge.md +29 -0
  71. package/docs/components/button.md +39 -0
  72. package/docs/components/card.md +32 -0
  73. package/docs/components/checkbox.md +35 -0
  74. package/docs/components/common.md +31 -0
  75. package/docs/components/composition.md +68 -0
  76. package/docs/components/dialog.md +41 -0
  77. package/docs/components/dropdown-menu.md +38 -0
  78. package/docs/components/input.md +32 -0
  79. package/docs/components/select.md +39 -0
  80. package/docs/components/sonner.md +37 -0
  81. package/docs/components/switch.md +33 -0
  82. package/docs/components/tabs.md +40 -0
  83. package/docs/components/textarea.md +35 -0
  84. package/docs/design/component-demand.md +30 -0
  85. package/docs/design/public-ui-final-verification.md +96 -0
  86. package/docs/design/public-ui-release-validation.md +86 -0
  87. package/docs/design/public-ui-stage3-verification.md +98 -0
  88. package/docs/design/public-ui-stage4-verification.md +129 -0
  89. package/docs/design/public-ui-support.md +42 -0
  90. package/docs/design/v2-migration.md +229 -0
  91. package/docs/package-release.md +108 -0
  92. package/licenses/Lato-OFL.txt +93 -0
  93. package/licenses/Noto-Sans-JP-OFL.txt +93 -0
  94. package/licenses/Nunito-Sans-OFL.txt +93 -0
  95. package/licenses/Pretendard-OFL.txt +94 -0
  96. package/licenses/React-MIT.txt +21 -0
  97. package/licenses/Storybook-MIT.txt +21 -0
  98. package/licenses/popper-MIT.txt +25 -0
  99. package/licenses/react-remove-scroll-bar-MIT.txt +21 -0
  100. package/licenses/store2-MIT.txt +22 -0
  101. package/licenses/toggle-selection-MIT.txt +21 -0
  102. package/package.json +184 -34
  103. package/src/styles/components.css +276 -0
  104. package/src/styles/globals.css +18 -0
  105. package/src/styles/theme.css +185 -98
  106. package/messages/en.json +0 -221
  107. package/messages/ja.json +0 -221
  108. package/messages/ko.json +0 -221
  109. package/src/app/globals.css +0 -32
@@ -0,0 +1,129 @@
1
+ # Demand-led extension verification — 2026-10-02
2
+
3
+ The approved minimal Tabs/Textarea extension and field/native-radio composition guidance are implemented and locally verified. Prepared `@naeil/ui@0.3.0` remains unpublished. This separate record extends reviewed Stage 3 `7d67fbde2370477fc164312106515a354b1a335a`; implementation began on checkout `f1d6a79799c329b09e861123f6da4d1aecb0a3a4`. Stage 3's original/follow-up hashes, 11-family results and limitations remain historical. Its two artifact-location paragraphs received prose-only hygiene edits.
4
+
5
+ [Demand decision](component-demand.md), [13-family component index](../components/README.md), [composition guide](../components/composition.md), [support/manual acceptance](public-ui-support.md) and [actual source/tool usage](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/docs/design/frontend-sources.md) define the scope. No RadioGroup/FormField API, new dependency, token value, business feature or consumer-repository edit was added. Existing public imports, consumer overrides, neutral visual contracts and mixed-entry inert behavior are retained.
6
+
7
+ ## Reproduce from the tested checkout
8
+
9
+ Environment: Node 22.23.2, pnpm 10.30.3, Playwright Chromium 153.0.8010.12 and WebKit 26.6. `pnpm-lock.yaml` identifies installed dependency versions. WebKit is a test engine, not actual Apple Safari.
10
+
11
+ ```sh
12
+ pnpm install --frozen-lockfile
13
+ pnpm test
14
+ pnpm check:types
15
+ pnpm lint
16
+ pnpm check:contrast
17
+ pnpm build:pkg
18
+ pnpm build:storybook
19
+ pnpm exec playwright install chromium firefox webkit
20
+ pnpm test:browser --project=chromium --project=webkit
21
+ pnpm check:package
22
+ NEXT_PUBLIC_SUPABASE_URL=https://example.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=public-build-fixture pnpm build
23
+ pnpm check:types
24
+ pnpm check:package:boundary
25
+ git diff --exit-code -- src/styles/theme.css src/tokens pnpm-lock.yaml
26
+ git diff --check
27
+ ```
28
+
29
+ The browser command serves the actual `storybook-static/` output through the configured local preview server. Open `pnpm preview:storybook` and navigate to UI / Tabs or Textarea / Docs and Usage. `pnpm check:package` packs the built sources, inspects the exact export/doc/CSS/notices boundary and independently installs clean React and Next fixtures; it needs network access for uncached dependencies and removes temporary installs. The site build uses explicit non-secret public fixture values and does not exercise OAuth/backend behavior. Full configured browser execution is `pnpm test:browser`; local Firefox remains blocked before application launch as documented below.
30
+
31
+ ## Final observed results
32
+
33
+ | Gate | Final observed result |
34
+ | --- | --- |
35
+ | Units | 8 suites, 41 tests passed, including four new native forwarding/export/Radix state and mounting regressions. |
36
+ | Types | Passed, including a fresh run after the website build. |
37
+ | Lint | Zero errors; one inherited unused `locale` warning in the blog route. |
38
+ | Token contrast | All 46 light/dark pairs passed. Generated theme, token JSON and lockfile have no diff. |
39
+ | Package build | Bundle, exact deep entries, declarations, import repair and token generation passed. |
40
+ | Actual Storybook build | 13 built Docs pages and 13 Usage stories passed artifact checks; 75 actual preview package notices and 254 conservative manager version notices retained. Local fonts/notices present; website public assets excluded. |
41
+ | Full local browser suite | **140 passed, 2 expected skips** in Chromium/WebKit (2.2 minutes). Both skips are Chromium-only forced-colors tests in WebKit. No earlier partial/failing run is final passing evidence. |
42
+ | Focused correction rerun | 17 passed, 1 expected WebKit forced-colors skip before the final full suite. |
43
+ | Clean packed React | Independent Vite production build/types/SSR/CSS, light/dark loaded fonts and readable deliberate font fallback passed; 48 actual production package notices retained. |
44
+ | Packed mixed-entry compatibility | Original bundled/deep inert ownership, overlapping close orders, forced unmount, object refs, focus/original-inert restoration and development StrictMode replay passed. |
45
+ | Packed extensions | Chromium and WebKit passed core/deep Tabs and deep Textarea, refs, consumer class override, RTL/disabled keyboard, native rows/form/newline/required behavior and 390px checks. |
46
+ | Clean packed Next | Production build, types and prerendered observed root/deep imports passed, including both extension controls. |
47
+ | Website compatibility | Production build passed; backend/auth/deployment unexercised. |
48
+ | Final document/package boundary | Fresh actual packed boundary and document-link checks passed after completing this record/source ledger. |
49
+ | Whitespace/source drift | `git diff --check` and token/generated-theme/lockfile drift checks passed. |
50
+
51
+ The native textarea keeps omitted `rows` at the DOM default of two, vertical resizing, visible label/help/error links, Enter/newline behavior, required validation and editable invalid recovery. Native same-name radios were keyboard/click exercised and submitted through FormData alongside Select; action buttons and `aria-pressed` toggles remain distinct. Tabs checks cover horizontal automatic and controlled vertical/manual activation, disabled skipping, Home/End/loop override, matching roles/IDs, default unmount/draft reset, explicitly hidden force-mounted state retention and packed RTL navigation. There is no invented initial selected value.
52
+
53
+ ## Corrected findings and rendered evidence
54
+
55
+ Initial runs reproduced a literal escaped newline in the read-only example, focus clipping when a localized tab exceeded its local scroll viewport, and long-word panel overflow under enlarged text. The example now uses an actual newline. Individual triggers are capped to list width and may wrap/grow above density minima; the list stays on one scrolling keyboard axis. Panels break long words. Complete accessible names and visible focus are retained without shrinking text. The guide describes 40/36px minimum heights and a 44px mobile/coarse minimum, rather than fixed single-line geometry.
56
+
57
+ Rendered checks also exposed an inactive `border-transparent` utility overriding the active selection border; inactive transparency moved to shared component styles so the neutral active border renders while consumer utility overrides remain available. Explicit `leading-normal` prevents Tailwind's text utility from replacing the required 25px control line height. Final focused and full-suite runs above include these corrections.
58
+
59
+ Across both engines, themes and densities, rendered selected-tab text measured 13.28–13.46:1, selection border against selection 12.01–12.20:1 and against canvas 13.69–15.53:1. Textarea text measured 15.11–17.17:1, placeholder 5.71–8.07:1, normal/error boundaries at least 3.03:1 and focus outlines at least 5.83:1. These are actual opaque computed-color measurements; disabled-opacity styles are not treated as readable metadata.
60
+
61
+ Extension axe scans reported zero violations. Their retained incomplete results comprise 16 `bypass` records for isolated story documents without application landmarks/headings and eight `color-contrast` records for partially occluded inactive tabs in the local scroll region. These are not erased or counted as automatic passes: application skip-navigation remains consumer-owned, and selected/control contrast is separately computed and inspected. Axe does not establish screen-reader announcement quality or complete offscreen-content contrast coverage.
62
+
63
+ Actually opened and visually inspected final captures: Chromium light/comfortable desktop Tabs, Chromium dark/compact desktop Tabs; WebKit light/comfortable and dark/compact invalid Textarea; Chromium dark/compact 320px Tabs and WebKit dark/compact 320px Textarea; Chromium forced-colors Tabs and invalid Textarea; packed WebKit 390px extension form/RTL tabs and Chromium blocked-font fallback; actual built manager Tabs Docs in Chromium and Textarea Docs in WebKit. They show restrained neutral selection, wrapped multilingual labels, distinct invalid text/boundaries, visible focus, locally scrolling tab content and stacked mobile actions. Native textarea content may scroll within its chosen rows. Other captures are retained but not claimed as individually visually inspected.
64
+
65
+ Full logs, browser HTML report/JSON attachments and captures were retained privately. They are neither npm payload nor checked-in evidence; this dated command/source record and the reproducible commands above identify the verified scope. No remote CI result, hosted preview, npm publication or website deployment is claimed.
66
+
67
+ ## Source identities
68
+
69
+ SHA-256 values below identify the tested runtime, examples and verification inputs. This report does not hash itself; the final private freeze inventory additionally covers every scoped changed file and packed artifact. Later documentation-only integration must identify its own tested commit/results rather than relabeling this runtime evidence.
70
+
71
+ | Tested source | SHA-256 |
72
+ | --- | --- |
73
+ | `src/components/ui/tabs.tsx` | `f1a3cad395afa0ce62e0aff7e7342ed6fff112fc4f14480ebecf9038fef1e289` |
74
+ | `src/components/ui/textarea.tsx` | `3a4e0363fe83e53795e0cd6a0ed9800392862015240ae62f1cc588fdf334865b` |
75
+ | `src/components/ui/index.ts` | `2c2ef2e6953d25c400a8bd5855bf29df6658452a6cba59712324675d4d13512b` |
76
+ | `src/styles/components.css` | `fa9ee1e1b96838471f4e9421ada70cb1253987d1417bd3d1e04d385abc37b4b0` |
77
+ | `src/stories/extension-examples.tsx` | `097736d45caf3d9c429af0f1dc10a54cc19739f50f7530f2330c301a99746e56` |
78
+ | `src/components/ui/tabs.stories.tsx` | `6e5567c898a3f9ebb1caf81f5507afbf0f394e7ea2bf21d2cdca838dad97546a` |
79
+ | `src/components/ui/textarea.stories.tsx` | `85eed758be89aacec89d6c3db1f03c174f043d590b4022552dc09254e3ed27f9` |
80
+ | `src/lib/design/__tests__/extension.test.ts` | `b6dfebe0eea5e01a6ca61f659d704660131d709d42d63123a7be37ddda06ca31` |
81
+ | `e2e/extension.spec.ts` | `7952a7bdab421789ce8f24dc1101db12bbee0ee50c37e9e42988f08871bc96c8` |
82
+ | `e2e/component-usage.spec.ts` | `3cc6c7308a083acc472647d6d3d6783b58618b51311ba67987b78b9dea658899` |
83
+ | `examples/react/src/App.tsx` | `30a2f8d3ccf763693d6250f2f04c5f1ce1c726e5d08203410c0c2425a36d8f75` |
84
+ | `scripts/fixtures/next/app/page.tsx` | `4aea9477428076b8a84f610c5a34e767ffd147aafa9025ecf7491f712b9b0ce9` |
85
+ | `scripts/check-consumer-browser.ts` | `f996fffa3bc3be008f39e0f9939146fc67571e0c6c94f5ff90bd122ee7c8a5eb` |
86
+ | `scripts/check-consumers.ts` | `a255263ed81cce4131d4d53c403347117e0c1c41b4443efb47ae833a922ee165` |
87
+ | `scripts/check-package.ts` | `3563e55d58a6320c829fc78b8b12e34a3c5eb5da44981823a38a1432ba58c4ec` |
88
+ | `scripts/check-storybook.ts` | `c37e3a71c5f0fc97176e69505a34c06d2131d9007fe7f2295db5ab55c1b82a5a` |
89
+ | `scripts/check-contrast.ts` | `1ffa7b157cf5b4fd675075b08dc6c3262aa80cbf47ee36bc3a6540e53e795a89` |
90
+ | `package.json` | `4a9eef65a9481ae89cbe685c4f943ac72a28b42559dfb1970079eae8851b4ee1` |
91
+ | `tsup.deep.config.ts` | `9ea59bc77b1a5ef0ca13b15c8f047f12166107f480b952b1bfed316111767497` |
92
+ | `tsconfig.build.json` | `96879c865714d3eae2c8551afd5fcc7519cc4673e2275bd3de88296da9bef6d0` |
93
+ | `docs/components/composition.md` | `62a7b8f799e555099385e79f2f51daf5c89720c0406a9dbe3e8152072f2c04de` |
94
+ | `docs/design/component-demand.md` | `0b36339d49f3cea5e613681f8a3272feae4872440508e81d67608ec315ed13f1` |
95
+
96
+ Installed Radix Tabs 1.1.13 `dist/index.js` SHA-256: `07fc8818ac9e6968155e50eec2ff16f89330cda1034b56b3b91edc606760fb78`; `dist/index.d.ts`: `7a14bf21ae8a29d64c42173c08f026928daf418bed1b97b37ac4bb2aa197b89b`. These are the installed files inspected for primitive defaults/forceMount semantics, not a claim of new copied visual code. Repository frontend-reference-workflow revision 2026-10-02.1 entry SHA-256: `ecada9f24d5ebbce5ac207d5225200ca2d76d08ea9f9f1d3b46d4e956a17d7b8`; its verification guidance: `b504804320724354584885782fe5522ca002028e647b3e146743649cb0a50efe`.
97
+
98
+ ## Remaining limits
99
+
100
+ Local Firefox's inherited `Could not find profile folder` launch block was not freshly rerun for Stage 4; no Firefox application pass is claimed. CI retains all three configured engines, which is not evidence of a remote passing run. Actual Safari, NVDA/VoiceOver or other assistive technology, physical iOS/Android, actual Windows high contrast and native desktop 200%/400% zoom remain manual. 320px/390px viewports, 200% CSS root-text scaling, CSS zoom and Chromium forced-colors media emulation are bounded substitutes, not those manual acceptances. No physical IME session, every locale/glyph/peer version or consumer-specific route/draft behavior is certified. Site-art rights findings carried forward in existing notices remain unresolved; excluding website assets does not clear their rights.
101
+
102
+ ## Documentation-only link follow-up — 2026-10-02
103
+
104
+ The full-runtime results and source hashes above belong to the tested implementation frozen at **`81fd395031dc5b20074c4d915a8585360ce2d28a`**. This later destination-only pass pins maintained repository navigation/source-authority links and the Storybook guide URL base to that exact commit. Original upstream/historical URLs, canonical repository/homepage links, Stage 3 evidence and all component runtime/style/API/dependency/export contracts remain unchanged. The original demand SHA-256 `0b36339d49f3cea5e613681f8a3272feae4872440508e81d67608ec315ed13f1` and composition hash in the original table still identify their **81fd** bodies; they are not replacement hashes for this follow-up.
105
+
106
+ Rendered inspection initially found 84 unresolved sibling Markdown link instances across 26 Docs pages: the existing formatter handles `./`, `../` and `common.md`, while bare names such as `composition.md` remained relative to the preview server. Affected sibling destinations now use explicit `./` paths; the formatter's behavior is unchanged. Future release policy requires versioned navigation/source links to the tested revision and rebuilt Docs/tarball target verification.
107
+
108
+ Scoped final checks: rebuilt Storybook passed **13 Docs + 13 Usage** and the existing notices/fonts/site-asset boundary; **26 rendered Docs tests passed** in Chromium/WebKit. Separate actual DOM inspection checked 288 pinned repository link instances (22 distinct destinations) across those 26 pages, with zero unresolved local Markdown or wrong-revision targets. Static inspection checked 26 maintained commit destinations and 129 relative destinations; every pinned target exists in the exact local Git tree. This establishes source identities, not remote HTTP availability before the commit is pushed. Actual new Tabs Docs/Chromium and Textarea Docs/WebKit captures were opened and inspected. Types passed; lint had zero errors and the inherited blog warning; whitespace and unchanged-runtime checks passed. A fresh packed-guide boundary check passed after this record was completed. Original broad browser, units/contrast and clean-consumer results were not rerun or relabeled for link destinations; their prior source binding and manual/environment limits remain in force.
109
+
110
+ Reproduce the affected rendered/packed checks from the follow-up source:
111
+
112
+ ```sh
113
+ pnpm build:storybook
114
+ pnpm exec playwright test e2e/component-usage.spec.ts --grep 'actual built Docs guide' --project=chromium --project=webkit
115
+ pnpm check:types
116
+ pnpm lint
117
+ pnpm check:package:boundary
118
+ git cat-file -e 81fd395031dc5b20074c4d915a8585360ce2d28a:src/components/ui/tabs.tsx
119
+ git cat-file -e 81fd395031dc5b20074c4d915a8585360ce2d28a:CONTRIBUTING.md
120
+ git diff --check
121
+ ```
122
+
123
+ For each maintained destination, inspect its Docs anchor `href` and use `git cat-file -e COMMIT:PATH` as illustrated above to check that exact target; relative repository/tarball links must resolve within their respective payload. Full per-file replacement hashes, DOM target inventories, check logs, packed artifact and captures were retained privately in a separate follow-up inventory. Key replacement source identities are below; the report does not hash itself. No publication, deployment, remote CI, Firefox or new manual acceptance pass is claimed.
124
+
125
+ | Follow-up source | Replacement SHA-256 |
126
+ | --- | --- |
127
+ | `docs/design/component-demand.md` | `e91aa9fa452620a1bb50e37bf24bf9856454b2bd46bf2440ee4374c5b338b0fc` |
128
+ | `docs/components/composition.md` | `6e034cb2f47d0dcdc360cac326114cd61fc443504aea2757a041eb8c465c40da` |
129
+ | `src/stories/guide.ts` | `74f093522a08c7059f464f47d9bf053b0e571c5864efb325637a190723668409` |
@@ -0,0 +1,42 @@
1
+ # Public UI support and manual acceptance
2
+
3
+ This support matrix targets published `@naeil/ui@0.3.0` (2026-10-03); see [registry/clean-consumer evidence](https://github.com/naeil-dev/naeil-ui/releases/download/v0.3.0/npm-publication-verification.json) and the [release](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.3.0) for npm identity and [live Docs](https://naeil-dev.github.io/naeil-ui/) deployment. Current documentation covers 13 families. This matrix describes the current examples/checks, not every consumer or every allowed dependency version. [Dated Stage 3 results](public-ui-stage3-verification.md) identify commands, source hashes and local limitations. [Stage 4 extension results](public-ui-stage4-verification.md) separately cover Tabs/Textarea and native field/choice composition.
4
+
5
+ Linux CI at `bcf99fca3467ae2b1cd29d54fa24f2569fb6001c` passed package-and-site in both the [push run](https://github.com/naeil-dev/naeil-ui/actions/runs/36945564443) and [PR run](https://github.com/naeil-dev/naeil-ui/actions/runs/36945943651). Their browser jobs failed: respectively 207 passed/4 skipped/2 failed (axe scan collision and Avatar Docs ambiguity), and 208 passed/4 skipped/1 failed (Avatar Docs ambiguity). Firefox application tests passed in both Linux runs. These failed baseline results remain historical evidence in the [final correction follow-up](public-ui-final-verification.md).
6
+
7
+ The corrected source `9f90493abb4fb1186c948084026c3f4c04074013` passed independent scoped review with no actionable findings and both actual Linux workflows: [push](https://github.com/naeil-dev/naeil-ui/actions/runs/36948276767) and [PR](https://github.com/naeil-dev/naeil-ui/actions/runs/36948280881). The PR browser suite passed **209 tests with 4 expected forced-colors skips** (two each in Firefox/WebKit); package-and-site and optional helper checks also passed. Root verified the downloaded PR Storybook artifact and its `/naeil-ui/` navigation/fonts in Chromium/WebKit. This evidence applies to that exact source; [merged PR checks](https://github.com/naeil-dev/naeil-ui/pull/1/checks) retain the release-preparation checks. Subsequent documentation changes require their own verification. Review/CI acceptance applies to its recorded source and does not complete native/manual platform coverage. Publication completed separately on 2026-10-03; unrun checks remain limitations rather than completed results.
8
+
9
+ Fresh npm-registry installs in clean-cache React/Next apps passed types/build, production fonts and blocked-font fallback, mixed-import ownership/StrictMode, Chromium/WebKit Tabs/Textarea contracts and Next 16.1.7 root/deep prerender; the [publication receipt](https://github.com/naeil-dev/naeil-ui/releases/download/v0.3.0/npm-publication-verification.json) gives their scope. The development overlay replay probe retains 34 Vite font allowlist warnings; it certifies overlay replay only, and font success applies to production. These fixtures do not establish adoption in a real consumer product.
10
+
11
+ | Environment / capability | Contract and evidence |
12
+ | --- | --- |
13
+ | React / ReactDOM | Host React 19; clean packed fixture uses 19.2.3 with library type checks enabled. |
14
+ | Styling | Tailwind 4 source scanning plus shared globals or theme + components CSS. Clean React production CSS/JS and actual browser fixture are checked. |
15
+ | Next compatibility | Optional Next 15/16 and next-intl 4 peers; separate clean fixture checks Next 16.1.7/next-intl 4.8.3. This is not every peer-version combination. |
16
+ | Chromium | Actual local checks and 71 application tests passed in the corrected Linux PR run above; exact local build is in dated evidence. This does not certify every Chromium version. |
17
+ | Native Safari / VoiceOver | The [2026-10-02 native environment report](public-ui-release-validation.md) records SafariDriver session creation blocked by “Allow remote automation”, Accessibility trust `false` and AppleEvents `-1744`. VoiceOver was not run; no native component, heard-announcement or human usability pass was obtained. |
18
+ | Playwright WebKit | Actual local checks and 69 application tests passed in the corrected Linux PR run, with 2 expected forced-colors skips. It is not installed Apple Safari certification. |
19
+ | Firefox | 69 Linux application tests passed in the corrected PR run, with 2 expected forced-colors skips; the full CI run passed. The [2026-10-02 native environment report](public-ui-release-validation.md) records two bounded local Firefox attempts failing before the application with `Could not find profile folder`; an isolated explicit profile did not resolve the launch block. This does not certify every Firefox version or resolve the local launch block. |
20
+ | Mobile | 320/390 CSS-pixel viewports, responsive controls/content and screenshots. Emulation is not physical iOS/Android device testing. |
21
+ | Scaling / zoom | Separate 320px viewport, 200% CSS root text scaling and 200% CSS zoom probes; native desktop browser zoom remains manual. No CDP pinch claim. |
22
+ | Forced colors | Chromium media emulation with control/focus/state checks. Actual Windows high contrast, Firefox forced colors and WebKit forced colors remain manual/unrun. |
23
+ | Fonts | Storybook and the independent consumer deliver local Pretendard and Noto Sans JP with OFL notices. Explicit loaded-face probes check representative Korean/Latin/Japanese; they do not certify every glyph/weight. Deliberate blocked-font checks verify readable fallback. |
24
+ | Accessibility | Axe WCAG 2/2.1/2.2 A/AA scopes plus keyboard/state checks including open overlays. Screen-reader announcements and real assistive technology remain manual. |
25
+ | Motion | Shared reduced-motion emulation, overlays and toast loading checked. Custom consumer motion needs separate checks. |
26
+
27
+ The public API surface is the exact manifest allowlist. [Component guides](../components/README.md) and the [consumer migration guide](v2-migration.md) explain defaults, overrides and consumer-owned labels/errors/state.
28
+
29
+ ## Native observations and remaining manual coverage
30
+
31
+ The [dated native environment report](public-ui-release-validation.md) records actual capability probes at source `79d9382f62166e99eeb26c785e690bf90cbb5379`. All native/manual acceptance rows remain open, including native 200%/400% page zoom, VoiceOver listening, physical devices and Windows checks. Its HTTP byte checks establish local artifact delivery only. No native layout, rendered font selection or component pass is claimed.
32
+
33
+ Record actual OS, browser/version, assistive technology, result and evidence for each check; do not check boxes based on axe or installed tooling. Native Safari browser observations, VoiceOver configuration or automation, heard screen-reader announcements, native zoom and human certification are distinct evidence categories. A browser automation pass or enabled assistive technology is not proof of a human listening pass. The dated automated reports above make no native/manual completion claim; any separate release observations must state their own scope and retain unrun items. The checks below describe remaining coverage to assess, not a new publication approval requirement.
34
+
35
+ - Use NVDA with Windows Firefox/Chromium and VoiceOver with actual Safari. Hear labels/descriptions, errors, switch checked state, checkbox mixed state, selected language, dialog title, selected tab/panel, textarea label/help/error, native radio selection and toast outcomes once; verify appropriate live regions and focus return.
36
+ - Use native desktop browser zoom at 200% and 400% and OS text enlargement. Check 320 CSS-pixel equivalent reflow, clipped labels, dialogs with long content and persistent recovery controls; do not substitute pinch/CSS zoom for this acceptance.
37
+ - Use actual Windows high contrast themes. Confirm text, input boundaries, focus outlines, switch thumb/track and checked/mixed indicators remain distinguishable, including disabled states, selected tab borders and textarea invalid boundaries.
38
+ - On physical iOS Safari and Android Chrome, check keyboard opening, native input zoom, 44px targets, choice-target hit areas and lack of adjacent overlap, scrollable overlays and portrait/landscape.
39
+ - Check keyboard-only consumer flows after overriding classes/focus/outside handlers. Keep Tab order logical, modal focus inside, Escape available, and focus returned to an appropriate action, including triggerless/removed-trigger compositions.
40
+ - Test font failure/offline/slow loading, long Korean/English/Japanese and product-specific errors/loading/empty/retry with real data. Confirm persistent errors/recovery do not disappear with a toast.
41
+
42
+ The automated implementation evidence does not complete screen-reader listening, physical-device, native Safari or Windows acceptance. Separate native release observations must not be inferred from Playwright WebKit, CSS zoom or accessibility snapshots. Publishing the package, hosting Docs, merging main and deploying the brand website are separate operations; a release does not close unrun checks.
@@ -0,0 +1,229 @@
1
+ # 공통 UI v2 사용 및 이전 안내
2
+
3
+ 이 안내는 `@naeil/ui`의 기본 모양과 재사용 규칙을 설명한다. 패키지 소비와 소비 사이트 배포는 별도 작업이다.
4
+
5
+ 이 안내는 **@naeil/ui 0.4.0**의 CSS·API·패키지 경계를 대상으로 한다. UI v2는 디자인 세대 이름이며 npm 2.0을 뜻하지 않는다. 기존 npm 0.2.0에 이 기능이 모두 구현됐다고 가정하지 않는다. Registry의 게시 여부와 latest 태그는 별도로 확인한다.
6
+
7
+ ## 시작하기
8
+
9
+ React 19/ReactDOM 19와 Tailwind 4 앱에서 `/ui`를 사용한다. API 키와 Next.js는 필요 없다. 소비 앱에서 정확한 버전을 지정한다.
10
+
11
+ ```sh
12
+ pnpm add --save-exact @naeil/ui@0.4.0
13
+ # npm install --save-exact @naeil/ui@0.4.0
14
+ ```
15
+
16
+ 이 명령은 해당 버전이 registry에 있을 때 사용할 수 있다. 게시 전 소스 검증은 저장소에서 `pnpm build:pkg` 후 `npm pack --ignore-scripts --pack-destination /tmp`를 실행하고, 소비 앱에 `/tmp/naeil-ui-0.4.0.tgz`를 설치한다. [독립 React 예제](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/examples/react/README.md)와 [검증/릴리스 정책](../package-release.md)을 참고한다.
17
+
18
+ 공통 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 의존성과 코드는 공통 소비 경계에서 제외했다.
19
+
20
+ 버전을 생략한 설치는 registry의 latest 태그를 따른다. 이 안내와 동일한 경계를 사용하려면 0.4.0을 지정하고 [변경 기록](../../CHANGELOG.md)을 확인한다.
21
+
22
+ Tailwind 4를 사용하는 앱의 전역 CSS에서 공통 스타일을 한 번 불러온다.
23
+
24
+ ```css
25
+ @import "@naeil/ui/globals.css";
26
+ /* 소비 앱의 Tailwind 빌드가 패키지의 클래스도 찾도록 등록한다.
27
+ 경로는 이 CSS 파일의 위치를 기준으로 조정한다. */
28
+ @source "../node_modules/@naeil/ui/dist";
29
+ ```
30
+
31
+ 이미 Tailwind와 기본 스타일을 구성한 앱은 `@naeil/ui/theme.css`와 `@naeil/ui/components.css`를 함께 불러올 수 있다. 컴포넌트 CSS에는 크기·포커스·밀도·포털·reduced-motion 규칙이 있으므로 theme.css만으로 전체 v2 모양이 완성되지는 않는다.
32
+
33
+ ```tsx
34
+ import { Button, Input, Select, SelectTrigger, SelectValue,
35
+ SelectContent, SelectItem, Switch, Checkbox } from '@naeil/ui/ui';
36
+
37
+ <label htmlFor="language">언어</label>
38
+ <Select name="language" defaultValue="ko">
39
+ <SelectTrigger id="language"><SelectValue /></SelectTrigger>
40
+ <SelectContent>
41
+ <SelectItem value="ko">한국어</SelectItem>
42
+ <SelectItem value="en">English</SelectItem>
43
+ </SelectContent>
44
+ </Select>
45
+ ```
46
+
47
+ Select는 값 선택, DropdownMenu는 행동 선택에 사용한다. Switch와 Checkbox는 보이는 label과 연결하고, 여러 선택 항목의 클릭 영역이 겹치지 않도록 최소 44px 행과 여유 간격을 둔다. `ui-choice-label`을 사용할 수 있다.
48
+
49
+ ## 기본 규칙
50
+
51
+ - 본문·입력·버튼 16px, 보조 14px, 메타정보 13px. 작은 화면에서도 입력 글씨를 줄이지 않는다.
52
+ - 기본 컨트롤 높이 40px. 문서 루트에 `data-ui-density="compact"`를 주면 36px가 된다. 작은 화면과 거친 포인터에서는 최소 44px를 유지한다. 데스크톱에서 `className="h-8"` 같은 높이 재정의는 적용되며, 모바일의 44px 최소 터치 크기는 유지된다.
53
+ - `.light`/`.dark`는 OS 테마보다 우선한다. 기존 ThemeProvider를 사용할 수 있다.
54
+ - `data-ui-layout="reading|settings|list|short-form|fluid"`로 콘텐츠 폭을 적용한다. 각각 최대 640/640/1200/480px 또는 가용 폭이다. 이 속성은 전체 앱의 레이아웃을 강제하지 않는다.
55
+ - 레이블·도움말·오류 문구는 소비 화면이 연결한다. Input의 `aria-invalid`와 `aria-describedby`를 사용하고, 로딩 중에는 Button의 `disabled`와 `aria-busy`를 함께 지정한다.
56
+ - 성공·경고·오류·안내에는 Badge의 `success`, `warning`, `error`, `info` variant를 사용할 수 있다. 색만으로 의미를 전달하지 않는다.
57
+
58
+ ## 앱 전체 틀과 콘텐츠 폭
59
+
60
+ 앱의 공통 헤더·메뉴·좌우 여백과 본문의 읽기/설정/목록 폭은 별도로 관리한다. 같은 앱 틀을 사용하는 페이지는 같은 화면 크기·언어·테마에서 메뉴 위치가 유지되어야 한다. 설정 폼을 640px로 제한할 때 헤더까지 그 폭에 종속시키지 않는다. 변동하는 계정 수·상태 요약도 메뉴를 밀어내지 않도록 배치한다.
61
+
62
+ 아래는 소비 앱의 구성 예이며 새 패키지 API가 아니다. `product-frame`과 최대 폭·여백은 제품에서 소유하고 정한다. 공통 숫자 토큰은 `src/tokens/*.json`을 기준으로 한다.
63
+
64
+ ```tsx
65
+ <>
66
+ <header>
67
+ <div className="product-frame"><ProductNavigation /></div>
68
+ </header>
69
+ <main className="product-frame">
70
+ <section data-ui-layout="settings">{/* 설정 폼 */}</section>
71
+ </main>
72
+ </>
73
+ ```
74
+
75
+ ```css
76
+ /* 제품이 결정한 --product-frame-max, --product-gutter를 사용한다. */
77
+ .product-frame {
78
+ box-sizing: border-box;
79
+ width: 100%;
80
+ max-width: var(--product-frame-max, 100%);
81
+ margin-inline: auto;
82
+ padding-inline: var(--product-gutter, 0);
83
+ }
84
+ ```
85
+
86
+ 대시보드라는 이유만으로 전체 폭을 쓰거나, 다른 제품의 1600px를 공통 기준으로 가져오지 않는다. 실제 과업·정보량·짧은/긴 내용으로 폭을 판단한다. 내부 카드·보고서 열 수는 모니터 폭보다 실제 콘텐츠 영역 폭에 맞춘다. 필요한 경우 container query를 사용한다.
87
+
88
+ 레이아웃 수정의 검증 기준:
89
+
90
+ - 주요 경로를 같은 조건에서 비교한다. 메뉴 좌표와 여백, 제목·행동의 정렬을 확인하고 의도적인 차이는 이유를 남긴다.
91
+ - 제품이 지원하는 언어, 긴 이름, 적은/많은 데이터, 영향을 받는 로딩·오류 상태를 포함한다. 공유 컴포넌트 예시는 기존 한글·영문·일문 기준을 유지한다.
92
+ - 페이지 넘침과 함께 표 내부 잘림·줄바꿈·조작 영역을 확인한다. 내부 스크롤 자체를 페이지 넘침과 혼동하지 않는다.
93
+ - 기능 검사, 공통 기준 준수, 실제 화면 구성을 별도로 기록한다. 기존 대비·중첩 조작·터치 크기 문제는 현재 증거가 생기기 전까지 미해결로 남긴다.
94
+
95
+ 복사한 CSS를 사용하는 소비 앱은 원본 리비전·수정 사항·동기화 책임을 기록한다. 공통 패키지 직접 사용과 같은 수준의 자동 반영을 주장하지 않는다.
96
+
97
+ ## 폰트
98
+
99
+ 공통 CSS는 외부 서버에서 폰트를 자동 다운로드하지 않는다. 소비 앱이 Pretendard를 직접 호스팅하거나 자신의 로더로 전달한다. 일본어에는 Noto Sans JP를 제공하고 필요한 글자/굵기만 로드한다. 로딩 실패 시 시스템 글꼴로 표시된다.
100
+
101
+ 소비 앱에서 로컬 번들 폰트를 사용하려면 다음과 같이 설치하고 앱 진입점에서 필요한 굵기를 불러올 수 있다.
102
+
103
+ ```sh
104
+ pnpm add --save-exact pretendard@1.3.9 @fontsource/noto-sans-jp@5.3.0
105
+ ```
106
+
107
+ ```tsx
108
+ import 'pretendard/dist/web/static/pretendard.css';
109
+ import '@fontsource/noto-sans-jp/400.css';
110
+ import '@fontsource/noto-sans-jp/500.css';
111
+ import '@fontsource/noto-sans-jp/600.css';
112
+ ```
113
+
114
+ 일본어 영역에 `lang="ja"`를 지정하면 globals의 일본어 font-family 규칙이 적용된다. 재배포 빌드에는 [폰트 OFL 고지](../../THIRD_PARTY_NOTICES.md#fonts)를 유지한다. 패키지 자체에는 폰트 런타임 의존성을 추가하지 않았다.
115
+
116
+ Storybook의 로컬 폰트 import는 예시다. 그대로 앱 전역에 모든 굵기·언어 폰트를 복사할 필요는 없다. 폰트를 바꾸면 줄바꿈과 밀도를 다시 확인한다. 코드용 폰트는 기존 fallback 체계를 유지한다.
117
+
118
+ ## 바뀌는 점과 호환성
119
+
120
+ 기존 root, `/ui`, `/utils`와 공통 컴포넌트 이름을 유지한다. 깊은 경로는 아래의 명시적 허용 목록에 있는 공통/호환 모듈만 배포된 JS와 타입으로 연결한다. 열린 wildcard 선언은 제거하며, 사이트 전용 경로별 이전 방법을 아래 표에 기록했다. Select·Switch·Checkbox와 `/components.css`는 추가 API다.
121
+
122
+ 기본 색·글자·컨트롤 크기·모서리·움직임이 바뀐다. 기존에 작은 높이를 가정한 고정 레이아웃은 확인해야 한다. Button의 기존 size 이름은 유지하되 v2의 읽기/터치 기준에 맞춘다. 명시적인 `className`은 소비 화면이 책임지는 예외이며 너무 작은 높이나 낮은 대비로 기본 규칙을 깨지 않도록 한다.
123
+
124
+ 공통 globals에서 사이트 전용 float 애니메이션을 분리했다. 저장소의 사이트는 로컬 `src/app/globals.css`에서 이를 계속 정의한다. 다른 소비자가 `animate-float`에 의존했다면 자기 사이트 스타일로 명시적으로 옮긴다.
125
+
126
+ ## 개별 컴포넌트 안내
127
+
128
+ [13개 사용 안내](../components/README.md)는 실제 wrapper API·기본값, 키보드, 상태, 레이블·오류 연결, 재정의 책임을 설명한다. Storybook의 각 `UI / 컴포넌트 / Docs`와 `Usage`에서 같은 안내와 실행 예시를 확인한다. [지원 범위와 수동 점검](public-ui-support.md)은 자동 검사와 실제 보조 기술·운영체제 검증의 차이를 기록한다.
129
+
130
+ ## 확인 방법
131
+
132
+ - `pnpm storybook`: 실제 공개 컴포넌트의 `UI v2 / Workspace` 화면.
133
+ - `pnpm build:tokens`, `pnpm check:contrast`: 실제 배포 CSS와 대비 확인.
134
+ - `pnpm test`, `pnpm build:storybook`, `pnpm test:browser`: 규칙, 키보드, 상태, 모바일, 자동 접근성 확인.
135
+ - `pnpm build:pkg`, `pnpm check:package`: 실제 tarball 경계와 독립 React/Next 소비 예시 확인.
136
+
137
+ 자동 검사와 HTML 시안만으로 모든 소비 화면의 품질을 보장하지 않는다. 실제 앱에서 긴 문장·테마·포커스·오류 상태를 확인한다. DESIGN.md의 선택한 방향을 우선하고 외부 예시는 부족한 부분만 보완한다.
138
+
139
+ ## 0.3 package boundary
140
+
141
+ `/ui` is the React core. Root imports preserve Nav, Footer, Logo, LocaleSwitcher, ThemeProvider, ThemeToggle, ThemeToggleIcon, PageTitle, SectionTitle and their class helpers, but root has static Next/next-intl dependencies. React-only apps must use `/ui`, `/utils` and appropriate shared deep modules. `next-themes` is a React runtime library; it does not require Next.js. Fonts remain consumer-owned.
142
+
143
+ Next.js `^15 || ^16` and next-intl `^4` are optional peers. Install both when using root, Nav, Footer or `i18n/routing`. This is an existing compatibility contract, not a claim that every peer combination has browser validation; the clean Next fixture checks Next 16.1.7. React/ReactDOM `^19` come from the host. Tailwind 4 is the documented styling pipeline. Explicit `className`, Radix props, Toaster options and theme-provider props remain consumer overrides.
144
+
145
+ The compiled deep import allowlist is exact (prefix each with `@naeil/ui/`):
146
+
147
+ ```text
148
+ components/index
149
+ components/ui/index
150
+ components/ui/avatar
151
+ components/ui/badge
152
+ components/ui/button
153
+ components/ui/card
154
+ components/ui/checkbox
155
+ components/ui/dialog
156
+ components/ui/dropdown-menu
157
+ components/ui/input
158
+ components/ui/select
159
+ components/ui/sonner
160
+ components/ui/switch
161
+ components/ui/tabs
162
+ components/ui/textarea
163
+ components/nav
164
+ components/footer
165
+ components/logo
166
+ components/locale-switcher
167
+ components/theme-provider
168
+ components/theme-toggle
169
+ components/theme-toggle-icon
170
+ components/typography
171
+ lib/utils
172
+ i18n/config
173
+ i18n/routing
174
+ ```
175
+
176
+ `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.
177
+
178
+ 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:
179
+
180
+ | Previously declared source path | Ownership/migration |
181
+ | --- | --- |
182
+ | `components/nav-wrapper`, `components/nav-server-wrapper` | Compose preserved Nav and its slots in your app; your app loads users/sessions. |
183
+ | `components/footer-wrapper` | Compose preserved Footer with your app's Link. |
184
+ | `components/auth-slot` | App-owned account UI, logout action and avatar policy; pass it through Nav slots. |
185
+ | `components/hero-scene`, `components/hero-section`, `components/paraglider-cursor` | Website scene/cursor source, assets and Three dependencies stay website-owned. |
186
+ | `components/project-layout`, `components/workflow-diagram`, `components/accent-picker` | Website showcase/data/theme editing composition; use shared primitives in product-owned compositions. |
187
+ | `components/blog/MarkdownRenderer`, `lib/blog` | Application-owned content rendering, filesystem and MDX/remark pipeline. |
188
+ | `lib/supabase/client`, `lib/supabase/server`, `lib/supabase/middleware` | Application-owned Supabase clients, environment, cookies and authentication. |
189
+ | `lib/auth/avatar`, `lib/auth/cookie-domain`, `lib/auth/redirect`, `lib/auth/routes` | Application-owned identity, cookie and protected-route policies. |
190
+ | `lib/axe` | Development-only accessibility initialization; configure your own tooling. |
191
+ | `i18n/request` | Application-owned `next-intl/server` request config and messages; keep compatible config/routing only if useful. |
192
+
193
+ npm 0.2.0 declared wildcard source paths but its actual tarball omitted those targets. Repository source aliases and unpublished local builds could nevertheless use them. This explicit migration documents both cases rather than silently treating the broad declaration as a stable working API. Unknown paths now fail at package exports instead of reaching website internals.
194
+
195
+ The reachable Next consumer's observed deep imports (Nav, Footer, ThemeProvider, ThemeToggleIcon, LocaleSwitcher) remain supported. Its old Tailwind `@source` paths scan `src/components`/`src/lib`; update them to `node_modules/@naeil/ui/dist` relative to the consumer CSS file and import shared component CSS. Site assets/messages and authentication are supplied by the application. This repository does not automatically modify or upgrade that consumer. The copied-UI consumer currently uses locally copied primitives, so publishing a new package will not update those copies.
196
+
197
+ ## Demand-led extension
198
+
199
+ Version 0.3.0 also adds `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent` and `Textarea` to `/ui`, plus exact `components/ui/tabs` and `components/ui/textarea` deep entries. Existing root stays the brand/framework barrel. No new dependency or existing default is changed. See the [13-family index](../components/README.md), [Tabs defaults/mount responsibilities](../components/tabs.md), [native Textarea contract](../components/textarea.md), [field/native-radio composition](../components/composition.md), and [demand decision](component-demand.md). Publishing does not update consumers that use locally copied primitives.
200
+
201
+
202
+ ## Brand Logo integration (0.4.0)
203
+
204
+ Version 0.4.0 connects the approved **brand 1.1.1** to the shared components. It is not a claim that npm 0.3.0 already contains the new logo. Package publication and consumer upgrades remain separate.
205
+
206
+ ```tsx
207
+ // React-only, no Next.js peer required for this deep import:
208
+ import { Logo, type LogoProps } from '@naeil/ui/components/logo';
209
+
210
+ <Logo size={32} />
211
+ <Logo variant="horizontal" size={28} />
212
+ <Logo variant="footer" size={20} />
213
+ <Logo tone="gray" size={40} />
214
+ <Logo variant="horizontal" size={28} theme="dark" />
215
+ <a href="/" aria-label="naeil 홈"><Logo size={28} label={null} /></a>
216
+ ```
217
+
218
+ Root and `components/index` continue to export Logo; root still has the existing Next/next-intl compatibility peers. `LogoProps` is also exported. No brand export is added to `/ui`.
219
+
220
+ - `size` remains the rendered height, default 20px. Default `variant="symbol"` remains square. The 16–48px symbol uses the reviewed small artwork; larger symbols use the detailed source. `horizontal`, `footer`, `stacked` and `wordmark` preserve their aspect ratio. Header height 28px and footer height 20px are recommended. For stacked use a minimum height of 140px (160px width).
221
+ - `className`, standard SVG props and consumer style overrides are retained. Avoid stretching width and height independently. Artwork contains paths, not text or external images; Lato installation is unnecessary.
222
+ - `theme="auto"` follows the nearest `.light`, `.dark`, `data-theme="light"` or `data-theme="dark"` ancestor, with OS preference as fallback. It uses embedded SVG CSS and React useId, so SSR markup does not branch on browser state. For strict CSP or manual control, provide `theme="light"` or `theme="dark"`; that form emits no theme style element. Multiple independently hydrated React roots should use distinct React identifierPrefix values as usual.
223
+ - `tone="color"` is default. `tone="gray"` uses the selected grayscale A, including islands. Existing `mono` remains a **single currentColor silhouette** for compatibility; its one-ink shape loses the internal sun/island distinction. It is not the preferred grayscale version or a separately approved print master. `mono` takes precedence over tone/theme colors.
224
+ - Default accessible name is naeil with role=img. Use `label={null}` for decorative use and name the enclosing link/button. `aria-label` and other standard SVG attributes remain consumer overrides.
225
+ - Nav now uses the horizontal wordmark at 28px; Footer uses the footer lockup at 20px. Their official visible spelling remains `.naeil`: the period marks an ending, followed by tomorrow. Nav's `brandSlot`, brandHref, external/internal links, layout frame and other slots are preserved. Check custom layouts on upgrade because the new artwork has a different width.
226
+
227
+ The independent kit lives in the repository's `brand/naeil/1.1.1/` directory with its own usage guide, SVG/PNG/icons, OFL and checksums. Copy it for non-React uses without installing @naeil/ui. It is intentionally not copied into the npm tarball. The package carries only generated React artwork and the [Lato notice](../../licenses/Lato-OFL.txt). A favicon is application-owned: Next file conventions can use the kit's favicon.ico, favicon.svg and apple-touch-icon.png; each consumer chooses its own app manifest and deployment.
228
+
229
+ Maintainers run `pnpm build:brand` after explicitly selecting a reviewed version in `brand/current.json`, then `pnpm check:brand`. Package/Storybook builds check that generated artwork, notices and this site's icon files match that version. Shared color tokens and Pretendard do not change. In Storybook, **Brand / Logo / Docs, Usage, Application** demonstrates the actual adapter, canonical SVG comparisons and Nav/Footer composition.
@@ -0,0 +1,108 @@
1
+ # Package verification and release policy
2
+
3
+ This policy covers `@naeil/ui@0.4.0`; the 0.3.0 publication evidence below is retained as history. UI v2 names a design generation, not an npm major. A 0.x minor increment communicates this dependency/export boundary change; future breaking changes must receive an explicit migration and version decision. The historical registry baseline on 2026-10-02 was npm latest at `0.2.0`; the 2026-10-03 publication evidence below records npm 0.3.0, its GitHub Release and live hosted Docs separately. Version-scoped installation is in the [README](../README.md#use-the-ui).
4
+
5
+ ## Architecture
6
+
7
+ One repository contains the shared package and the separate Next.js brand/example website. `@naeil/ui/ui` is the React entrypoint. The legacy root is a framework compatibility entry with static Next/next-intl imports, even when selecting only Logo or a heading; React-only consumers use the documented shared deep modules. Next and next-intl are optional peers, not optional behavior inside the root. Supply them when importing that entry, Nav, Footer, or i18n/routing. Theme controls and Toaster use the framework-independent React library next-themes, retained as a runtime dependency.
8
+
9
+ 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 application message catalog.
10
+
11
+ ## Checks
12
+
13
+ Use Node 22+ and the pinned pnpm version:
14
+
15
+ ```sh
16
+ pnpm install --frozen-lockfile
17
+ pnpm test
18
+ pnpm check:types
19
+ pnpm lint
20
+ pnpm build:tokens
21
+ git diff --exit-code -- src/styles/theme.css
22
+ pnpm check:contrast
23
+ pnpm build:pkg
24
+ pnpm check:package
25
+ node --test scripts/consumer-font-notices.test.mjs
26
+ pnpm build
27
+ pnpm build:storybook
28
+ pnpm exec playwright install chromium firefox webkit
29
+ pnpm test:browser
30
+ ```
31
+
32
+ `check:package:boundary` inspects an actual `npm pack --ignore-scripts` archive for every declared export, runtime dependencies, source aliases, relative imports, required CSS/tokens/documents/notices and forbidden website payload. `check:consumers` separately installs that tarball with npm into two temporary directories. It builds the reusable React example with Vite/Tailwind, type-checks with library checks enabled, imports shared deep modules, checks SSR and CSS, and asserts Next/Supabase/Three are absent. A separate Next production build exercises root exports and the deep paths observed in the reachable Next consumer, with consumer-owned messages and no auth backend. Neither fixture uses repository dependency symlinks. Network access is needed for uncached npm dependencies; temporary installs are removed on completion or failure.
33
+
34
+ CI runs these checks and a separate actual Storybook/browser job. Configured browser projects run Chromium, Firefox and WebKit in CI. Local Chromium/WebKit results and the Firefox environment launch block are distinguished in the [current support matrix](design/public-ui-support.md) and [dated Stage 3 verification](design/public-ui-stage3-verification.md) and [Stage 4 extension verification](design/public-ui-stage4-verification.md); configured CI is not a recorded remote pass. Automated axe/keyboard checks are not manual screen-reader or native Safari certification. The website build checks compatibility independently from package consumption; fonts fetched through next/font may require network access. Supabase OAuth and deployed behavior remain separate checks.
35
+
36
+ At baseline `bcf99fca3467ae2b1cd29d54fa24f2569fb6001c`, both [push CI](https://github.com/naeil-dev/naeil-ui/actions/runs/36945564443) and [PR CI](https://github.com/naeil-dev/naeil-ui/actions/runs/36945943651) passed package-and-site and failed the browser job. Linux Firefox application coverage passed in those runs. The [final correction follow-up](design/public-ui-final-verification.md) preserves that baseline and the initial local freeze evidence, then records independent scoped review approval and successful [push CI](https://github.com/naeil-dev/naeil-ui/actions/runs/36948276767) and [PR CI](https://github.com/naeil-dev/naeil-ui/actions/runs/36948280881) at exact correction commit `9f90493abb4fb1186c948084026c3f4c04074013`. The PR browser job passed 209 tests with 4 expected Firefox/WebKit forced-colors skips; package-and-site and optional helper checks passed. The downloaded CI preview also passed actual Chromium/WebKit subpath navigation/font checks. This acceptance applies to that source; [merged PR checks](https://github.com/naeil-dev/naeil-ui/pull/1/checks) retain the release-preparation checks. Subsequent documentation changes require their own verification. Publication and manual platform acceptance remain separate.
37
+
38
+ The explicit font-notice regression gate copies the real React fixture config into scratch and installs only its existing Vite/Tailwind-plugin/font dependencies, with scripts disabled. It loads the installed fixture Vite and checks output ownership and exact OFL bytes. Like clean-consumer checks, it requires network for uncached npm dependencies and cleans scratch on failure.
39
+
40
+ ## Publication and deployment
41
+
42
+ ### 0.4.0 release scope — 2026-10-11
43
+
44
+ The user authorized repository integration, npm publication, hosted Docs and naeil.dev deployment for the approved `.naeil` logo. Brand 1.1.1 is independent of npm 0.4.0. Existing imports/props/slots remain supported; new Logo variants, grayscale and theme controls justify a minor package increment. New consumers should use the 0.4.0 instructions above the historical records.
45
+
46
+ Follow the release procedure below with version 0.4.0, freeze and publish the inspected archive, and record actual registry/tag/site/Docs outcomes in the v0.4.0 GitHub Release. Authorization is not itself evidence of publication. The previous Supabase-local-runtime and manual-device limitations remain documented; verify production behavior at its actual URL after Vercel deployment.
47
+
48
+ ### Verified 0.3.0 publication — 2026-10-03
49
+
50
+ - npm published `@naeil/ui@0.3.0` at `2026-10-03T04:14:17.028Z`; `latest` was verified as `0.3.0` that day. [Public machine-readable evidence](https://github.com/naeil-dev/naeil-ui/releases/download/v0.3.0/npm-publication-verification.json) records registry integrity and fresh consumption.
51
+ - [PR #1](https://github.com/naeil-dev/naeil-ui/pull/1) merged as `71464f3985d0146c85087411d1e2f07ddaaaaab0`, with the same tree as independently approved `0d51755160b3d8e986c9b464b123fa4beed2689a`. Tag `v0.3.0` points to the merge commit; the [GitHub Release](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.3.0) retains the reviewed archive.
52
+ - The registry archive matches the reviewed bytes: **105 files**, **453,120 unpacked bytes**, SHA-256 `b71a81b22354f6b7c17610ef9c02650fbd2a84e4309706e311dd62fe32a66d27`.
53
+ - [Hosted Docs](https://naeil-dev.github.io/naeil-ui/) are live following the 2026-10-02 [Pages run 36963256014](https://github.com/naeil-dev/naeil-ui/actions/runs/36963256014). Recorded Chromium/WebKit checks covered all 13 Docs pages, Docs-to-Usage navigation, local fonts and pinned links.
54
+
55
+ Fresh actual npm installs in separate React/Next apps with empty caches passed types and production builds, production font/fallback checks, mixed-import ownership/StrictMode checks, Chromium/WebKit extension contracts and Next 16.1.7 root/deep prerender. The development overlay probe retains 34 Vite font allowlist warnings and certifies overlay replay only; font success applies to production. Publication did not rerun the full CI/browser suite for unchanged reviewed source/runtime bytes. Native/manual coverage and real-product adoption remain open; see [support limits](design/public-ui-support.md).
56
+
57
+ The immutable npm archive's bundled guides are the release-preparation snapshot. Maintained GitHub guides record subsequent publication status; documentation-only changes do not alter npm 0.3.0, its tag or release asset. Hosted Docs reflect their separately deployed source.
58
+
59
+ ### Release procedure
60
+
61
+ The Storybook guide URL base and README documentation index use publication-status documentation snapshot `04c5b8cce145a4c387763db6f28d29e62f7664c7`. Runtime/API source-authority links retain tested component snapshot `81fd395031dc5b20074c4d915a8585360ce2d28a`; that original evidence remains valid and is not replaced by this documentation-only snapshot. Verify targets at their respective pinned revisions and preserve original upstream sources, dated approval scope and runtime evidence. Freeze subsequent documentation changes separately from the immutable 0.3.0 archive.
62
+
63
+ 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.
64
+
65
+ The 0.3.0 publication procedure below preserves the distinction between preparation and external verification; future releases require their own version, authorization and frozen source/archive:
66
+
67
+ 1. Review the changelog, migration, dated verification and the [2026-10-02 native environment report](design/public-ui-release-validation.md). Its capability blockers leave all native/manual acceptance rows open and add no native component pass. Confirm maintained links, actual Storybook Docs/Usage and legal notices for the intended source. Record unresolved manual coverage without inventing passes.
68
+ 2. Build and inspect a fresh archive with `npm pack --ignore-scripts --json --pack-destination /path/to/candidate`; preserve its SHA-256, file list and source revision outside the archive. Run boundary/relative-link checks and clean packed consumers on that candidate.
69
+ 3. Check registry availability for `@naeil/ui@0.3.0` immediately before publication. Publish the verified candidate archive, then verify the registry version, integrity and dist-tag; a changelog or install command alone proves none of these.
70
+ 4. Create the release tag/GitHub Release for the recorded source and retain version, artifact identity, validation scope and support limitations.
71
+ 5. Publish the reviewed Storybook artifact through the manual Pages workflow below. Verify the actual hosted URL, subpath Docs-to-Usage navigation, fonts and notices over HTTP before reporting it live.
72
+
73
+ npm publication, GitHub Releases, main merge and hosted Docs are distinct operations. Production deployment of the brand website remains a separate scope; shared-package checks do not clear unknown site-art or fetched-site-font provenance.
74
+
75
+ `vercel.json` disables Git deployments only for `feat/public-ui-readiness`. Other branches retain Vercel's default behavior, so merging or pushing another branch requires a separate deployment decision. The automatic GitHub Actions checks are verification-only; enabling repository workflows is not evidence of a hosted site or approved release.
76
+
77
+ ## Storybook preview artifact
78
+
79
+ `pnpm build:storybook` builds actual Docs pages and interactive Usage examples for all 13 families. It copies only generated documentation notices, bundles locally installed Pretendard/Noto Sans JP and disables Vite publicDir. The artifact check verifies real Docs/story entries, exact MIT/shadcn/font notices and absence of website public images/SVGs/HTML. It does not claim those excluded site assets have cleared rights.
80
+
81
+ 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):
82
+
83
+ ```sh
84
+ pnpm preview:storybook
85
+ # Or pass the downloaded artifact directory: pnpm preview:storybook /path/to/preview
86
+ # Open http://127.0.0.1:6007 and choose UI / a family / Docs or Usage.
87
+ ```
88
+
89
+ Run the command from this checkout after installing its dependencies. It serves the built or downloaded static artifact with persistent HTTP connections; a conventional static host works as well. Do not open iframe.html directly as a file; use HTTP. Preserve LICENSE, THIRD_PARTY_NOTICES.md and licenses/ with the artifact. The static preview needs no backend, credentials or external font server. Third-party dependency code also retains its own bundled/license notices.
90
+
91
+ ### Authorized GitHub Pages publication
92
+
93
+ The public Docs destination [https://naeil-dev.github.io/naeil-ui/](https://naeil-dev.github.io/naeil-ui/) is live following the 2026-10-02 [Pages run 36963256014](https://github.com/naeil-dev/naeil-ui/actions/runs/36963256014). The [release](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.3.0) records deployed source and hosted HTTP/navigation checks. Pages uses `build_type=workflow` and a **github-pages** main-only deployment branch policy. See [Docs workflow status](https://github.com/naeil-dev/naeil-ui/actions/workflows/publish-docs-manual.yml) for subsequent deployments; preview artifact checks above establish local artifact behavior only.
94
+
95
+ `.github/workflows/publish-docs-manual.yml` is an explicit `workflow_dispatch` recipe with no PR/push trigger. Pages is configured to use **GitHub Actions**; the **github-pages** environment permits deployment from main only. Run the authorized workflow from main with the exact reviewed source SHA; configuration alone does not establish a successful deployment. The workflow file does not enable Pages itself. A default-branch merge can separately invoke the brand site's existing Vercel integration; that production deployment and its asset/font provenance require separate handling.
96
+
97
+ Select **Publish reviewed UI docs (manual only)** in Actions (or use the command below), supply the exact full reviewed source SHA and type `PUBLISH_REVIEWED_DOCS`. The job checks out that SHA, rebuilds/verifies its actual preview/notices, runs the configured three-engine browser suite, and deploys only the Pages artifact through its environment. Failed checks do not reach deploy. Native observations and remaining manual limitations belong in the release evidence; the workflow does not certify them.
98
+
99
+ ```sh
100
+ # Release maintainer: replace with the exact frozen source commit.
101
+ gh workflow run publish-docs-manual.yml -f reviewed_sha=FULL_REVIEWED_COMMIT_SHA -f confirmation=PUBLISH_REVIEWED_DOCS
102
+ ```
103
+
104
+ After deployment, verify the manager and iframe under `/naeil-ui/`, all 13 Docs/Usage entries, Docs links, local fonts and exact LICENSE/THIRD_PARTY_NOTICES/font notices. Retain the deployment URL, source SHA and observed HTTP/navigation results. 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.
105
+
106
+ 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.
107
+
108
+ 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.