gbs-add-block 2.0.1 → 2.0.3

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