@api7/ui-components 0.1.0 → 0.1.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.
Files changed (2) hide show
  1. package/README.md +137 -28
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,48 +1,157 @@
1
1
  # @api7/ui-components
2
2
 
3
- API7 component library built on Base UI and Tailwind CSS v4.
3
+ API7 React component library built on [Base UI](https://base-ui.com) and Tailwind CSS v4. It ships a precompiled stylesheet, so an application does not need Tailwind CSS to use it.
4
4
 
5
- ## Setup
5
+ ## Installation
6
6
 
7
- Import the stylesheet once, before the app's own styles:
7
+ ```sh
8
+ npm install @api7/ui-components react-day-picker lucide-react
9
+ # or
10
+ pnpm add @api7/ui-components react-day-picker lucide-react
11
+ # or
12
+ yarn add @api7/ui-components react-day-picker lucide-react
13
+ ```
8
14
 
9
- import '@api7/ui-components/styles.css';
15
+ The package expects these peer dependencies in the application:
10
16
 
11
- The stylesheet is precompiled, so the app does not need Tailwind CSS. An app that uses Tailwind itself can load both: every library class carries the `asu:` prefix and every library variable the `--asu-` prefix.
17
+ | Package | Version | Needed for |
18
+ | ----------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
19
+ | `react`, `react-dom` | `^19` | Everything |
20
+ | `lucide-react` | `^1` | Icons used inside components |
21
+ | `react-day-picker` | `^10.0.1` | Required. `Calendar`, `DatePicker` and `DateRangePicker` import it, and the package declares it as a required peer, so install it even if you do not use them |
22
+ | `@tanstack/react-form` | `^1.33.0` | `@api7/ui-components/form` (optional) |
23
+ | `@tanstack/react-table` | `^9.0.0` | `@api7/ui-components/data-table` (optional) |
12
24
 
13
- The CSS reset only applies inside library components (`[data-slot]` elements), so the rest of the page keeps its own styles. Load a font for `--asu-font-sans` (Inter by default, for example with `@fontsource-variable/inter`), or override the variable to use another font.
25
+ Add the optional ones only if you import those entry points.
14
26
 
15
- Theme colors are CSS variables such as `--asu-primary`. Override them on `:root` or `[data-theme=dark]` to change the palette. `className` on a component is passed through to the element for the app's own classes; it cannot restyle what the component already sets.
27
+ ## Quick start
16
28
 
17
- ## Peer dependencies
29
+ 1. Import the stylesheet once, in the entry file of the application, before your own styles:
18
30
 
19
- Install these in the application: `react` and `react-dom` 19, `lucide-react` 1, and `react-day-picker` 10 (the calendar and date pickers import it). `@tanstack/react-form` and `@tanstack/react-table` are optional and only needed for the `form` and `data-table` entry points.
31
+ ```ts
32
+ import '@api7/ui-components/styles.css';
33
+ ```
20
34
 
21
- ## Entry points
22
-
23
- - `@api7/ui-components`: components, hooks and `ConfigProvider`.
24
- - `@api7/ui-components/form`: form components built on TanStack Form. Needs the optional peer dependency `@tanstack/react-form`.
25
- - `@api7/ui-components/data-table`: the data table built on TanStack Table. Needs the optional peer dependency `@tanstack/react-table`.
26
- - `@api7/ui-components/tokens`: the design token data (`palette`, `themes`, `FAMILIES`, `STEPS` and the contrast helpers `AA`, `semanticPairs`, `badgePairs`) for documentation pages. The CSS generators stay internal.
27
- - `@api7/ui-components/styles.css`: the precompiled stylesheet.
35
+ 2. Load a font for `--asu-font-sans`. It is Inter by default. For example, install `@fontsource-variable/inter` (`npm install @fontsource-variable/inter`) and import it in the same entry file:
28
36
 
29
- ## Tokens
37
+ ```ts
38
+ import '@fontsource-variable/inter';
39
+ ```
30
40
 
31
- Token data lives in `src/tokens/`. After changing it, run `pnpm --filter @api7/ui-components tokens` to regenerate `src/theme.css` and `packages/storybook/.storybook/story-theme.css`. Never edit either file by hand; a test fails when one is out of date.
41
+ To use another font, override the variable:
32
42
 
33
- `culori` is a runtime dependency because the public tokens entry builds the palette with it when it is imported.
43
+ ```css
44
+ :root {
45
+ --asu-font-sans: 'Your Font', sans-serif;
46
+ }
47
+ ```
34
48
 
35
- ## Tests
49
+ 3. Use the components. Render `Toaster` once if you use `toast`, and wrap the application in `ConfigProvider` if you need a locale other than `en-US`:
36
50
 
37
- `vitest.config.ts` has two projects: `unit` (Node) and `browser` (every `*.test.tsx`, in headless Chromium through Playwright). Run one with `pnpm exec vitest run --project browser`. Install the browser once with `pnpm exec playwright install chromium`. The stories are tested in [`packages/storybook`](../storybook/README.md).
51
+ ```tsx
52
+ import { Button, ConfigProvider, Toaster, toast } from '@api7/ui-components';
38
53
 
39
- The browser project has a 30 second test timeout, and on CI (`CI` set) a failed test is retried twice. A test that passes only on a retry is reported as flaky in the run output, so treat that as a bug to fix, not as noise. A test file that cannot be imported is not retried.
54
+ export function App() {
55
+ return (
56
+ <ConfigProvider locale="zh-CN">
57
+ <Button onClick={() => toast.success('Saved', { description: 'Your changes were stored.' })}>Save</Button>
58
+ <Toaster />
59
+ </ConfigProvider>
60
+ );
61
+ }
62
+ ```
40
63
 
41
- Two things make browser tests slow or flaky:
64
+ `ConfigProvider` accepts `locale` (`en-US` or `zh-CN`) and `messages`, an object that overrides the built-in texts, such as the loading label of a button, the close buttons, the empty state of the data table and the pagination labels. Define `messages` at module scope or memoize it.
42
65
 
43
- - **Do not click an element that is meant to be disabled with a plain `userEvent.click`.** Playwright waits for the element to become enabled until the action timeout, and a `.catch` around it only hides the wait, so the test always takes as long as the timeout. Click with `{ force: true }` and assert that nothing happened.
44
- - A test that takes seconds on a workstation can fail on a slower runner. Check the slowest tests with `--reporter=verbose` after adding one, a good browser test finishes in well under a second, and only fuzz style tests run for a few seconds.
45
-
46
- ## Releasing
66
+ ## Entry points
47
67
 
48
- Releases are made with Changesets from the repository root. See [Releasing](../../CONTRIBUTING.md#releasing).
68
+ | Import | Contents |
69
+ | -------------------------------- | ------------------------------------------------------------------------------------------------------------- |
70
+ | `@api7/ui-components` | Components, `toast` and `Toaster`, `ConfigProvider`, `useLocale` and `useMessages` |
71
+ | `@api7/ui-components/form` | Form components built on TanStack Form |
72
+ | `@api7/ui-components/data-table` | The data table built on TanStack Table |
73
+ | `@api7/ui-components/tokens` | Design token data (`palette`, `themes`, `FAMILIES`, `STEPS` and the contrast helpers) for documentation pages |
74
+ | `@api7/ui-components/styles.css` | The precompiled stylesheet |
75
+
76
+ The package is ESM only. Component modules keep their `"use client"` directive, so the components work in a React Server Components setup such as the Next.js app router.
77
+
78
+ ## Buttons
79
+
80
+ `Button` takes a `variant`: `primary` (the default), `secondary`, `outline`, `ghost`, `destructive` or `link`. It takes a `size`: `sm`, `md` (the default), `lg` or `icon`. `loading` disables the button and shows a spinner, and `loadingLabel` sets the text that screen readers announce.
81
+
82
+ ```tsx
83
+ import { Button } from '@api7/ui-components';
84
+
85
+ export function Actions() {
86
+ return (
87
+ <>
88
+ <Button>Save</Button>
89
+ <Button variant="outline" size="sm">
90
+ Cancel
91
+ </Button>
92
+ <Button variant="destructive" loading loadingLabel="Deleting">
93
+ Delete
94
+ </Button>
95
+ </>
96
+ );
97
+ }
98
+ ```
99
+
100
+ A link that looks like a button is an ordinary anchor or router link styled with `buttonVariants`. Give it `data-slot="button"` so the library's CSS reset applies to it:
101
+
102
+ ```tsx
103
+ import { buttonVariants } from '@api7/ui-components';
104
+
105
+ export function DocsLink() {
106
+ return (
107
+ <a href="/docs" data-slot="button" className={buttonVariants({ variant: 'outline' })}>
108
+ Docs
109
+ </a>
110
+ );
111
+ }
112
+ ```
113
+
114
+ ## Forms
115
+
116
+ `@api7/ui-components/form` wraps TanStack Form. `useAppForm` returns a form whose `AppField` hands you ready made fields: `TextField`, `TextareaField`, `NumberField`, `SelectField`, `ComboboxField`, `DatePickerField`, `DateRangePickerField`, `CheckboxField`, `SwitchField` and `RadioGroupField`:
117
+
118
+ ```tsx
119
+ import { Button } from '@api7/ui-components';
120
+ import { useAppForm } from '@api7/ui-components/form';
121
+
122
+ export function NameForm({ onSave }: { onSave: (name: string) => void }) {
123
+ const form = useAppForm({
124
+ defaultValues: { name: '' },
125
+ onSubmit: ({ value }) => onSave(value.name),
126
+ });
127
+
128
+ return (
129
+ <form
130
+ noValidate
131
+ onSubmit={(event) => {
132
+ event.preventDefault();
133
+ void form.handleSubmit();
134
+ }}
135
+ >
136
+ <form.AppField name="name" validators={{ onChange: ({ value }) => (value ? undefined : 'Name is required') }}>
137
+ {(field) => <field.TextField label="Name" />}
138
+ </form.AppField>
139
+ <Button type="submit">Save</Button>
140
+ </form>
141
+ );
142
+ }
143
+ ```
144
+
145
+ Validators are the ones of TanStack Form, so a function or a Standard Schema such as a zod schema both work. A string returned by a validator is shown under the field.
146
+
147
+ ## Theming
148
+
149
+ Theme colors, radii and the font are CSS variables with the `--asu-` prefix, for example `--asu-primary`. Override them on `:root` to change the palette. Only a light theme ships. The stylesheet also reads `[data-theme=dark]`, so a dark palette can be supplied by an application that sets those variables on that selector.
150
+
151
+ `className` on a component is passed to its element for your own classes. The library's component rules are not placed in a cascade layer, so styles of yours that are in a layer, such as the utilities of Tailwind CSS, cannot override what a component already sets. Your own rules that are not in a layer compete by specificity and source order as usual, so import the library stylesheet first, as the quick start says, and use a selector that is specific enough.
152
+
153
+ ### Using it next to Tailwind CSS
154
+
155
+ Every utility class in the library carries the `asu:` prefix and every variable the `--asu-` prefix, so an application that uses Tailwind itself can load both without clashes.
156
+
157
+ The CSS reset applies only inside library components (`[data-slot]` elements and their descendants), so the rest of the page keeps its own styles.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@api7/ui-components",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "API7 React component library",
5
5
  "type": "module",
6
6
  "sideEffects": [