@abuzareal/contour-ui 0.4.0 → 0.5.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 (136) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/CONTRACTS.md +7 -1
  3. package/NEXTJS.md +3 -1
  4. package/OVERLAYS.md +52 -0
  5. package/PUBLIC-API.md +179 -162
  6. package/README.md +40 -26
  7. package/RELEASING.md +1 -1
  8. package/SIZE.md +45 -0
  9. package/STYLING.md +68 -0
  10. package/dist/actions.css +7 -0
  11. package/dist/components/hero/Sculpture.js +2 -1
  12. package/dist/components/three/ObjectStudy.js +2 -1
  13. package/dist/components/ui/Alert.d.ts +2 -1
  14. package/dist/components/ui/Alert.js +3 -3
  15. package/dist/components/ui/Avatar.d.ts +3 -1
  16. package/dist/components/ui/Avatar.js +3 -3
  17. package/dist/components/ui/Badge.js +2 -2
  18. package/dist/components/ui/BrandMark.js +2 -1
  19. package/dist/components/ui/Breadcrumbs.d.ts +2 -1
  20. package/dist/components/ui/Breadcrumbs.js +3 -2
  21. package/dist/components/ui/Button.d.ts +2 -0
  22. package/dist/components/ui/Button.js +3 -2
  23. package/dist/components/ui/Card.js +2 -2
  24. package/dist/components/ui/Checkbox.js +3 -3
  25. package/dist/components/ui/CountUp.d.ts +2 -1
  26. package/dist/components/ui/CountUp.js +6 -3
  27. package/dist/components/ui/DataTable.d.ts +1 -0
  28. package/dist/components/ui/DataTable.js +12 -8
  29. package/dist/components/ui/DepthButton.js +2 -2
  30. package/dist/components/ui/Dialog.d.ts +5 -1
  31. package/dist/components/ui/Dialog.js +49 -18
  32. package/dist/components/ui/Disclosure.js +2 -1
  33. package/dist/components/ui/Divider.js +3 -2
  34. package/dist/components/ui/DropdownMenu.d.ts +11 -4
  35. package/dist/components/ui/DropdownMenu.js +109 -66
  36. package/dist/components/ui/EmptyState.js +2 -1
  37. package/dist/components/ui/Field.js +2 -2
  38. package/dist/components/ui/FlipCard.js +2 -2
  39. package/dist/components/ui/FloatingPortal.d.ts +10 -0
  40. package/dist/components/ui/FloatingPortal.js +51 -0
  41. package/dist/components/ui/IconButton.js +2 -2
  42. package/dist/components/ui/Kbd.js +2 -1
  43. package/dist/components/ui/Magnetic.js +2 -1
  44. package/dist/components/ui/Marquee.js +3 -2
  45. package/dist/components/ui/OverlayTrigger.d.ts +11 -0
  46. package/dist/components/ui/OverlayTrigger.js +5 -0
  47. package/dist/components/ui/Pagination.d.ts +5 -1
  48. package/dist/components/ui/Pagination.js +3 -2
  49. package/dist/components/ui/Popover.d.ts +18 -8
  50. package/dist/components/ui/Popover.js +58 -17
  51. package/dist/components/ui/ProgressBar.js +2 -2
  52. package/dist/components/ui/RadioGroup.js +5 -5
  53. package/dist/components/ui/Reveal.d.ts +0 -1
  54. package/dist/components/ui/Reveal.js +4 -3
  55. package/dist/components/ui/RevealHeading.js +2 -1
  56. package/dist/components/ui/ScrollProgress.js +2 -1
  57. package/dist/components/ui/SectionLabel.js +2 -1
  58. package/dist/components/ui/SegmentedControl.js +6 -3
  59. package/dist/components/ui/SelectField.js +3 -2
  60. package/dist/components/ui/Skeleton.js +2 -2
  61. package/dist/components/ui/Slider.js +3 -3
  62. package/dist/components/ui/Spinner.js +2 -2
  63. package/dist/components/ui/Stat.js +2 -1
  64. package/dist/components/ui/Stepper.js +3 -3
  65. package/dist/components/ui/Switch.d.ts +2 -0
  66. package/dist/components/ui/Switch.js +6 -7
  67. package/dist/components/ui/Tabs.js +7 -5
  68. package/dist/components/ui/Tag.d.ts +2 -1
  69. package/dist/components/ui/Tag.js +4 -3
  70. package/dist/components/ui/TextArea.js +2 -1
  71. package/dist/components/ui/TextField.js +3 -2
  72. package/dist/components/ui/ThemeScope.d.ts +13 -0
  73. package/dist/components/ui/ThemeScope.js +10 -0
  74. package/dist/components/ui/ThemeToggle.d.ts +3 -0
  75. package/dist/components/ui/ThemeToggle.js +4 -3
  76. package/dist/components/ui/TiltCard.js +3 -2
  77. package/dist/components/ui/Timeline.js +2 -2
  78. package/dist/components/ui/ToastProvider.d.ts +5 -2
  79. package/dist/components/ui/ToastProvider.js +5 -5
  80. package/dist/components/ui/Tooltip.d.ts +4 -4
  81. package/dist/components/ui/Tooltip.js +70 -10
  82. package/dist/data-display.css +5 -0
  83. package/dist/effects.css +6 -0
  84. package/dist/feedback.css +5 -0
  85. package/dist/fonts-latin.css +10 -4
  86. package/dist/fonts.css +8 -0
  87. package/dist/forms.css +5 -0
  88. package/dist/hooks/useDismiss.d.ts +12 -3
  89. package/dist/hooks/useDismiss.js +5 -21
  90. package/dist/hooks/useFloatingPanel.d.ts +14 -0
  91. package/dist/hooks/useFloatingPanel.js +157 -0
  92. package/dist/hooks/useLayerDismiss.d.ts +4 -0
  93. package/dist/hooks/useLayerDismiss.js +48 -0
  94. package/dist/hooks/useMobileMenu.d.ts +0 -1
  95. package/dist/hooks/useMobileMenu.js +11 -16
  96. package/dist/hooks/usePanelFocus.d.ts +10 -0
  97. package/dist/hooks/usePanelFocus.js +60 -0
  98. package/dist/hooks/useTheme.d.ts +1 -0
  99. package/dist/hooks/useTheme.js +18 -5
  100. package/dist/index.d.ts +5 -0
  101. package/dist/index.js +1 -0
  102. package/dist/kit/forms.css +11 -2
  103. package/dist/kit/navigation.css +4 -0
  104. package/dist/kit/overlays.css +8 -4
  105. package/dist/lib/classNames.d.ts +2 -0
  106. package/dist/lib/classNames.js +16 -1
  107. package/dist/lib/componentClasses.d.ts +1 -0
  108. package/dist/lib/componentClasses.js +2 -0
  109. package/dist/lib/keyboard.d.ts +1 -1
  110. package/dist/lib/keyboard.js +5 -2
  111. package/dist/lib/layers.d.ts +18 -0
  112. package/dist/lib/layers.js +128 -0
  113. package/dist/lib/themeScope.d.ts +5 -0
  114. package/dist/lib/themeScope.js +3 -0
  115. package/dist/minimal-reset.css +6 -0
  116. package/dist/navigation.css +5 -0
  117. package/dist/overlays.css +5 -0
  118. package/dist/scoped/base.css +183 -0
  119. package/dist/scoped/kit/actions.css +209 -0
  120. package/dist/scoped/kit/data-display.css +492 -0
  121. package/dist/scoped/kit/effects.css +140 -0
  122. package/dist/scoped/kit/feedback.css +309 -0
  123. package/dist/scoped/kit/forms.css +370 -0
  124. package/dist/scoped/kit/navigation.css +266 -0
  125. package/dist/scoped/kit/overlays.css +299 -0
  126. package/dist/scoped/marquee.css +58 -0
  127. package/dist/scoped/spinner.css +20 -0
  128. package/dist/scoped/theme-toggle.css +38 -0
  129. package/dist/scoped/tokens.css +119 -0
  130. package/dist/scoped/ui.css +127 -0
  131. package/dist/scoped/utilities.css +17 -0
  132. package/dist/scoped-tokens.css +1 -0
  133. package/dist/scoped.css +12 -0
  134. package/dist/theme-toggle.css +2 -2
  135. package/dist/tokens.json +710 -0
  136. package/package.json +26 -5
