gbs-add-block 2.0.1 → 2.0.2
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/.gbs/skills/gbs-components/SKILL.md +132 -0
- package/.gbs/skills/gbs-components/references/accessibility.md +102 -0
- package/.gbs/skills/gbs-components/references/data-display.md +185 -0
- package/.gbs/skills/gbs-components/references/data-grid.md +117 -0
- package/.gbs/skills/gbs-components/references/forms.md +202 -0
- package/.gbs/skills/gbs-components/references/install.md +190 -0
- package/.gbs/skills/gbs-components/references/overlays.md +209 -0
- package/.gbs/skills/gbs-components/references/pickers.md +83 -0
- package/.gbs/skills/gbs-components/references/styling.md +180 -0
- package/.gbs/skills/gbs-components/references/toaster.md +58 -0
- package/README.md +42 -19
- package/index.cjs +1019 -665
- package/package.json +3 -2
- package/source/beta-components/data-grid/README.md +4 -3
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Styling
|
|
2
|
+
|
|
3
|
+
"Headless" here means the components own behaviour and accessibility and ship a
|
|
4
|
+
default look you can replace at three levels: CSS variables, slot classes, and
|
|
5
|
+
state attributes.
|
|
6
|
+
|
|
7
|
+
## 1. Stylesheets are per component
|
|
8
|
+
|
|
9
|
+
Each folder has its own `styles.css`. Import the ones you use, once, anywhere:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import "component-lib/button/styles.css";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
or from a root stylesheet:
|
|
16
|
+
|
|
17
|
+
```css
|
|
18
|
+
@import "../component-lib/button/styles.css";
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Nothing renders correctly without it — the components emit class names only.
|
|
22
|
+
|
|
23
|
+
## 2. Theme with `--gbs-*` on `:root`
|
|
24
|
+
|
|
25
|
+
One set of variables themes every component at once. This is the whole theming
|
|
26
|
+
API; reach for the other levels only when it is not enough.
|
|
27
|
+
|
|
28
|
+
```css
|
|
29
|
+
:root {
|
|
30
|
+
--gbs-accent: #7c3aed;
|
|
31
|
+
--gbs-accent-soft: #f3e8ff;
|
|
32
|
+
--gbs-radius: 10px;
|
|
33
|
+
--gbs-font-size: 14px;
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Set them on `:root`, not inside a component — components read them through
|
|
38
|
+
inheritance, so anything set on an ancestor reaches every control beneath it.
|
|
39
|
+
|
|
40
|
+
### Resolution order
|
|
41
|
+
|
|
42
|
+
Each component variable falls through this chain, stopping at the first set:
|
|
43
|
+
|
|
44
|
+
1. **The component's own variable** — `--in-accent`, `--dg-accent`, `--ck-border`.
|
|
45
|
+
Set this to change one component, or one instance.
|
|
46
|
+
2. **The shared variable** — `--gbs-accent`. The one you normally set.
|
|
47
|
+
3. **The DataGrid's variable** — `--dg-accent`, when the grid's stylesheet is
|
|
48
|
+
loaded. Kept for projects that themed the grid before the shared variables existed.
|
|
49
|
+
4. **The built-in default** — a `light-dark()` pair, so it follows the page's
|
|
50
|
+
colour scheme.
|
|
51
|
+
|
|
52
|
+
```css
|
|
53
|
+
.in-root { --in-accent: var(--gbs-accent, var(--dg-accent, light-dark(#2563eb, #60a5fa))); }
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### The shared variables
|
|
57
|
+
|
|
58
|
+
Defaults written light / dark.
|
|
59
|
+
|
|
60
|
+
**Surfaces and text:** `--gbs-bg` (`#ffffff`/`#0b0b0e`), `--gbs-fg`
|
|
61
|
+
(`#18181b`/`#f4f4f5`), `--gbs-muted` (`#71717a`/`#a1a1aa`), `--gbs-subtle`
|
|
62
|
+
(`#f4f4f5`/`#1c1c20`), `--gbs-hover` (`#f4f4f5`/`#1f1f23`), `--gbs-input-bg`
|
|
63
|
+
(`#ffffff`/`#121216`), `--gbs-readonly-bg` (`#fafafa`/`#0e0e12`),
|
|
64
|
+
`--gbs-header-bg` (`#fafafa`/`#111114`), `--gbs-header-fg` (`#3f3f46`/`#d4d4d8`).
|
|
65
|
+
|
|
66
|
+
**Borders and shape:** `--gbs-border` (`#e4e4e7`/`#27272a`),
|
|
67
|
+
`--gbs-border-subtle` (`#f0f0f2`/`#1c1c20`), `--gbs-border-control`
|
|
68
|
+
(`#a1a1aa`/`#52525b`), `--gbs-radius` (`8px`), `--gbs-font-size` (`13px`),
|
|
69
|
+
`--gbs-shadow`, `--gbs-backdrop`.
|
|
70
|
+
|
|
71
|
+
**Accent and status:** `--gbs-accent`, `--gbs-accent-soft`,
|
|
72
|
+
`--gbs-accent-strong`, `--gbs-accent-fg`, `--gbs-focus`, `--gbs-danger`,
|
|
73
|
+
`--gbs-danger-fg`, `--gbs-success`, `--gbs-warning`, `--gbs-info`.
|
|
74
|
+
|
|
75
|
+
**Grid-specific:** `--gbs-row-alt`, `--gbs-row-hover`, `--gbs-row-selected`,
|
|
76
|
+
`--gbs-row-selected-hover`, `--gbs-cell-px`, `--gbs-pin-shadow`,
|
|
77
|
+
`--gbs-skeleton`, `--gbs-tab-fg`, `--gbs-tooltip-bg`, `--gbs-tooltip-fg`.
|
|
78
|
+
|
|
79
|
+
### Per-component prefixes
|
|
80
|
+
|
|
81
|
+
To change one component only, set its own prefix on its root class:
|
|
82
|
+
|
|
83
|
+
| Component | Prefix | Root class |
|
|
84
|
+
| --- | --- | --- |
|
|
85
|
+
| DataGrid | `--dg-*` | `.dg-root` |
|
|
86
|
+
| Combobox | `--cb-*` | `.cb-root` |
|
|
87
|
+
| Toaster | `--ts-*` | `.ts-region` |
|
|
88
|
+
| Input | `--in-*` | `.in-root` |
|
|
89
|
+
| Button | `--bt-*` | `.bt-root` |
|
|
90
|
+
|
|
91
|
+
```css
|
|
92
|
+
.cb-root { --cb-accent: #7c3aed; --cb-radius: 12px; }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Toasts render on `<body>`, so grid/shared values they inherit must be set on
|
|
96
|
+
`:root`.
|
|
97
|
+
|
|
98
|
+
## 3. Slot classes
|
|
99
|
+
|
|
100
|
+
`className` goes to the root element only. To reach an inner part, use
|
|
101
|
+
`classNames`, a map of slot name to class string:
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
<Input label="Email" classNames={{ root: "mb-4", label: "font-semibold", input: "font-mono" }} />
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Slots are per component and listed in each `react/props.ts` and in this skill's
|
|
108
|
+
`forms.md` / `overlays.md` / `data-display.md`. Passing a slot that does not
|
|
109
|
+
exist is silently ignored, so check the list.
|
|
110
|
+
|
|
111
|
+
Classes are joined with `cx` from `shared/core/cx.ts`, which drops falsy values
|
|
112
|
+
— a conditional that evaluates to `undefined` contributes nothing.
|
|
113
|
+
|
|
114
|
+
## 4. Tailwind
|
|
115
|
+
|
|
116
|
+
Every `styles.css` declares:
|
|
117
|
+
|
|
118
|
+
```css
|
|
119
|
+
@layer theme, base, components, utilities;
|
|
120
|
+
@layer components { /* the component's rules */ }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Component rules live in the `components` layer, so **Tailwind utilities passed
|
|
124
|
+
through `className` / `classNames` win** without `!important`. That is the
|
|
125
|
+
supported way to adjust spacing, typography and layout.
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
<Button className="w-full sm:w-auto" classNames={{ content: "gap-3" }}>Save</Button>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Do not use `!important`, and do not write selectors against internal class names
|
|
132
|
+
(`.bt-root`, `.dg-cell`) in app CSS — they are implementation detail. Use the
|
|
133
|
+
variables or the slots.
|
|
134
|
+
|
|
135
|
+
## 5. State attributes
|
|
136
|
+
|
|
137
|
+
Components expose their state as `data-*` attributes, so you can style states
|
|
138
|
+
without tracking them in React.
|
|
139
|
+
|
|
140
|
+
| Attribute | Where |
|
|
141
|
+
| --- | --- |
|
|
142
|
+
| `data-state="open"` / `"closing"` | Combobox, Popover, Menu, Modal, toasts |
|
|
143
|
+
| `data-side` | Popover, Menu, Tooltip — the side it settled on after flipping |
|
|
144
|
+
| `data-size` | Controls that take a `size` |
|
|
145
|
+
| `data-invalid`, `data-disabled` | Form controls |
|
|
146
|
+
| `data-active`, `data-selected` | Combobox options, grid cells and rows |
|
|
147
|
+
| `data-editing`, `data-pinned`, `data-density` | DataGrid |
|
|
148
|
+
| `data-type`, `data-custom`, `data-swiping` | Toasts |
|
|
149
|
+
| `data-position` | Toaster region |
|
|
150
|
+
| `aria-sort` | DataGrid header cells |
|
|
151
|
+
|
|
152
|
+
```css
|
|
153
|
+
.cb-option[data-active] { outline: 2px solid var(--gbs-focus); }
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## 6. Dark mode
|
|
157
|
+
|
|
158
|
+
Colours are `light-dark()` pairs driven by the page's `color-scheme`, so the
|
|
159
|
+
default is whatever the device prefers. To pin it, set `color-scheme` — the
|
|
160
|
+
components follow:
|
|
161
|
+
|
|
162
|
+
```css
|
|
163
|
+
:root { color-scheme: light dark; } /* follow the device */
|
|
164
|
+
:root[data-theme="dark"] { color-scheme: dark; }
|
|
165
|
+
:root[data-theme="light"] { color-scheme: light; }
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The DataGrid additionally treats a `.dark` or `[data-theme="dark"]` ancestor as
|
|
169
|
+
forcing a scheme.
|
|
170
|
+
|
|
171
|
+
Do not maintain a second palette for dark mode. Override the `--gbs-*` variables
|
|
172
|
+
with `light-dark()` pairs, or set them inside your own `[data-theme="dark"]`
|
|
173
|
+
block, and every component follows.
|
|
174
|
+
|
|
175
|
+
## 7. Right-to-left
|
|
176
|
+
|
|
177
|
+
The components use logical properties and read `dir` from the document, so RTL
|
|
178
|
+
works without configuration. Arrow keys in Menu, Switch and Tabs mirror
|
|
179
|
+
automatically. The Toaster takes an explicit `dir` prop if one region needs to
|
|
180
|
+
differ from the page.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Toaster and toast
|
|
2
|
+
|
|
3
|
+
Notifications. `toast()` is callable from anywhere — components, event
|
|
4
|
+
handlers, data layers, even outside React. No hook, context or provider.
|
|
5
|
+
|
|
6
|
+
Mount `<Toaster />` **once**; call `toast()` from anywhere — components, event
|
|
7
|
+
handlers, data layers, even outside React. No hook, context or provider.
|
|
8
|
+
|
|
9
|
+
**Import from one path everywhere.** `toast()` and `<Toaster />` meet through a
|
|
10
|
+
shared module-level store; two import paths can create two stores.
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
// once, near the root
|
|
14
|
+
import { Toaster } from "component-lib/toaster";
|
|
15
|
+
import "component-lib/toaster/styles.css";
|
|
16
|
+
<Toaster />
|
|
17
|
+
|
|
18
|
+
// anywhere
|
|
19
|
+
import { toast } from "component-lib/toaster";
|
|
20
|
+
|
|
21
|
+
toast("Event created", { description: "Monday, 10:00" });
|
|
22
|
+
toast.success("Saved");
|
|
23
|
+
toast.error("Upload failed", { action: { label: "Retry", onClick: retry } });
|
|
24
|
+
toast.warning("Storage almost full");
|
|
25
|
+
toast.info("New version available");
|
|
26
|
+
const id = toast.loading("Uploading…"); // stays until updated
|
|
27
|
+
toast.update(id, { type: "success", title: "Uploaded" });
|
|
28
|
+
toast.dismiss(id); // or toast.dismiss() for all
|
|
29
|
+
|
|
30
|
+
toast.promise(saveUser(data), {
|
|
31
|
+
loading: "Saving…",
|
|
32
|
+
success: (user) => `${user.name} saved`,
|
|
33
|
+
error: (error) => `Could not save: ${(error as Error).message}`,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
toast.custom(({ dismiss }) => <MyCard onClose={dismiss} />);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Every call returns the toast's id; reusing an on-screen id updates that toast.
|
|
40
|
+
|
|
41
|
+
**Toast options:** `id`, `type` (`default` `success` `error` `warning` `info`
|
|
42
|
+
`loading`), `description`, `duration` (5000; `0`/`Infinity` stays),
|
|
43
|
+
`dismissible`, `action` / `cancel` (`{ label, onClick }`), `icon`, `className`,
|
|
44
|
+
`render`, `onDismiss`, `onAutoClose`.
|
|
45
|
+
|
|
46
|
+
**Toaster props:** `position` (`top-right`), `limit` (3), `duration` (5000),
|
|
47
|
+
`closeButton` (true), `hotkey` (`["altKey","KeyT"]`), `icons`, `store`, `dir`,
|
|
48
|
+
`className`, `classNames`, `style`, `localeText`.
|
|
49
|
+
|
|
50
|
+
Slots: `region`, `list`, `toast`, `icon`, `content`, `title`, `description`,
|
|
51
|
+
`actions`, `action`, `cancel`, `close`.
|
|
52
|
+
|
|
53
|
+
Timers pause while the pointer is over the stack, while focus is inside it, and
|
|
54
|
+
while the tab is hidden. The list is a polite live region; error toasts use
|
|
55
|
+
`role="alert"`. **Alt+T** moves focus to the notifications.
|
|
56
|
+
|
|
57
|
+
`toast()` does nothing during a server render — call it in the browser, e.g.
|
|
58
|
+
after a Server Action resolves.
|
package/README.md
CHANGED
|
@@ -1,19 +1,42 @@
|
|
|
1
|
-
# GBS Building Blocks 2.0 (v2.0.
|
|
2
|
-
|
|
3
|
-
Latest and upgraded version of GBS building blocks with headless UI and removed dependencies.
|
|
4
|
-
|
|
5
|
-
## Documentation
|
|
6
|
-
|
|
7
|
-
For detailed documentation on usage and props, Please visit: [Building Block Documentation](https://gramprokit.vercel.app)
|
|
8
|
-
|
|
9
|
-
## Beta Components
|
|
10
|
-
|
|
11
|
-
New 2.0.0 beta (current version) is available for testing and feedback, Please visit: [Building Block Documentation v2.0.0 beta](https://gramprokit.vercel.app)
|
|
12
|
-
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
1
|
+
# GBS Building Blocks 2.0 (v2.0.2)
|
|
2
|
+
|
|
3
|
+
Latest and upgraded version of GBS building blocks with headless UI and removed dependencies.
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
For detailed documentation on usage and props, Please visit: [Building Block Documentation](https://gramprokit.vercel.app)
|
|
8
|
+
|
|
9
|
+
## Beta Components
|
|
10
|
+
|
|
11
|
+
New 2.0.0 beta (current version) is available for testing and feedback, Please visit: [Building Block Documentation v2.0.0 beta](https://gramprokit.vercel.app)
|
|
12
|
+
|
|
13
|
+
## Agent skill
|
|
14
|
+
|
|
15
|
+
Install the skill once per project so a coding agent uses these components
|
|
16
|
+
correctly instead of guessing at the API:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx gbs-add-block@latest -skill
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
It writes the skill at the root of the project you run it in, in the place each
|
|
23
|
+
agent looks:
|
|
24
|
+
|
|
25
|
+
| Agent | Gets |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| GBS SE Agent | `.gbs/skills/gbs-components/` (canonical) |
|
|
28
|
+
| Claude Code | `.claude/skills/gbs-components/` |
|
|
29
|
+
| Antigravity | `.agents/rules/gbs-components.md` |
|
|
30
|
+
| Codex | a marked block in `AGENTS.md` |
|
|
31
|
+
|
|
32
|
+
Pick a subset with `--for claude,codex`, or `--for none` for just `.gbs/`.
|
|
33
|
+
Commit the result so everyone's agent picks it up. Re-run to update; a file you
|
|
34
|
+
have edited is never replaced without `--force`.
|
|
35
|
+
|
|
36
|
+
## What's New 🎉 (Ver 2.0.2)
|
|
37
|
+
|
|
38
|
+
- Update Candidate for next major change 2.0.0
|
|
39
|
+
|
|
40
|
+
## Authors
|
|
41
|
+
|
|
42
|
+
- [@anandhuremanan](https://www.github.com/anandhuremanan)
|