@nextlyhq/ui 0.0.2-alpha.5 → 0.0.2-alpha.51

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 CHANGED
@@ -31,33 +31,41 @@ pnpm add react react-dom lucide-react
31
31
 
32
32
  ## Setup
33
33
 
34
- The components ship as Tailwind CSS 4 token consumers. They reference HSL CSS variables (`--background`, `--primary`, `--border`, etc.) which your project must define.
34
+ The package ships three CSS entry points. Pick one:
35
35
 
36
- **Tailwind v4 (recommended)**
36
+ **Zero config — pre-compiled bundle**
37
37
 
38
- In your global CSS, define the design tokens with `@theme` and import the components:
38
+ Import the pre-built stylesheet once at your root. It bundles Tailwind, every design token
39
+ (on `:root`, flipped under `.dark`), and the base reset, so components render fully styled
40
+ with no build wiring:
39
41
 
40
- ```css
41
- /* app/globals.css */
42
- @import "tailwindcss";
42
+ ```tsx
43
+ import "@nextlyhq/ui/styles.css";
44
+ import { Button } from "@nextlyhq/ui";
43
45
 
44
- @theme {
45
- --color-background: hsl(0 0% 100%);
46
- --color-foreground: hsl(222 47% 11%);
47
- --color-primary: hsl(221 83% 53%);
48
- --color-primary-foreground: hsl(0 0% 100%);
49
- /* ...the rest. See `uiPreset` for the full token contract. */
50
- }
46
+ <Button variant="outline">Click me</Button>;
51
47
  ```
52
48
 
53
- The exported `uiPreset` is the reference contract: it lists every token name the components expect. Use it to write the matching `@theme` block (or import it directly if you are still on Tailwind v3).
49
+ **Bring your own Tailwind v4 build**
54
50
 
55
- ```tsx
56
- import { Button } from "@nextlyhq/ui";
51
+ If you already run Tailwind v4, import just the tokens and let your pipeline compile the
52
+ utilities the components use:
57
53
 
58
- <Button variant="outline">Click me</Button>;
54
+ ```css
55
+ /* app/globals.css */
56
+ @import "tailwindcss";
57
+ @import "@nextlyhq/ui/theme.css";
58
+ @source "../node_modules/@nextlyhq/ui/dist";
59
59
  ```
60
60
 
61
+ `theme.css` defines the tokens as complete OKLCH color values (`--nx-background`, `--nx-primary`,
62
+ `--nx-border`, …) with `@theme inline` mappings and the dark-mode overrides. Reference tokens
63
+ directly (`var(--nx-primary)`) — never wrap them in `hsl()`. `uiPreset` remains available
64
+ as a Tailwind v3 preset from `@nextlyhq/ui/tailwind-preset`.
65
+
66
+ > Inside a Nextly admin plugin you need neither import — the admin already provides the
67
+ > tokens. See the [**Plugin UI authoring guide**](./docs/plugin-ui-authoring.md).
68
+
61
69
  ## Components
62
70
 
63
71
  **Buttons and inputs:** `Button`, `Input`, `Textarea`, `Label`
@@ -69,18 +77,85 @@ import { Button } from "@nextlyhq/ui";
69
77
  **Feedback:** `Spinner`, `Toaster` (with `toast()` helper)
70
78
  **Tables:** `Table` primitives, `ResponsiveTable`, `TableSearch`, `TablePagination`, `TableSkeleton`, `TableEmpty`, `TableError`, `TableLoading`
71
79
  **Providers:** `PortalProvider`, `usePortalContainer`