package/CHANGELOG.md CHANGED
@@ -6,6 +6,18 @@ Changes to the published `@abuzareal/contour-ui` package. Version headings refer
6
6
 
7
7
  No changes recorded.
8
8
 
9
+ ## 0.5.0
10
+
11
+ Combined overlay, styling and size work. This heading records source work, not npm publication.
12
+
13
+ - Shared owner-document topmost dismissal and matching paint order for nested/sibling/portaled layers; cancellation, outside focus, ancestor visibility, native backdrop priority and cleanup are covered by regressions. Mobile-menu dismissal cooperates with the same registry.
14
+ - Popover/Menu/Tooltip gain collision-aware placement, bounded scrolling, RTL and CSS-zoom handling via Floating UI DOM 1.8.0. Default body/native-modal portals escape clipping and carry theme values/direction. Default DOM placement changes ancestor selectors; use direct part hooks or portal=false for a deliberate local integration. Public refs/state callbacks and void useDismiss remain compatible.
15
+ - Hoverable/persistent supplemental tooltips retain descriptions/names and Escape suppression. Public button renderTrigger and focus policies avoid nested controls; native Dialog preserves focus/scroll/lifecycle behavior and accepts explicit initial focus.
16
+ - Add isolated scoped.css, prefixed classes/tokens, controlled ThemeScope, minimal-reset.css, token JSON generation, forced-color states, logical RTL layouts and configurable internal labels/formatters. Legacy globals, branded fonts and application-layout compatibility remain; no consumer migration is performed. Compact density is deferred pending a concrete need.
17
+ - Add measured Vite/Next Button/settings/table fixtures, selected-icon comparison, actual network/install/archive categories, selective CSS entries and reviewed regression budgets. System fonts make no font requests; Fontsource/Lucide install costs are retained and disclosed. Three.js/Lenis remain optional and absent from core fixtures.
18
+
19
+ See OVERLAYS.md, STYLING.md and SIZE.md for migration, behavior, measurements and evidence boundaries. Independent applications/site versions are not upgraded by this package release.
20
+
9
21
  ## 0.4.0
