@abuzareal/contour-ui 0.5.0 → 0.6.1
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.
- package/CHANGELOG.md +16 -0
- package/COMBOBOX.md +87 -0
- package/COMPOSITION.md +4 -0
- package/CONTRACTS.md +27 -27
- package/DOCS.md +86 -0
- package/FORMS.md +4 -0
- package/FOUNDATION.md +35 -0
- package/GETTING-STARTED.md +67 -0
- package/HELPERS.md +33 -0
- package/HOOKS.md +67 -0
- package/MANUAL-QA.md +38 -0
- package/MIGRATION.md +44 -0
- package/MODELS.md +18 -0
- package/NEXTJS.md +3 -1
- package/OVERLAYS.md +4 -0
- package/PROP-REFERENCE.md +37 -0
- package/PUBLIC-API.md +174 -164
- package/README.md +9 -5
- package/RECIPES.md +43 -0
- package/REFERENCE.md +193 -0
- package/RELEASING.md +8 -2
- package/SIZE.md +9 -3
- package/STYLING.md +4 -0
- package/SUPPORT.md +36 -0
- package/THREE.md +40 -0
- package/dist/components/ui/Combobox.d.ts +325 -0
- package/dist/components/ui/Combobox.js +135 -0
- package/dist/components/ui/Combobox.types.d.ts +46 -0
- package/dist/components/ui/Combobox.types.js +1 -0
- package/dist/components/ui/DataTable.js +5 -4
- package/dist/components/ui/Field.js +1 -1
- package/dist/components/ui/FloatingPortal.js +2 -40
- package/dist/components/ui/FloatingScope.d.ts +9 -0
- package/dist/components/ui/FloatingScope.js +43 -0
- package/dist/components/ui/Table.d.ts +20 -0
- package/dist/components/ui/Table.js +9 -0
- package/dist/hooks/useComboboxAnchor.d.ts +17 -0
- package/dist/hooks/useComboboxAnchor.js +61 -0
- package/dist/hooks/useInitialHashScroll.js +5 -1
- package/dist/hooks/usePrintPreparation.js +12 -1
- package/dist/hooks/useScrollSpy.js +6 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/kit/data-display.css +6 -0
- package/dist/kit/forms.css +34 -0
- package/dist/lib/componentClasses.js +1 -1
- package/dist/scoped/kit/data-display.css +6 -0
- package/dist/scoped/kit/forms.css +34 -0
- package/docs/prop-metadata.json +2668 -0
- package/examples/onboarding/SettingsForm.jsx +30 -0
- package/examples/onboarding/SettingsForm.tsx +50 -0
- package/examples/optional/LazyScene.tsx +78 -0
- package/examples/optional/OptionalSmoothScroll.tsx +25 -0
- package/examples/optional/SmoothScrollOwner.tsx +7 -0
- package/examples/optional/optional.css +25 -0
- package/examples/recipes/AsyncProjectPicker.tsx +82 -0
- package/examples/recipes/DeleteProjectConfirmation.tsx +97 -0
- package/examples/recipes/InputCompositions.tsx +49 -0
- package/examples/recipes/RemoteRecordsTable.tsx +256 -0
- package/examples/recipes/useRemoteResource.ts +81 -0
- package/examples/reference/HookExamples.tsx +146 -0
- package/examples/reproduction/README.md +9 -0
- package/examples/reproduction/index.html +14 -0
- package/examples/reproduction/package.json +27 -0
- package/examples/reproduction/src/main.tsx +33 -0
- package/examples/reproduction/src/style.css +19 -0
- package/examples/reproduction/tsconfig.json +18 -0
- package/examples/reproduction/vite.config.ts +19 -0
- package/examples/starters/next/README.md +18 -0
- package/examples/starters/next/app/Demo.tsx +65 -0
- package/examples/starters/next/app/layout.tsx +25 -0
- package/examples/starters/next/app/next-page/page.tsx +9 -0
- package/examples/starters/next/app/page.tsx +11 -0
- package/examples/starters/next/app/style.css +19 -0
- package/examples/starters/next/next-env.d.ts +2 -0
- package/examples/starters/next/next.config.mjs +1 -0
- package/examples/starters/next/package.json +27 -0
- package/examples/starters/next/proxy.ts +16 -0
- package/examples/starters/next/tsconfig.json +30 -0
- package/examples/starters/vite/README.md +16 -0
- package/examples/starters/vite/index.html +14 -0
- package/examples/starters/vite/package.json +27 -0
- package/examples/starters/vite/src/main.tsx +81 -0
- package/examples/starters/vite/src/style.css +19 -0
- package/examples/starters/vite/tsconfig.json +18 -0
- package/examples/starters/vite/vite.config.ts +19 -0
- package/package.json +37 -4
package/HOOKS.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Hooks and browser lifecycles
|
|
2
|
+
|
|
3
|
+
Reference for the current package manifest version; exact released implementations and emitted types are linked in [PUBLIC-API.md](PUBLIC-API.md). Hooks belong in a React client component. Import from `@abuzareal/contour-ui` unless the optional `/scroll` entry is named explicitly. No general provider is required except useToast. These are executable contracts, not promises of every browser, renderer or application layout.
|
|
4
|
+
|
|
5
|
+
## Theme
|
|
6
|
+
|
|
7
|
+
`useTheme(animate = true)` returns `{theme, toggle(origin), canToggle}`. Theme is `"light" | "dark"`; toggle accepts an HTMLElement that anchors the reveal. Outside ThemeScope it owns html[data-theme], the existing theme-color meta, local storage key `aa-theme`, and subscriptions to root attributes, storage events and system changes when no stored preference exists. Initial server snapshot is light. Use the pure bootstrap entry before paint rather than hiding arbitrary hydration mismatches. Blocked storage does not prevent a local toggle. Animation respects system reduced motion; unsupported View Transitions fall back to a short class-based transition.
|
|
8
|
+
|
|
9
|
+
Within controlled ThemeScope it reads the scope's theme and invokes onThemeChange; it does not write document preference/storage. Without that callback canToggle is false. ThemeToggle supplies the native button, constant accessible name and aria-pressed state. The hook is not a general persisted settings manager. Independent scopes need scoped CSS. See [STYLING.md](STYLING.md) and the actual hash/nonce starter sources in [GETTING-STARTED.md](GETTING-STARTED.md).
|
|
10
|
+
|
|
11
|
+
`themeBootstrapScript` and `themeColors` are exported from `@abuzareal/contour-ui/theme-bootstrap`, not the core entry. The string reads valid stored light/dark, otherwise system preference, sets root theme and an existing meta; it does not initialize independent scopes. themeColors contains light `#f2f3ee` and dark `#0f100d`. Hash the exact current string or authorize a fresh request nonce; never interpolate user data, reuse a nonce, copy an old hash, or assume a dynamic nonce setup supports static export. The bootstrap module can be imported by a server/config process without browser globals; executing its string is a browser operation.
|
|
12
|
+
|
|
13
|
+
## Motion
|
|
14
|
+
|
|
15
|
+
`useMotionPreference()` returns a boolean for `(prefers-reduced-motion: reduce)` and subscribes to changes, removing the listener on unmount. It reports system preference only. It does not combine an application pause, stop timers, cancel a network request or control unrelated scenes. The app combines `!reducedMotion && !paused` and owns cleanup of its effects.
|
|
16
|
+
|
|
17
|
+
`motionDisabledFor(element)` synchronously returns true for system reduction or an ancestor `[data-motion="off"]`. It is a browser helper, not a subscription. It uses the current window's media preference and the supplied element's ancestors. CSS motion rules and JavaScript loops have separate responsibilities. Do not call this on the server or infer that merely mounting the preference hook pauses every animation.
|
|
18
|
+
|
|
19
|
+
## Clipboard
|
|
20
|
+
|
|
21
|
+
`useClipboardCopy(text: string)` returns `{status, copy}`. CopyStatus is `idle | copying | copied | error`. Invoke copy from an explicit user action. It awaits navigator.clipboard.writeText; only a resolved write yields copied. Missing API, insecure context, denial and rejected writes yield error; there is no fabricated fallback success. Feedback returns to idle after 4,000 ms. Changing text resets feedback and invalidates earlier completions; newer calls win, unmount removes reset timers and ignores late writes. A clipboard write itself cannot be cancelled.
|
|
22
|
+
|
|
23
|
+
Render visible feedback or a polite status, and a retry action when appropriate. The hook does not request browser permission in advance or guarantee OS clipboard retention. Do not log secrets or use a toast as the only record of failure.
|
|
24
|
+
|
|
25
|
+
## Dismissal and mobile menus
|
|
26
|
+
|
|
27
|
+
`useDismiss(containerRef, active, onDismiss, options = {})` returns void. The callback receives DismissReason (`escape | outside`) and the native KeyboardEvent or PointerEvent. The topmost registered layer in that element's owner document dismisses once. Native preventDefault cancellation and ordinary document observers remain meaningful; nested/sibling ordering is described in [OVERLAYS.md](OVERLAYS.md). A render with changed callbacks updates policy without simulating a close. Actual node/document changes rebind registration and unmount removes it.
|
|
28
|
+
|
|
29
|
+
DismissOptions supplies `branches` (owned refs, including trigger/portals), `layerElement` (floating paint-order owner) and `outside` (default true; native modal backdrop handling may own it instead). This hook does not create a trigger, portal, focus trap, accessible name, modal scroll lock or automatic open state. Prefer Dialog/Popover when their complete interaction fits. Custom layer callers own focus entry/return, role/ARIA, state and structural containment. Do not deep-import internal stack helpers.
|
|
30
|
+
|
|
31
|
+
`useMobileMenu(containerRef, toggleButtonRef)` returns readonly `[open, setOpen]`, initially false. It uses dismissal with the trigger as an owned branch; Escape closes and focuses a connected toggle, outside press closes without stealing focus. While open it listens for the container's owner window to transition into `(min-width: 768px)` and closes. It does not supply menu markup, ARIA, a modal trap, routing or a responsive design system. Opening programmatically while already at desktop width is not prohibited by the hook; the app owns viewport-dependent rendering. Match refs to the actual connected nodes and choose native links/buttons for the menu's purpose.
|
|
32
|
+
|
|
33
|
+
PanelFocusOptions is a public type used by built-in floating panels: initialFocus may be a ref or false; onOpenAutoFocus/onCloseAutoFocus receive cancelable events. FloatingOptions covers side/align/offset/collision and portal/container. These types do not expose the internal positioning hook. Use their current declarations; disabling automatic focus transfers responsibility to the application.
|
|
34
|
+
|
|
35
|
+
## Scroll and navigation
|
|
36
|
+
|
|
37
|
+
`useHeaderScroll(headerRef)` returns `{scrolled, overDark, activeId}`. It samples `main section[id]` and `[data-header-theme='dark']` once when the effect installs. scrolled means scrollY > 20; overDark tests the header-height line against marked areas; activeId is the last listed section whose top is at or above 35% of viewport height. It subscribes to scroll/resize and removes listeners on cleanup. Dynamic section replacement, arbitrary nested scroll containers and router state are not observed automatically. This is a retained page-oriented hook, not a universal app header API.
|
|
38
|
+
|
|
39
|
+
`useScrollSpy(ids: string[])` returns the last supplied existing section above a 30% viewport activation line, or an empty string before any qualifies. Keep unique stable section IDs in visual order. Targets are resolved when the ID sequence changes, not on every DOM mutation. Scroll/resize updates are batched through one animation frame and cleanup cancels it. The serialized sequence preserves IDs containing separators; this patch fixes the prior `|`-joined ambiguity. It does not observe a custom scroll container or change the URL.
|
|
40
|
+
|
|
41
|
+
`useInitialHashScroll()` has no arguments/return value. At mount it decodes the initial hash, finds an existing ID, scrolls to its start and realigns once after document.fonts.ready. Malformed or missing hashes are ignored. Wheel/touchstart/keydown stops the delayed realignment so it cannot override the visitor. Cleanup invalidates font readiness; it cannot scroll a later page after unmount. It does not subscribe to hashchange or wait for a later lazy route to create the target. Native history/focus/routing remain application-owned.
|
|
42
|
+
|
|
43
|
+
## Idle and print
|
|
44
|
+
|
|
45
|
+
`useIdleTrigger(enabled)` returns false until enabled and an idle callback fires (timeout 1,200 ms), or a 300 ms setTimeout fallback where idle callbacks are unavailable. It cancels the pending callback/timer when disabled or unmounted. Once true it stays true for that hook instance, even if enabled later becomes false. It is a scheduling hint, not a loading indicator, work queue or guarantee that the main thread is free; actual heavy work still needs a bounded/lazy design.
|
|
46
|
+
|
|
47
|
+
`usePrintPreparation()` installs beforeprint/afterprint listeners on the current document/window. It temporarily opens closed details and sets root data-theme to light, then restores the exact original theme attribute and only those disclosures it opened. Repeated beforeprint does not replace the original snapshot; repeated afterprint is harmless. Unmount during print also restores the snapshot and removes listeners. Mount one document owner. This inherited page hook changes all disclosures/root theme; independent ThemeScope values, application state, server printing, PDF layout and unrelated printer dialogs are outside its contract. Use CSS print rules for product layout. This patch fixes the prior absent-theme/repeated-event/unmount restoration defects.
|
|
48
|
+
|
|
49
|
+
## Toast
|
|
50
|
+
|
|
51
|
+
`useToast()` returns ToastContextValue `{show(toast): void}` and throws outside ToastProvider. ToastInput requires title, accepts message and AlertTone (`neutral | accent | info | success | warning | danger`); neutral is the visual default. The provider requires children and defaults label="Notifications", dismissLabel="Dismiss notification". It renders a polite live region, retains at most the latest three notifications and dismisses each after 5,000 ms while not hovered/focused. Leaving a pause starts a new full timeout, not a remaining-time countdown. Close buttons dismiss individual items. The public command returns no ID and has no update/dismiss/promise/undo API.
|
|
52
|
+
|
|
53
|
+
A toast describes an already established result. Fetching, business validation, persistence and retry remain application-owned. Keep important errors beside the task and use durable state when a message must outlive a temporary notification. ToastContext appears only as a type-level export through the current public re-export surface; it is not a runtime provider escape hatch.
|
|
54
|
+
|
|
55
|
+
## Optional scroll
|
|
56
|
+
|
|
57
|
+
`useSmoothScroll(enabled)` is imported from `@abuzareal/contour-ui/scroll`. Install the declared Lenis peer and import `lenis/dist/lenis.css` in the application. Enabled creates one Lenis with autoRaf=true, duration=1.05, smoothWheel=true, syncTouch=false and anchors=true; disabling or unmounting destroys that owner. It returns no Lenis instance/commands. It does not read system preference itself. The app must combine pause/reduced motion, keep one active owner, preserve native focus/hash behavior and supply native-scroll fallback until opt-in.
|
|
58
|
+
|
|
59
|
+
The [actual optional recipe](examples/optional/OptionalSmoothScroll.tsx) lazy-loads its owner and stylesheet; core installation has no Lenis requirement. Vite/client integration is exercised; Next Lenis and arbitrary router scroll restoration remain unverified. Three is separate; see [THREE.md](THREE.md).
|
|
60
|
+
|
|
61
|
+
See [REFERENCE.md](REFERENCE.md) for every runtime/type/style export mapping, [HELPERS.md](HELPERS.md) for pure/browser helpers and [SUPPORT.md](SUPPORT.md) for dated evidence. Report hook/version details through [the public reproduction](examples/reproduction); source/version issue paths are in PUBLIC-API.md and GETTING-STARTED.md.
|
|
62
|
+
|
|
63
|
+
Copyable [HookExamples.tsx](examples/reference/HookExamples.tsx) uses these public contracts for clipboard feedback, motion policy, custom nonmodal dismissal, idle scheduling, scoped theme and toast ownership. Copied source compiles in the packed React18/19 consumers. The custom help region deliberately has no modal trap; use Dialog/Popover for their complete focus/portal contracts.
|
|
64
|
+
|
|
65
|
+
## Version and reproduction
|
|
66
|
+
|
|
67
|
+
Reference version **0.6.1** (candidate until published). [Versioned source](https://github.com/abuzareal/contour-ui/tree/v0.6.1/src) and [emitted type inventory](PUBLIC-API.md) describe this contract; tag links resolve after release. [Report Hooks 0.6.1](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Hooks&version=0.6.1), using the [public minimal reproduction](examples/reproduction) and synthetic data.
|
package/MANUAL-QA.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Manual screen-reader check guide
|
|
2
|
+
|
|
3
|
+
VoiceOver (Mac) and NVDA (Windows) read a page aloud. These checks need a person to listen: an automated test cannot know whether the spoken name, state or error makes sense. You do not need to share a recording or private data. Use synthetic fixture values only. **No session is claimed as completed by this guide.**
|
|
4
|
+
|
|
5
|
+
## Prepare the public fixture
|
|
6
|
+
|
|
7
|
+
From a public repository checkout at the exact commit being checked, run npm ci --ignore-scripts, npm run build, then npm run qa:preview. Open http://127.0.0.1:5177 in the browser being checked. Record the package/source commit, OS version, browser version and screen-reader version. These are local fixture results, not production deployment proof. Stop the preview with Ctrl+C afterward.
|
|
8
|
+
|
|
9
|
+
For VoiceOver use Safari on Mac and turn VoiceOver on with Command+F5 (some keyboards also require Fn), or through the Accessibility settings. For NVDA use a Windows machine with NVDA and Firefox. Browser/OS keyboard navigation settings can affect Tab behavior; record the settings rather than changing the application to hide the difference. Consult the screen reader's own help for reading/navigation commands.
|
|
10
|
+
|
|
11
|
+
## Scenarios to listen to
|
|
12
|
+
|
|
13
|
+
1. Read the heading and local-only notice. Move to Name: its label, required state and hint should make sense. Change it, submit, inspect the actual visible payload, then reset and check Ada returns.
|
|
14
|
+
2. Move to Allow updates and Notifications. Check the announced name/checked state, Space activation and FormData omission when unchecked. No fake success or silent data save should be suggested.
|
|
15
|
+
3. Move to Project. Open the picker, type part of a label, use arrows and select. Confirm the announced field name, expanded/collapsed state, highlighted/selected choice and disabled choice. Test the long translated label and no matches. Typed text must not become an arbitrary submitted ID.
|
|
16
|
+
4. With the picker open, press Tab and Shift+Tab. Confirm the list closes and the newly focused control is readable, with no dead/hidden keyboard target. Try reading outside the popup with the screen-reader cursor as well as keyboard focus. Record any inaccessible background, duplicate announcements or lost position; do not presume the static finding is harmless.
|
|
17
|
+
5. Open Confirm settings. Check the title/description, initial Review note focus, Tab containment, Escape close and focus return to the connected previously focused opener. Safari pointer clicks do not necessarily focus buttons; this fixture explicitly focuses its opener before opening. Repeat Project help and its Escape/focus return.
|
|
18
|
+
6. Repeat relevant controls in dark mode (?theme=dark), narrow width, high browser zoom and RTL (?rtl=1). Distinguish browser zoom from display scaling and CSS zoom. Check long labels/errors do not clip essential controls.
|
|
19
|
+
7. In actual copied async/confirmation recipes, listen for loading/error/retry and safe cancellation. Confirm destructive success is announced only after a real caller-confirmed result. A failed request should leave a readable persistent error. Record the exact recipe/service fixture used; do not claim these paths from the basic static form alone.
|
|
20
|
+
|
|
21
|
+
## Result record
|
|
22
|
+
|
|
23
|
+
| Field | Record |
|
|
24
|
+
| ------------------------------------- | ------- |
|
|
25
|
+
| Date, reviewer and synthetic fixture | Pending |
|
|
26
|
+
| Package/source commit/archive | Pending |
|
|
27
|
+
| OS / browser / screen reader versions | Pending |
|
|
28
|
+
| Scenario / exact keyboard steps | Pending |
|
|
29
|
+
| Expected name/state/announcement | Pending |
|
|
30
|
+
| Actual observed announcement/focus | Pending |
|
|
31
|
+
| Pass / fail / blocked / not attempted | Pending |
|
|
32
|
+
| Reproduction / issue / fix / retest | Pending |
|
|
33
|
+
|
|
34
|
+
Mark unattempted scenarios explicitly. A passing session covers only its recorded environment/scenarios. QA-13 and QA-14 remain open until actual results exist; preparing this guide does not close them. Substantive findings need fixes or public limitations, and the strict automated findings remain independently recorded in SUPPORT.md.
|
|
35
|
+
|
|
36
|
+
## Version and reproduction
|
|
37
|
+
|
|
38
|
+
Reference version **0.6.1** (candidate until published). [Versioned source](https://github.com/abuzareal/contour-ui/tree/v0.6.1/src) and [emitted type inventory](PUBLIC-API.md) describe this contract; tag links resolve after release. [Report Manual accessibility 0.6.1](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Manual%20accessibility&version=0.6.1), using the [public minimal reproduction](examples/reproduction) and synthetic data.
|
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Upgrades and older contracts
|
|
2
|
+
|
|
3
|
+
Use the exact released package version and its declarations. A Git branch, catalogue label or successful local build does not identify what your application installed. Keep the previous lockfile available, review API/type/style/theme/visual changes, install an exact published version, run the application's checks and compare real form/overlay journeys before deployment. Publishing Contour does not upgrade a consumer.
|
|
4
|
+
|
|
5
|
+
## Release history access
|
|
6
|
+
|
|
7
|
+
| Version boundary | Inspect the immutable source | Main contract change |
|
|
8
|
+
| ---------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
9
|
+
| 0.2.0 baseline | [README](https://github.com/abuzareal/contour-ui/blob/v0.2.0/README.md) | Earlier native fields and wrapper limits; do not project later ref/form/portal contracts backwards. |
|
|
10
|
+
| 0.2.1 baseline documentation | [README](https://github.com/abuzareal/contour-ui/blob/v0.2.1/README.md) | Explicit architecture, dependency, compatibility and maturity contract. |
|
|
11
|
+
| 0.3.0 API | [README](https://github.com/abuzareal/contour-ui/blob/v0.3.0/README.md) | Native refs/attributes and typed owned parts; inspect the actual released component, not a generic polymorphic API. |
|
|
12
|
+
| 0.4.0 forms | [README](https://github.com/abuzareal/contour-ui/blob/v0.4.0/README.md) | Named custom-control submission, defaults/reset and native/RHF recipes. |
|
|
13
|
+
| 0.5.0 overlays/styles | [README](https://github.com/abuzareal/contour-ui/blob/v0.5.0/README.md) | Default portals/collision/layer semantics and isolated prefixed CSS/theme scope; legacy style paths retained. |
|
|
14
|
+
| 0.6.0 additions | [README](https://github.com/abuzareal/contour-ui/blob/v0.6.0/README.md) | Combobox, semantic Table, application recipes and standalone starters. No general grid/NumberField/PasswordInput export. |
|
|
15
|
+
|
|
16
|
+
An old guide remains tied to its version. To inspect the emitted declarations/CSS of an older version, use `npm pack @abuzareal/contour-ui@VERSION --ignore-scripts` in a disposable directory and inspect the archive without running application code. Tagged source retains authored documentation available at that release; do not invent an older guide URL when it did not exist. No indefinite hosted website archive/SLA is promised. Current website routes and migration of its own installed release are separate catalogue work.
|
|
17
|
+
|
|
18
|
+
## Refs and forms
|
|
19
|
+
|
|
20
|
+
Before native ref support, some components needed an application-specific wrapper; do not copy that workaround into a current application automatically. The current public targets are documented in COMPOSITION.md and FORMS.md. For example, `const input = useRef<HTMLInputElement>(null)` and `<TextField ref={input} ... />` target the native input; a wrapper div is not the form-registration target. Switch remains a button ref with a backing successful control, not an HTMLInputElement ref.
|
|
21
|
+
|
|
22
|
+
The shipped [ManualSettingsForm-0.3.0.tsx](examples/forms/ManualSettingsForm-0.3.0.tsx) preserves the old application-assembled payload path. [NativeSettingsForm.tsx](examples/forms/NativeSettingsForm.tsx) and [HookFormSettingsForm.tsx](examples/forms/HookFormSettingsForm.tsx) are the current copied-and-tested contracts. Add name/form/value deliberately and verify checked-only omission, required validation, disabled fields, form.reset(), controlled state and error focus. Do not retain both old manually appended values and new named backing controls, producing duplicate submissions. Server validation/authorization remains necessary.
|
|
23
|
+
|
|
24
|
+
## CSS and theme
|
|
25
|
+
|
|
26
|
+
Before: importing legacy styles.css/reset.css supplies global component/reset rules and unprefixed classes. For an embedded current control, choose scoped.css or selective families and opt into minimal-reset only if required. Legacy paths remain available for an intentional gradual migration; changing imports alone does not port application overrides.
|
|
27
|
+
|
|
28
|
+
Before an override might use `.card .popover-panel`. Default portaled content is no longer a DOM descendant of that card. After migration, attach a scoped application class through the documented panelProps/class hook and style that class; do not depend on private DOM ancestry. `portal={false}` preserves inline placement where supported but restores ancestor clipping constraints. Exercise native-dialog top-layer placement, viewport edges and one-layer Escape in the final app.
|
|
29
|
+
|
|
30
|
+
Before root useTheme/bootstrap owns the whole document and aa-theme preference. After embedding, controlled ThemeScope owns an independent subtree and optional onThemeChange; it needs no document bootstrap. Do not mount document-theme owners merely to style one card. Preserve semantic token names, import order and font choice from STYLING.md; system fonts need no font stylesheet. Review any app-specific aliases before removing old reset/layout assumptions.
|
|
31
|
+
|
|
32
|
+
## Rollout and rollback
|
|
33
|
+
|
|
34
|
+
1. Record the application's old package/lock version and affected routes; read the destination release's CHANGELOG, CONTRACTS and limits.
|
|
35
|
+
2. Install the exact published package with --save-exact; retain a real registry install rather than a workspace link.
|
|
36
|
+
3. Compile declarations, lint/build and exercise forms, refs, overlays, styling/theme and optional scenes actually used. Verify narrow/long content and keyboard behavior. Compare runtime support with SUPPORT.md.
|
|
37
|
+
4. Commit manifest/lockfile and required composition changes together. Deploy only with authorization, then verify hosted version/content separately.
|
|
38
|
+
5. If rollback is needed, restore the previous exact package/lock and compatible application composition together; do not unpublish or overwrite an existing library version.
|
|
39
|
+
|
|
40
|
+
The 0.6.1 work is intended as compatible lifecycle/documentation corrections. Its publication state and support evidence must be checked before installation; a candidate version in source is not an npm release. No universal screen-reader or framework certification is added by these migration instructions.
|
|
41
|
+
|
|
42
|
+
## Version and reproduction
|
|
43
|
+
|
|
44
|
+
Reference version **0.6.1** (candidate until published). [Versioned source](https://github.com/abuzareal/contour-ui/tree/v0.6.1/src) and [emitted type inventory](PUBLIC-API.md) describe this contract; tag links resolve after release. [Report Migration 0.6.1](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Migration&version=0.6.1), using the [public minimal reproduction](examples/reproduction) and synthetic data.
|
package/MODELS.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Library models and references
|
|
2
|
+
|
|
3
|
+
Reviewed14 October2026 against the linked primary documentation. This is a distinction between distribution/ownership models, not a ranking or a claim that Contour has equivalent coverage, staffing, accessibility evidence or maintenance guarantees.
|
|
4
|
+
|
|
5
|
+
- **Contour** is an authored TypeScript/React package distributed as ESM JavaScript, declarations and CSS. Vite is tooling for fixtures/catalogues, not a requirement that consumers mount another Vite app. Public primitives/tokens and experimental optional entries remain versioned package contracts; applications own workflows and data.
|
|
6
|
+
- **Radix Primitives** provides unstyled React interaction primitives for building a design system. It is not a ready-made Contour visual theme. Its [official introduction](https://www.radix-ui.com/primitives/docs/overview/introduction) describes accessibility and composition priorities. Source/typed APIs do not make arbitrary adapters automatically interoperable.
|
|
7
|
+
- **shadcn/ui** describes a code distribution platform: its CLI distributes component source into the application, where the adopter owns modifications and update reconciliation. That differs from upgrading an npm component package. See the [official introduction](https://ui.shadcn.com/docs). The original research interpreted the spoken “ChatC” as shadcn/ui; that remains an assumption, not a separate verified product name.
|
|
8
|
+
- **Material UI** is an independent React implementation of Google's Material Design, with prebuilt components and customization. Google's design guidance and the MUI implementation are separate sources. The [MUI overview](https://mui.com/material-ui/getting-started/) and [repository](https://github.com/mui/material-ui) describe that relationship; adopting Material's principles does not require copying its visual identity or claiming all MUI X capabilities belong to the same core scope.
|
|
9
|
+
- **Salt** is J.P. Morgan's open-source React design system for financial services and other products. Its [official glossary](https://www.saltdesignsystem.com/salt/about/glossary) and [repository](https://github.com/jpmorganchase/salt-ds) establish an actual public implementation. Specific private firm themes, company product screens and business workflows are not thereby public reusable assets. Study task clarity, support matrices and contribution boundaries rather than copying a bank's product identity.
|
|
10
|
+
- **Polaris React** is now a deprecated archived implementation, rather than evidence of an actively maintained current React target. Its [official archive](https://github.com/Shopify/polaris-react-archive) and Shopify's [web-component migration guidance](https://shopify.dev/docs/apps/build/app-home/migrate-from-polaris-react) distinguish the older React contract from the current migration direction. An archived reference can explain a historical pattern but needs an explicit maintenance disposition before reuse.
|
|
11
|
+
|
|
12
|
+
Other company design websites can be useful visual/process references without proving an open-source implementation, redistribution license or reusable package. Check the actual repository/package, source license, notices, supported environment and version before adopting code/assets. Public screenshots or tokens are not blanket permission to redistribute a brand. This page does not copy upstream implementation or change Contour's MIT license.
|
|
13
|
+
|
|
14
|
+
The bounded Base UI/Radix+cmdk/React Aria decision, exact versions, licenses and measured tradeoffs remain in [FOUNDATION.md](FOUNDATION.md). Preserve that dated evidence instead of treating a competitor list as a reason to add dependencies. New controls still require a reusable contract and demonstrated need.
|
|
15
|
+
|
|
16
|
+
## Version and reproduction
|
|
17
|
+
|
|
18
|
+
Reference version **0.6.1** (candidate until published). [Versioned source](https://github.com/abuzareal/contour-ui/tree/v0.6.1/src) and [emitted type inventory](PUBLIC-API.md) describe this contract; tag links resolve after release. [Report Library models 0.6.1](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Library%20models&version=0.6.1), using the [public minimal reproduction](examples/reproduction) and synthetic data.
|
package/NEXTJS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Next.js App Router integration
|
|
2
2
|
|
|
3
|
-
This guide describes **Contour 0.
|
|
3
|
+
This guide describes **Contour 0.6.1**. npm 0.1.2 does not include the client directives, native refs or relative Latin font files described here. Check npm for release availability before installing. The fixture pins Next 16.4.0 with React/React DOM 19.3.0, uses the webpack production build, and consumes an npm archive. It does not establish every Next version, Turbopack, Pages Router, scroll entries or hosting platform. A separate optional mode checks a lazy Three.js scene with SSR disabled and disposal on navigation.
|
|
4
4
|
|
|
5
5
|
In `app/layout.tsx`, load CSS once:
|
|
6
6
|
|
|
@@ -55,3 +55,5 @@ The 0.4.0 fixture also verifies Button native-ref focus and styled Next Link ord
|
|
|
55
55
|
Named form/reset APIs and copyable form recipes are described in [FORMS.md](FORMS.md). They remain client interactions; server-side validation and persistence belong to your application.
|
|
56
56
|
|
|
57
57
|
For embedded first use, substitute scoped.css, omit fonts/bootstrap/reset, and wrap client controls in controlled ThemeScope. The size fixture separately measures Button/settings/table routes with system fonts on the same pinned webpack configuration. Existing document-owned/branded integration above remains compatible; new portal migration and family imports are described in OVERLAYS.md and SIZE.md.
|
|
58
|
+
|
|
59
|
+
The standalone [Next starter](examples/starters/next) adds a tested per-request nonce CSP and dynamic layout using Next 16.4.0/React 19.3.0/webpack and TypeScript 7.0.2. Its strict DOM/ES2024 declaration check is separate from the older generated JS fixture. Follow [onboarding](GETTING-STARTED.md) for the existing-app, provider and optional-feature paths.
|
package/OVERLAYS.md
CHANGED
|
@@ -50,3 +50,7 @@ Production checks cover nested/sibling/portaled layers, native modal portals, to
|
|
|
50
50
|
Keep a portal container stable while open. Changing its DOM target can remount the portaled subtree; keep unsaved child state in the owner when container changes are required.
|
|
51
51
|
|
|
52
52
|
Default-open children choose an enclosing native dialog even before its open attribute is set. When Dialog calls showModal in the same commit, these children enter its top layer without an additional click or render.
|
|
53
|
+
|
|
54
|
+
## Version and reproduction
|
|
55
|
+
|
|
56
|
+
Reference version **0.6.1** (candidate until published). [Versioned source](https://github.com/abuzareal/contour-ui/tree/v0.6.1/src) and [emitted type inventory](PUBLIC-API.md) describe this contract; tag links resolve after release. [Report Overlays 0.6.1](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Overlays&version=0.6.1), using the [public minimal reproduction](examples/reproduction) and synthetic data.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Emitted prop reference and guide audit
|
|
2
|
+
|
|
3
|
+
The installed package's `.d.ts` files are the full typed API. [PUBLIC-API.md](PUBLIC-API.md) links each released symbol and defining source; [REFERENCE.md](REFERENCE.md) maps every public runtime/type/style entry to maintained guidance. Native inherited React attributes and generic overloads are not replaced by a hand-written short table.
|
|
4
|
+
|
|
5
|
+
## Generated metadata
|
|
6
|
+
|
|
7
|
+
[docs/prop-metadata.json](docs/prop-metadata.json) is extracted from emitted declarations for Checkbox, SelectField, ProgressBar, TextField, TextArea, Dialog, Tabs, ToastProvider, DropdownMenu, Combobox and Table. It preserves all call signatures, authored/inherited prop names and selected prop types/required flags. Source destructuring initializers supply explicit defaults; missing initializer is not evidence of false, empty string or a browser default. Dependent expressions remain expressions, not evaluated promises. Generic/inherited React types may be verbose; read their emitted declaration for the complete context.
|
|
8
|
+
|
|
9
|
+
Run `npm run check:reference` after build. It fails on removed documented props, changed types/defaults, reference targets and stale generated metadata. `node scripts/check-reference.mjs --write` updates only after reviewing the change. Human behavior, anatomy, form ownership, accessibility and unsupported combinations remain authored. This bounded generator avoids inventing defaults from optional TypeScript properties or flattening an overloaded component into a misleading universal schema. Other component pages remain PAGE promotion work; type discovery is not full-page coverage.
|
|
10
|
+
|
|
11
|
+
## Nine existing guides: current contract differences
|
|
12
|
+
|
|
13
|
+
The catalogue has its own installed release. Its older release-labelled guides must retain their original meaning until that consumer is upgraded. The current public library references below supplement them; they do not silently relabel old documentation as current.
|
|
14
|
+
|
|
15
|
+
| Component | Current contract and authored reference |
|
|
16
|
+
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| Checkbox | Native input ref and caller id; descriptions and errors merge with caller aria-describedby. indeterminate=false; application owns checked/mixed relationships. Native successful-control/reset behavior in FORMS.md. |
|
|
18
|
+
| SelectField | Native select ref and native value/defaultValue/onChange; generated or supplied id, external form, controlled reset restoration and merged descriptions. Options are value/label records; placeholder adds a disabled empty option. No searchable/free-text API. FORMS.md. |
|
|
19
|
+
| ProgressBar | Required label; value omitted means indeterminate; finite0–100 supplied by caller means determinate with aria-valuenow and rounded visible percent. tone defaults accent, alternatives success/danger. It does not estimate progress, fetch work, clamp invalid data or accept a native input ref. Unknown totals must remain unknown. |
|
|
20
|
+
| TextField | Native input ref/attributes; label, hint/error, optional leadingIcon/trailing and maxLength counter including0. Controlled/default ownership and external form/reset in FORMS.md; decorative adornments are not labels. |
|
|
21
|
+
| TextArea | Native textarea ref/attributes, visible label/help/error, maxLength counter and controlled/default/reset contracts in FORMS.md. rows defaults to3; autoResize defaults false and, when enabled, measures height from rendered content on input/render/reset. Check constrained containers. It is not a rich-text editor. |
|
|
22
|
+
| Dialog | Native dialog ref, controlled open/onClose, required title/children, optional description/footer; placement=center/left/right. Typed body/footer/close-button parts, focus overrides, dismissal, scroll and native top-layer ownership in OVERLAYS.md. A drawer is this placement composition, not another export. |
|
|
23
|
+
| Tabs | Native div ref and typed list/button/panel parts; default/controlled stable-ID selection, automatic activation and RTL arrows in COMPOSITION.md. No disabled-tab or automatic URL/router contract. |
|
|
24
|
+
| ToastProvider | Children plus translated region/dismiss labels. useToast().show requires provider; latest3 queue, polite region,5s timeout with hover/focus pause. No command ID/update/undo/durable inbox. HOOKS.md. |
|
|
25
|
+
| DropdownMenu | Native trigger props/ref and one custom ref-forwarding button via renderTrigger; controlled/default state, stable item IDs and disabled choices. Portal/collision/native-dialog integration supersedes old local-only geometry; no general submenus. OVERLAYS.md. |
|
|
26
|
+
|
|
27
|
+
The historical nine-guide audit compares the old installed declarations with the current implementation, rather than overwriting older limits. Guide URLs/search and catalogue composition remain deferred. The public component-page contract in DOCS.md still applies before promoting a full page; a row here is a focused audit record, not a claim that every PAGE acceptance item is finished.
|
|
28
|
+
|
|
29
|
+
## Forms, anatomy and states
|
|
30
|
+
|
|
31
|
+
Native field refs target the actual input/select/textarea; Dialog targets dialog and Tabs targets its root div. ProgressBar and ToastProvider have no native ref contract. DropdownMenu exposes its trigger through triggerProps, not a root forwardRef. Labels, description IDs, aria-invalid, button types and successful controls must stay attached to the correct element. Error takes precedence over hint in Field; loading/service failure is separate application state.
|
|
32
|
+
|
|
33
|
+
Read [FORMS.md](FORMS.md), [COMPOSITION.md](COMPOSITION.md), [OVERLAYS.md](OVERLAYS.md), [COMBOBOX.md](COMBOBOX.md) and [RECIPES.md](RECIPES.md) for actual runnable sources, named/default state, form reset, keyboard/focus and optional parts. Styling and state selectors belong to STYLING.md; version-specific source and issue paths use the public reproduction. Long labels, disabled fields and both themes need final composition checks. RTL/forced-colors coverage is fixture-specific; manual assistive-technology support is recorded in SUPPORT.md rather than inferred from emitted types.
|
|
34
|
+
|
|
35
|
+
## Version and reproduction
|
|
36
|
+
|
|
37
|
+
Reference version **0.6.1** (candidate until published). [Versioned source](https://github.com/abuzareal/contour-ui/tree/v0.6.1/src) and [emitted type inventory](PUBLIC-API.md) describe this contract; tag links resolve after release. [Report Prop reference 0.6.1](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Prop%20reference&version=0.6.1), using the [public minimal reproduction](examples/reproduction) and synthetic data.
|