72
- **Utilities:** `cn`, `uiPreset`
80
+
81
+ > Which of these carry a stability guarantee is recorded in
82
+ > [STABILITY.md](https://github.com/nextlyhq/nextly/blob/main/packages/ui/STABILITY.md). A component becomes `@public` once a first-party
83
+ > plugin depends on it; everything else is `@experimental` and may change in any
84
+ > release.
85
+
86
+ **Utilities:** `cn` (from `@nextlyhq/ui/utils`), `uiPreset` (from `@nextlyhq/ui/tailwind-preset`)
87
+
88
+ > Both ship from their own subpaths rather than the root: the root bundle is
89
+ > published with `"use client"`, and neither of these contains a React runtime,
90
+ > so a server component or a Tailwind config can import them safely.
91
+
92
+ ## Stylesheets
93
+
94
+ | Import | Use when |
95
+ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
96
+ | `@nextlyhq/ui/styles.css` | The app is yours end to end. Styles the whole document, Tailwind preflight included. |
97
+ | `@nextlyhq/ui/styles.scoped.css` | Dropping a few components into an existing app. Every rule is confined to `.nextly-ui`, so the rest of the page keeps its own styles. |
98
+ | `@nextlyhq/ui/theme.css` | You compile Tailwind yourself and want the token contract only. |
99
+
100
+ The scoped sheet needs a wrapper element, and dark mode goes on the same element:
101
+
102
+ ```tsx
103
+ import "@nextlyhq/ui/styles.scoped.css";
104
+
105
+ <div className="nextly-ui">
106
+ <Button>Save</Button>
107
+ </div>;
108
+ ```
109
+
110
+ It keeps preflight rather than dropping it — these components are designed against a
111
+ normalised baseline — but confines it to the wrapper, so your headings, lists and form
112
+ controls outside it are untouched. Three things CSS resolves globally are namespaced
113
+ along with the selectors, so the sheet cannot reach outside the wrapper through them
114
+ either: animation names (it will not displace a `spin` or `fade-in` you define),
115
+ Tailwind's internal `--tw-*` registrations, and the ancestor classes `dark:` and
116
+ `group-*:` variants look for. Dark mode is therefore driven by the wrapper, not by a
117
+ `dark` class higher up your page.
118
+
119
+ ### Overlays need a portal container
120
+
121
+ AlertDialog, Command, Dialog, DropdownMenu, Popover, Select, Sheet and Tooltip render
122
+ their overlay through a portal, which defaults to `document.body` — outside the wrapper,
123
+ where the scoped rules and tokens do not reach. Triggers would look right and the menus
124
+ they open would not. Point them back inside with `PortalProvider`:
125
+
126
+ ```tsx
127
+ import { useState } from "react";
128
+ import { PortalProvider } from "@nextlyhq/ui";
129
+ import "@nextlyhq/ui/styles.scoped.css";
130
+
131
+ function Kit({ children }: { children: React.ReactNode }) {
132
+ const [container, setContainer] = useState<HTMLElement | null>(null);
133
+
134
+ return (
135
+ <div className="nextly-ui" ref={setContainer}>
136
+ <PortalProvider container={container}>{children}</PortalProvider>
137
+ </div>
138
+ );
139
+ }
140
+ ```
141
+
142
+ A callback ref rather than `useRef` because the container has to be a state value: on the
143
+ first render it is still `null`, and the overlays need a re-render once the element exists.
144
+
145
+ This does not apply to `styles.css`, where the rules are document-wide and
146
+ `document.body` is already covered.
73
147
 
74
148
  ## Compatibility
75
149
 
76
- | Tool | Version |
77
- | -------------- | ---------------------------------------------------------------- |
78
- | React | 18 or 19 |
79
- | Tailwind CSS | 4+ (the `uiPreset` JS export also works as a Tailwind v3 preset) |
80
- | `lucide-react` | 0.400+ |
150
+ | Tool | Version |
151
+ | -------------- | ---------------------------------------------------------------------- |
152
+ | React | 18 or 19 |
153
+ | Tailwind CSS | 4+ (`@nextlyhq/ui/tailwind-preset` also works as a Tailwind v3 preset) |
154
+ | `lucide-react` | 0.400+ |
81
155
 
82
156
  ## Documentation
83
157
 
158
+ - [**Plugin UI authoring guide**](./docs/plugin-ui-authoring.md): the token contract, dark mode, container queries, and the design lint guard
84
159
  - [**Admin customization**](https://nextlyhq.com/docs/admin/customization): theming, branding, and custom field UIs
85
160
 
86
161
  ## Related packages