10
22
 
11
23
  Native forms and tested application recipes. This heading records source work, not npm publication.
package/CONTRACTS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Architecture, scope and compatibility
2
2
 
3
- Contract version **0.4.0**, reviewed 13 October 2026. Contour is an early 0.x React library with typed controls, paper/ink surfaces, a lime accent, light/dark themes, restrained motion and separate optional depth/scene APIs. The [public API and maturity register](PUBLIC-API.md) lists every exported value, type and stylesheet, its maintainer, status, use and limits.
3
+ Contract version **0.5.0**, reviewed 13 October 2026. Contour is an early 0.x React library with typed controls, paper/ink surfaces, a lime accent, light/dark themes, restrained motion and separate optional depth/scene APIs. The [public API and maturity register](PUBLIC-API.md) lists every exported value, type and stylesheet, its maintainer, status, use and limits.
4
4
 
5
5
  ## Intended adoption scope
6
6
 
@@ -91,3 +91,9 @@ Formal deprecation identifies replacement/affected versions, marks the API/docs
91
91
  Releases choose an unused version, align manifest/lock/tag/changelog, validate a candidate archive and state material limits. Consumers keep exact pins until the released version is installed, their lockfile updated and relevant checks pass. Package publication does not deploy an application.
92
92
 
93
93
  1.0 requires settled supported contracts, appropriate docs/evidence, successful outside-use workflows and no known critical/high-impact defect in the promoted scope. Complete stabilization, then rerun final release gates. Deferred component backlog completion is not a prerequisite.
