@enonic/ui 1.1.1 → 1.2.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.
- package/README.md +92 -77
- package/dist/enonic-ui.cjs +1 -1
- package/dist/enonic-ui.es.js +124 -119
- package/dist/style.cjs +1 -0
- package/dist/style.es.js +1 -0
- package/dist/styles/style.css +1 -1
- package/dist/types/components/app-root/app-root.d.ts +49 -0
- package/dist/types/components/app-root/index.d.ts +1 -0
- package/dist/types/components/combobox/combobox.d.ts +4 -3
- package/dist/types/components/context-menu/context-menu.d.ts +8 -1
- package/dist/types/components/date-picker/date-picker.d.ts +2 -2
- package/dist/types/components/dialog/dialog.d.ts +1 -0
- package/dist/types/components/index.d.ts +1 -0
- package/dist/types/components/menu/menu.d.ts +2 -2
- package/dist/types/components/menubar/menubar.d.ts +4 -5
- package/dist/types/components/selector/selector.d.ts +3 -3
- package/dist/types/components/time-picker/time-picker.d.ts +2 -2
- package/dist/types/hooks/index.d.ts +1 -1
- package/dist/types/hooks/use-floating-position.d.ts +57 -10
- package/dist/types/hooks/use-portal-focus-container.d.ts +3 -2
- package/dist/types/hooks/use-radio-navigation.d.ts +2 -0
- package/dist/types/hooks/use-step-navigation.d.ts +2 -0
- package/dist/types/providers/combobox-provider.d.ts +3 -0
- package/dist/types/providers/index.d.ts +1 -0
- package/dist/types/providers/portal-provider.d.ts +21 -0
- package/dist/types/style.d.ts +8 -0
- package/dist/types/utils/dom.d.ts +22 -0
- package/package.json +21 -6
package/README.md
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
# @enonic/ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@enonic/ui)
|
|
4
|
+
[](https://github.com/enonic/npm-enonic-ui/actions/workflows/ci.yml)
|
|
5
|
+
[](LICENSE)
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
UI components for Preact and React, styled with Tailwind CSS v4. Components ship with keyboard navigation, focus management, and ARIA wiring; theming runs on CSS custom properties with a light and a dark palette.
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
**[Browse the components →](https://enonic.github.io/npm-enonic-ui/)** Every component and variant, live, with props tables and accessibility checks.
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
**1. Install** — with React:
|
|
8
14
|
|
|
9
15
|
```bash
|
|
10
16
|
pnpm add @enonic/ui react react-dom @radix-ui/react-slot
|
|
11
17
|
```
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
…or with Preact:
|
|
14
20
|
|
|
15
21
|
```bash
|
|
16
22
|
pnpm add @enonic/ui preact @radix-ui/react-slot
|
|
@@ -19,39 +25,51 @@ pnpm add @enonic/ui preact @radix-ui/react-slot
|
|
|
19
25
|
<details>
|
|
20
26
|
<summary><b>npm</b></summary>
|
|
21
27
|
|
|
22
|
-
#### With React
|
|
23
|
-
|
|
24
28
|
```bash
|
|
25
|
-
npm install @enonic/ui react react-dom @radix-ui/react-slot
|
|
29
|
+
npm install @enonic/ui react react-dom @radix-ui/react-slot # React
|
|
30
|
+
npm install @enonic/ui preact @radix-ui/react-slot # Preact
|
|
26
31
|
```
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
</details>
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
**2. Load the styles.** Components use Tailwind utility classes and render unstyled until a stylesheet is present. The prebuilt one needs no configuration:
|
|
36
|
+
|
|
37
|
+
```css
|
|
38
|
+
/* your app's entry CSS */
|
|
39
|
+
@import '@enonic/ui/style.css';
|
|
32
40
|
```
|
|
33
41
|
|
|
34
|
-
|
|
42
|
+
Already running Tailwind v4? Use the [Tailwind setup](#tailwind-v4-setup) instead — it shares one utility build with your app and lets your theme overrides through.
|
|
35
43
|
|
|
36
|
-
|
|
44
|
+
**3. Render something.**
|
|
37
45
|
|
|
38
|
-
|
|
46
|
+
```tsx
|
|
47
|
+
import { Button, Input } from '@enonic/ui';
|
|
39
48
|
|
|
40
|
-
|
|
49
|
+
function App() {
|
|
50
|
+
return (
|
|
51
|
+
<>
|
|
52
|
+
<Input label='Project' placeholder='Search projects' />
|
|
53
|
+
<Button variant='filled' size='md'>
|
|
54
|
+
Search
|
|
55
|
+
</Button>
|
|
56
|
+
</>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
41
60
|
|
|
42
|
-
|
|
61
|
+
## Styles
|
|
43
62
|
|
|
44
|
-
|
|
63
|
+
Two paths. Pick by whether your app already runs Tailwind:
|
|
45
64
|
|
|
46
|
-
|
|
65
|
+
| Your app | Import | Trade-off |
|
|
66
|
+
| ----------------------------- | ----------------------- | ----------------------------------------------------------------- |
|
|
67
|
+
| No Tailwind | `@enonic/ui/style.css` | Zero config, ships Tailwind's output for the components |
|
|
68
|
+
| Tailwind CSS v4 (recommended) | `@enonic/ui/preset.css` | One shared utility build, your theme overrides apply, smaller CSS |
|
|
47
69
|
|
|
48
|
-
|
|
49
|
-
@import '@enonic/ui/style.css';
|
|
50
|
-
```
|
|
70
|
+
### Tailwind v4 setup
|
|
51
71
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
If your project already runs **Tailwind CSS v4**, integrate the design tokens through `preset.css` so components share your Tailwind build — one set of utilities, your theme overrides apply, and a smaller bundle. A working setup needs all of the following:
|
|
72
|
+
Import the tokens through `preset.css` and point Tailwind at the package. All four pieces are needed:
|
|
55
73
|
|
|
56
74
|
```css
|
|
57
75
|
/* Declare layer order first so your own overrides win over component styles */
|
|
@@ -60,19 +78,19 @@ If your project already runs **Tailwind CSS v4**, integrate the design tokens th
|
|
|
60
78
|
@import 'tailwindcss/theme.css' layer(theme);
|
|
61
79
|
@import 'tailwindcss/preflight.css' layer(base);
|
|
62
80
|
@import '@enonic/ui/preset.css'; /* design tokens, dark variant, base + custom utilities */
|
|
63
|
-
@import 'tw-animate-css'; /* component enter/exit animations
|
|
81
|
+
@import 'tw-animate-css'; /* component enter/exit animations */
|
|
64
82
|
@import 'tailwindcss/utilities.css' layer(utilities);
|
|
65
83
|
|
|
66
|
-
/*
|
|
67
|
-
The path is relative to THIS file — adjust the number of ../ to reach node_modules. */
|
|
84
|
+
/* Relative to THIS file — adjust the ../ depth to reach node_modules */
|
|
68
85
|
@source '../node_modules/@enonic/ui';
|
|
69
86
|
```
|
|
70
87
|
|
|
71
|
-
>
|
|
88
|
+
> [!IMPORTANT]
|
|
89
|
+
> `@source` is mandatory. Tailwind v4 generates only the utilities it finds in scanned sources, and it skips `node_modules` by default. Without this line the component classes are never generated and everything renders unstyled.
|
|
72
90
|
|
|
73
|
-
|
|
91
|
+
`tw-animate-css` is also required on this path: `Dialog`, `Toast`, and `Tooltip` emit `animate-in` / `fade-*` / `zoom-*` classes that `preset.css` does not include. Install it with `pnpm add tw-animate-css`. The prebuilt `style.css` already inlines them.
|
|
74
92
|
|
|
75
|
-
|
|
93
|
+
Without explicit layer control, the shorthand works too:
|
|
76
94
|
|
|
77
95
|
```css
|
|
78
96
|
@import 'tailwindcss';
|
|
@@ -81,36 +99,19 @@ If you don't need explicit layer control, the shorthand also works:
|
|
|
81
99
|
@source '../node_modules/@enonic/ui';
|
|
82
100
|
```
|
|
83
101
|
|
|
84
|
-
|
|
102
|
+
### CSS exports
|
|
85
103
|
|
|
86
|
-
| Export | Contents | Use when
|
|
87
|
-
| -------------------------- | --------------------------------------------------------------------- |
|
|
88
|
-
| `@enonic/ui/style.css` | Fully compiled — Tailwind output + tokens + animations | You don't run Tailwind
|
|
89
|
-
| `@enonic/ui/preset.css` | Design tokens (`@theme`), dark variant, base styles, custom utilities | You run Tailwind
|
|
90
|
-
| `@enonic/ui/tokens.css` | Design tokens + dark variant only | Tokens without base/utilities
|
|
91
|
-
| `@enonic/ui/base.css` | Root font size + base text color | Granular composition
|
|
92
|
-
| `@enonic/ui/utilities.css` | Custom `@utility` definitions (shimmer, `scrollbar-none`, …) | Granular composition
|
|
104
|
+
| Export | Contents | Use when |
|
|
105
|
+
| -------------------------- | --------------------------------------------------------------------- | ----------------------------- |
|
|
106
|
+
| `@enonic/ui/style.css` | Fully compiled — Tailwind output + tokens + animations | You don't run Tailwind |
|
|
107
|
+
| `@enonic/ui/preset.css` | Design tokens (`@theme`), dark variant, base styles, custom utilities | You run Tailwind v4 |
|
|
108
|
+
| `@enonic/ui/tokens.css` | Design tokens + dark variant only | Tokens without base/utilities |
|
|
109
|
+
| `@enonic/ui/base.css` | Root font size + base text color | Granular composition |
|
|
110
|
+
| `@enonic/ui/utilities.css` | Custom `@utility` definitions (shimmer, `scrollbar-none`, …) | Granular composition |
|
|
93
111
|
|
|
94
|
-
|
|
112
|
+
## Dark mode
|
|
95
113
|
|
|
96
|
-
|
|
97
|
-
import { Button, Input } from '@enonic/ui';
|
|
98
|
-
|
|
99
|
-
function App() {
|
|
100
|
-
return (
|
|
101
|
-
<div>
|
|
102
|
-
<Button variant='primary' size='md'>
|
|
103
|
-
Click Me
|
|
104
|
-
</Button>
|
|
105
|
-
<Input placeholder='Enter text...' />
|
|
106
|
-
</div>
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### Dark Mode
|
|
112
|
-
|
|
113
|
-
The library ships light and dark themes as CSS variables, switched by a class. Add `dark` to a root element (or a shadow-DOM host) and every token updates:
|
|
114
|
+
Both themes ship as CSS variables, switched by a class. Add `dark` to a root element and every token updates:
|
|
114
115
|
|
|
115
116
|
```html
|
|
116
117
|
<html class="dark">
|
|
@@ -119,48 +120,62 @@ The library ships light and dark themes as CSS variables, switched by a class. A
|
|
|
119
120
|
```
|
|
120
121
|
|
|
121
122
|
```ts
|
|
122
|
-
// Toggle at runtime
|
|
123
123
|
document.documentElement.classList.toggle('dark', isDark);
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
-
The variant is
|
|
126
|
+
The variant is `@custom-variant dark (&:where(.dark, .dark *))`, so `dark:` matches `.dark` and anything inside it. Use it in your own markup as usual.
|
|
127
|
+
|
|
128
|
+
Inside a shadow root the document's theme does not reach in, even though custom properties cross the boundary: the adopted sheet declares the light tokens on `:host`, and a declaration on the host beats a value inherited into it. Mount through `AppRoot` and let it switch — `<AppRoot theme='dark' stylesheets={sheets}>`. `theme='light'` emits nothing, being the state a root is already in. A `dark` class on the host works too, since `:host(.dark)` outranks `:host`, but it leaves your own `dark:` utilities unmatched because `.dark *` cannot see an ancestor in the outer tree; the class `AppRoot` places sits inside the root, and it mirrors it onto the portal layer so overlays follow. `stylesheets` expects constructed sheets: on Tailwind v4 your own compiled CSS, which already carries the package's tokens and utilities via `preset.css` and `@source`; without Tailwind the prebuilt sheet from `@enonic/ui/style` (`getStyleSheet()`, or `styleText` for the raw text). Not both, and never `tokens.css`/`utilities.css`, which are Tailwind source entries.
|
|
127
129
|
|
|
128
|
-
|
|
130
|
+
## Icons
|
|
129
131
|
|
|
130
|
-
Icons used
|
|
132
|
+
Icons used inside components are bundled — no icon package is needed for components to render.
|
|
131
133
|
|
|
132
|
-
|
|
134
|
+
A Lucide package is needed only when you pass your own icon to a component that takes one, such as the `icon` prop on `Tab`, `Link`, or `VirtualizedTreeList`:
|
|
133
135
|
|
|
134
136
|
```tsx
|
|
135
137
|
import { Tab } from '@enonic/ui';
|
|
136
|
-
import { Star } from 'lucide-react'; //
|
|
137
|
-
// import { Star } from 'lucide-preact'; // Preact
|
|
138
|
+
import { Star } from 'lucide-react'; // lucide-preact in Preact projects
|
|
138
139
|
|
|
139
140
|
<Tab icon={Star} label='Favorites' />;
|
|
140
141
|
```
|
|
141
142
|
|
|
142
|
-
|
|
143
|
+
The `icon` prop accepts either package.
|
|
143
144
|
|
|
144
|
-
##
|
|
145
|
+
## Requirements
|
|
145
146
|
|
|
146
|
-
|
|
147
|
+
`package.json` holds the exact ranges — installing surfaces any unmet peer.
|
|
147
148
|
|
|
148
|
-
|
|
149
|
+
| Requirement | Notes |
|
|
150
|
+
| ----------------------------------------------- | ----------------------------------- |
|
|
151
|
+
| `@radix-ui/react-slot` | Required — backs the `asChild` prop |
|
|
152
|
+
| `react` + `react-dom` v19, **or** `preact` v10+ | Pick one framework |
|
|
153
|
+
| Tailwind CSS v4 | Only for the `preset.css` path |
|
|
149
154
|
|
|
150
|
-
|
|
155
|
+
Optional peers, needed per feature:
|
|
151
156
|
|
|
152
|
-
|
|
157
|
+
| Package | Needed for |
|
|
158
|
+
| ------------------ | ------------------------------------------------- |
|
|
159
|
+
| `focus-trap-react` | Focus management in `Dialog` and other overlays |
|
|
160
|
+
| `react-virtuoso` | `VirtualizedTreeList` and other virtualized lists |
|
|
161
|
+
| `tw-animate-css` | Component animations on the `preset.css` path |
|
|
153
162
|
|
|
154
|
-
|
|
155
|
-
| --------------------------- | --------------- |
|
|
156
|
-
| `react` + `react-dom` (v19) | `preact` (v10+) |
|
|
163
|
+
## What's exported
|
|
157
164
|
|
|
158
|
-
|
|
165
|
+
Beyond the components, the package entry re-exports the hooks that drive them (roving tabindex, type-ahead, floating position, scroll lock, and more), the bundled icon set, context providers, shared types, and the `cn` class-merge helper.
|
|
159
166
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
167
|
+
```tsx
|
|
168
|
+
import { Button, cn, useControlledState } from '@enonic/ui';
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Development
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
pnpm dev # Storybook on :6006
|
|
175
|
+
pnpm check:fix # format + lint, then typecheck
|
|
176
|
+
pnpm build # library + CSS into dist/
|
|
177
|
+
```
|
|
163
178
|
|
|
164
179
|
## License
|
|
165
180
|
|
|
166
|
-
|
|
181
|
+
Apache-2.0 — see [LICENSE](LICENSE).
|