94
+
95
+ ## 0.5 overlay/style/size contract
96
+
97
+ Default floating portals render in the owner body or active native modal, carrying scoped values/direction. Topmost dismissal, focus customization, closed-ancestor suspension and hover persistence follow OVERLAYS.md. Default portal DOM placement is an explicit 0.x migration; local placement remains available. Stable ref targets and the public void useDismiss return remain unchanged.
98
+
99
+ Legacy aggregate/reset/tokens/classes remain compatibility mode. Isolated CSS, prefixed schema, controlled ThemeScope, optional minimal reset and measured family entries follow STYLING.md. Product/layout tokens remain legacy/app-owned. Scope persistence is caller-owned; document hooks retain aa-theme behavior. Compact density and a font-install packaging migration were evaluated and deferred with reasons in STYLING.md/SIZE.md. No zero-dependency, universal RTL/AT or production performance claim is added.
package/NEXTJS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Next.js App Router integration
2
2
 
3
- This guide describes **Contour 0.4.0**. 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.
3
+ This guide describes **Contour 0.5.0**. 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
 
@@ -53,3 +53,5 @@ Run `npm run test:next` to rebuild and consume the candidate archive. The fixtur
53
53
  The 0.4.0 fixture also verifies Button native-ref focus and styled Next Link ordinary/canceled/middle-click navigation. Use [the composition guide](COMPOSITION.md#native-and-router-links) for the Link recipe; Button remains an action rather than a polymorphic navigation component.
54
54
 
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
+
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.
package/OVERLAYS.md ADDED
@@ -0,0 +1,52 @@
1
+ # Floating layers and focus
2
+
3
+ 0.5 adds shared dismissal, collision-aware placement and portals to Popover, DropdownMenu and Tooltip. Dialog remains a native modal/drawer. Contour uses MIT-licensed Floating UI DOM 1.8.0 for geometry and observers; it does not replace the public components with another component library.
4
+
5
+ ## Dismissal
6
+
7
+ One Escape reaches the deepest active layer; independent siblings use most-recent activation. Paint order follows that dismissal order. One outside primary-pointer press dismisses at most one layer. Presses in portaled descendants are inside their owned layer. Explicit buttons can still perform their own actions. A native modal backdrop does not also dismiss its modal when that press already belongs to a child layer.
8
+
9
+ Listeners attach to the layer's owner document, rebind on document moves and release on inactivity/unmount. They never stop event propagation. Handled Escape prevents its native default so a child dismissal does not also cancel its native parent dialog. Other keys and ordinary outside focus remain available. `onDismiss(reason, nativeEvent)` on Popover/Menu can call `preventDefault()` to veto dismissal. Dialog uses its existing `onCancel` and `onClick` cancellation contracts. `useDismiss(ref, active, callback, options)` uses the same registry; additional `branches` include a caller's trigger/portal. `layerElement` opts a custom floating element into owned stack order; its previous inline z-index is restored on release.
10
+
11
+ A closed ancestor suspends descendant layers without clearing their controlled/uncontrolled state. Reopening resumes that state; reset child state in the parent's application callback when a different policy is wanted. Modal/native close buttons and controlled parent updates are application-owned.
12
+
13
+ ## Placement and containers
14
+
15
+ Popover/Menu accept `side` (bottom by default), `align` (start by default; center/end supported), `sideOffset` (8 px) and `collisionPadding` (8 px). Tooltip retains `placement` (top), with center alignment and a 10 px offset. Alignment is logical in RTL. Placement flips, shifts on both axes and constrains scrollable content to the clipping boundary; scroll/resize/layout/element observers update it while open and clean up on close. Nonfinite offsets/padding fall back to defaults; negative collision padding clamps to zero. A geometry failure retains a viewport fallback and emits a warning rather than leaving an unhandled promise. Geometry properties and stack order are owned; use part props for appearance/content, not competing position/transform declarations. `--contour-z-overlay` configures the nonmodal stacking base (30); native modal top-layer ordering is browser-owned.
16
+
17
+ Default `portal` is true. Content renders in the trigger's owner-document body, or **inside its open native dialog**. A small portal wrapper carries inherited variables, font, text color and direction and follows ancestor theme/style mutations. This escapes a clipped or transformed theme root without changing the document's theme. `container` selects an explicit element in the same document; outside/wrong-document containers inside an active modal fall back to that modal. Keep custom containers unclipped and provide enough space. `portal={false}` preserves local DOM placement for a deliberate integration; clipping ancestors may then clip it.
18
+
19
+ **Migration from 0.4:** default portal DOM placement changes ancestor selectors and DOM-based tests. Target `panelProps.className` directly rather than `.host-root .host-panel`; use `portal={false}` when local placement is required. Root refs still target the wrapper, trigger refs target buttons and panel refs target panels, and may detach/reattach when the portal container changes. No deep import is needed.
20
+
21
+ ## Triggers and focus
22
+
23
+ `trigger` still supplies button content. `renderTrigger` supplies a supported ref-forwarding button component. Spread the provided props so refs, caller handlers and owned type/expanded/controls/haspopup relationships survive; do not nest a button inside the default trigger. An ordinary native button or Contour Button works. Link/non-button triggers are not supported by this contract.
24
+
25
+ ```tsx
26
+ import { Button, Popover, TextField } from "@abuzareal/contour-ui";
27
+ export function HelpPanel() {
28
+ return (
29
+ <Popover
30
+ title="Help"
31
+ trigger="Help"
32
+ renderTrigger={(props) => <Button {...props} variant="secondary" />}
33
+ >
34
+ <TextField label="Question" />
35
+ </Popover>
36
+ );
37
+ }
38
+ ```
39
+
40
+ Popover focuses its panel on entry; `initialFocus={ref}` selects a mounted descendant and `initialFocus={false}` keeps the trigger focused. Cancelable `onOpenAutoFocus` / `onCloseAutoFocus` events allow caller control. Escape returns to a connected trigger by default, including controlled dismissal requests. Outside press does not steal focus from its destination. Programmatic close/unmount returns focus when the layer or a descendant owned it. A missing/removed trigger receives no forced substitute; the application owns its workflow fallback. Popover is nonmodal: it does not trap focus or make the background inert. Portal DOM order affects Tab order; choose inline placement or explicit focus customization for an application-specific sequence.
41
+
42
+ Menu enters the first enabled action; ArrowUp from its trigger enters the last. ArrowUp/Down, Home/End and typeahead skip disabled entries. Selection/Escape return to the trigger; Tab dismisses without consuming Tab. Empty/all-disabled menus focus their panel. Labels/content are caller-owned. Dialog uses native focus confinement and focus return; its new `initialFocus` chooses a mounted modal descendant. `onOpenAutoFocus` can cancel that explicit override; it does not undo native showModal autofocus. Existing nested locks, drawer placement, long content and cleanup remain supported.
43
+
44
+ ## Supplemental hints
45
+
46
+ Tooltip content is a noninteractive string. Hover and keyboard focus cooperate; leaving the pointer does not erase a focused hint. Trigger-to-content travel stays available through a bounded pointer corridor; the hint remains while pointer/focus applies. Escape suppresses it until the current hover/focus conditions end and a new session begins. Existing `aria-describedby` values and the child's accessible name/ref/events are retained. Pointer content is hoverable; tooltip content is never a substitute for a visible label, essential instruction, validation error or interactive panel. Touch users must have the same essential information visibly available.
47
+
48
+ Production checks cover nested/sibling/portaled layers, native modal portals, touch outside press, RTL, narrow/resized viewports, long scrolling panels and CSS zoom. These are automated browser checks, not physical mobile-keyboard or assistive-technology certification. See [W3C hover/focus guidance](https://www.w3.org/WAI/WCAG21/Techniques/client-side-script/SCR39) and [Floating UI observer lifecycle](https://floating-ui.com/docs/autoupdate).
49
+
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
+
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.