@egose/shadcn-theme-ng-tw 0.1.0 → 0.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 +1 -1
- package/accordion/README.md +405 -2
- package/alert/README.md +372 -2
- package/alert-dialog/README.md +471 -5
- package/aspect-ratio/README.md +272 -5
- package/autocomplete/README.md +502 -2
- package/avatar/README.md +357 -5
- package/badge/README.md +318 -2
- package/basic-alert/README.md +353 -2
- package/breadcrumb/README.md +406 -5
- package/button/README.md +482 -2
- package/button/fesm2022/button.mjs +85 -107
- package/button/types/button.d.ts +5 -8
- package/button-group/README.md +318 -5
- package/button-group/fesm2022/button-group.mjs +1 -1
- package/calendar/README.md +357 -2
- package/card/README.md +331 -5
- package/carousel/README.md +333 -5
- package/carousel/fesm2022/carousel.mjs +4 -1
- package/checkbox/README.md +320 -2
- package/collapsible/README.md +332 -5
- package/combobox/README.md +507 -5
- package/combobox/fesm2022/combobox.mjs +4 -1
- package/command/README.md +435 -5
- package/confirmation-dialog/README.md +301 -2
- package/context-menu/README.md +366 -5
- package/date-picker/README.md +465 -2
- package/date-picker/fesm2022/date-picker.mjs +2 -2
- package/dialog/README.md +448 -2
- package/drawer/README.md +395 -5
- package/dropdown-menu/README.md +417 -5
- package/empty/README.md +329 -5
- package/field/README.md +385 -5
- package/form-checkbox/README.md +312 -2
- package/form-date-picker/README.md +322 -2
- package/form-field/README.md +356 -2
- package/form-field-simple/README.md +340 -2
- package/form-searchable-multiselect/README.md +361 -2
- package/form-select/README.md +350 -2
- package/form-text-input/README.md +371 -2
- package/form-textarea/README.md +347 -2
- package/hover-card/README.md +256 -5
- package/icon/README.md +239 -2
- package/input/README.md +269 -2
- package/input-group/README.md +335 -5
- package/input-group/fesm2022/input-group.mjs +3 -3
- package/input-otp/README.md +375 -5
- package/item/README.md +385 -5
- package/item/fesm2022/item.mjs +3 -3
- package/kbd/README.md +291 -5
- package/label/README.md +272 -2
- package/layout-simple/README.md +193 -2
- package/layout-simple/fesm2022/layout-simple.mjs +877 -409
- package/layout-simple/types/layout-simple.d.ts +174 -137
- package/menu/README.md +417 -2
- package/menubar/README.md +343 -5
- package/native-select/README.md +323 -5
- package/navigation-menu/README.md +369 -5
- package/package.json +1 -1
- package/pagination/README.md +388 -5
- package/popover/README.md +331 -2
- package/progress/README.md +311 -5
- package/radio-group/README.md +364 -2
- package/radio-group/fesm2022/radio-group.mjs +5 -1
- package/resizable/README.md +269 -5
- package/scroll-area/README.md +233 -5
- package/searchable-multiselect/README.md +323 -2
- package/select/README.md +437 -2
- package/separator/README.md +222 -2
- package/sheet/README.md +311 -2
- package/sidebar/README.md +457 -5
- package/skeleton/README.md +217 -5
- package/slider/README.md +273 -5
- package/slider/fesm2022/slider.mjs +17 -13
- package/sonner/README.md +346 -2
- package/spinner/README.md +284 -2
- package/switch/README.md +310 -2
- package/table/README.md +423 -5
- package/tabs/README.md +411 -2
- package/tabs/fesm2022/tabs.mjs +12 -2
- package/textarea/README.md +282 -5
- package/toggle/README.md +270 -5
- package/toggle-group/README.md +340 -5
- package/tooltip/README.md +269 -2
- package/typography/README.md +271 -5
- package/utils/README.md +303 -2
package/toggle-group/README.md
CHANGED
|
@@ -1,11 +1,346 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Toggle Group (`@egose/shadcn-theme-ng/toggle-group`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A set of related two-state buttons, equivalent to [shadcn/ui Toggle Group](https://ui.shadcn.com/docs/components/toggle-group). This subpath ships `HlmToggleGroup` (container, `[hlmToggleGroup]` / `<hlm-toggle-group>`) and `HlmToggleGroupItem` (member, `button[hlmToggleGroupItem]`) over spartan-ng's `BrnToggleGroup` / `BrnToggleGroupItem` primitives, plus the `HlmToggleGroupToken` injection context (`injectHlmToggleGroup()`, `provideHlmToggleGroup()`). Sizing/variant cascade from the group to items via DI; item-level inputs override the group.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> **Ships as:** `@egose/shadcn-theme-ng/toggle-group` and `@egose/shadcn-theme-ng-tw/toggle-group` (the `tw:`-prefixed Tailwind variant). See the [package README](../../README.md) for install steps, peer dependencies, Tailwind setup, and testing/release guidance. Do not publish this project directory independently.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Installation
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
10
|
+
# Plain Tailwind (no prefix)
|
|
11
|
+
npm install @egose/shadcn-theme-ng
|
|
12
|
+
|
|
13
|
+
# Or the tw:-prefixed variant
|
|
14
|
+
npm install @egose/shadcn-theme-ng-tw
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`@spartan-ng/brain` and `@egose/shadcn-theme-ng/toggle` (for `toggleVariants`) arrive transitively. See the [package README](../../README.md) for the full peer-dependency table.
|
|
18
|
+
|
|
19
|
+
## Imports
|
|
20
|
+
|
|
21
|
+
All public symbols are re-exported from `projects/toggle-group/src/public-api.ts`:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import {
|
|
25
|
+
HlmToggleGroup,
|
|
26
|
+
HlmToggleGroupImports,
|
|
27
|
+
HlmToggleGroupItem,
|
|
28
|
+
HlmToggleGroupModule,
|
|
29
|
+
HlmToggleGroupToken,
|
|
30
|
+
injectHlmToggleGroup,
|
|
31
|
+
provideHlmToggleGroup,
|
|
32
|
+
} from '@egose/shadcn-theme-ng/toggle-group';
|
|
33
|
+
import type { HlmToggleGroupContext } from '@egose/shadcn-theme-ng/toggle-group';
|
|
34
|
+
// tw variant: swap to '@egose/shadcn-theme-ng-tw/toggle-group'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Standalone-component usage (preferred):
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { Component } from '@angular/core';
|
|
41
|
+
import { HlmToggleGroupImports } from '@egose/shadcn-theme-ng/toggle-group';
|
|
42
|
+
|
|
43
|
+
@Component({
|
|
44
|
+
selector: 'app-demo',
|
|
45
|
+
standalone: true,
|
|
46
|
+
imports: [...HlmToggleGroupImports],
|
|
47
|
+
template: `
|
|
48
|
+
<div hlmToggleGroup>
|
|
49
|
+
<button hlmToggleGroupItem value="a">A</button>
|
|
50
|
+
</div>
|
|
51
|
+
`,
|
|
52
|
+
})
|
|
53
|
+
export class DemoComponent {}
|
|
11
54
|
```
|
|
55
|
+
|
|
56
|
+
NgModule usage:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { NgModule } from '@angular/core';
|
|
60
|
+
import { HlmToggleGroupModule } from '@egose/shadcn-theme-ng/toggle-group';
|
|
61
|
+
|
|
62
|
+
@NgModule({ imports: [HlmToggleGroupModule] })
|
|
63
|
+
export class FeatureModule {}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
| Symbol | Kind | Description |
|
|
67
|
+
| ------------------------- | ---------------- | ------------------------------------------------------------------------ |
|
|
68
|
+
| `HlmToggleGroup` | Directive | Container: `[hlmToggleGroup], hlm-toggle-group`. Provides group context. |
|
|
69
|
+
| `HlmToggleGroupItem` | Directive | Member: `button[hlmToggleGroupItem]`. Inherits group variant/size. |
|
|
70
|
+
| `HlmToggleGroupToken` | `InjectionToken` | DI token for `HlmToggleGroupContext` (variant/size/spacing). |
|
|
71
|
+
| `injectHlmToggleGroup()` | Function | Injects the parent group context (for custom items). |
|
|
72
|
+
| `provideHlmToggleGroup()` | Function | Provides the group context for a custom container. |
|
|
73
|
+
| `HlmToggleGroupContext` | Interface (type) | `{ variant, size, spacing }` input signals shared via DI. |
|
|
74
|
+
| `HlmToggleGroupImports` | `const` array | `[HlmToggleGroup, HlmToggleGroupItem]`. |
|
|
75
|
+
| `HlmToggleGroupModule` | NgModule | Imports + re-exports both directives. |
|
|
76
|
+
|
|
77
|
+
## Anatomy / Structure
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<!-- single-select formatting group -->
|
|
81
|
+
<div hlmToggleGroup type="single" variant="outline" size="default">
|
|
82
|
+
<button hlmToggleGroupItem value="bold" aria-label="Toggle bold">B</button>
|
|
83
|
+
<button hlmToggleGroupItem value="italic" aria-label="Toggle italic">I</button>
|
|
84
|
+
<button hlmToggleGroupItem value="underline" aria-label="Toggle underline">U</button>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<!-- multi-select with spacing + vertical orientation -->
|
|
88
|
+
<div hlmToggleGroup type="multiple" variant="outline" [spacing]="1" orientation="vertical">
|
|
89
|
+
<button hlmToggleGroupItem value="left" aria-label="Align left">L</button>
|
|
90
|
+
<button hlmToggleGroupItem value="center" aria-label="Align center">C</button>
|
|
91
|
+
<button hlmToggleGroupItem value="right" aria-label="Align right">R</button>
|
|
92
|
+
</div>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
> Items must be `<button hlmToggleGroupItem value="…">`. The group `type` is `'single' | 'multiple'` (from Brn); omit `type` only for uncontrolled demos.
|
|
96
|
+
|
|
97
|
+
## API reference
|
|
98
|
+
|
|
99
|
+
### `HlmToggleGroup` — selector `[hlmToggleGroup], hlm-toggle-group` (directive, hosts `BrnToggleGroup`)
|
|
100
|
+
|
|
101
|
+
Own styling inputs:
|
|
102
|
+
|
|
103
|
+
| Input | Type | Default | Description |
|
|
104
|
+
| ------------- | ------------------------------------------------------ | -------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
105
|
+
| `variant` | `ToggleVariants['variant']` (`'default' \| 'outline'`) | `'default'` | Cascades to items (item input wins when set). Reflected to `data-variant`. |
|
|
106
|
+
| `size` | `ToggleVariants['size']` (`'default' \| 'sm' \| 'lg'`) | `'default'` | Cascades to items. Reflected to `data-size`. |
|
|
107
|
+
| `spacing` | `number` (coerced with `numberAttribute`) | `0` | Gap level. Reflected to `data-spacing` + `--gap` (`gap-[--spacing(var(--gap))]`). `0` = joined segmented control. |
|
|
108
|
+
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Layout direction. Reflected to `data-orientation`. |
|
|
109
|
+
|
|
110
|
+
Forwarded to `BrnToggleGroup` via `hostDirectives`:
|
|
111
|
+
|
|
112
|
+
| Input / Output | Direction | Description |
|
|
113
|
+
| -------------- | --------- | ------------------------------------------------------------- |
|
|
114
|
+
| `type` | input | `'single' \| 'multiple'` selection mode. |
|
|
115
|
+
| `value` | input | Current value(s). Supports two-way binding. |
|
|
116
|
+
| `nullable` | input | (single mode) whether deselecting the active item is allowed. |
|
|
117
|
+
| `disabled` | input | Disables the whole group. |
|
|
118
|
+
| `valueChange` | output | Emits when the group value changes. |
|
|
119
|
+
|
|
120
|
+
Host: `data-slot="toggle-group"`, `flex w-fit` (column when `data-vertical`).
|
|
121
|
+
|
|
122
|
+
### `HlmToggleGroupItem` — selector `button[hlmToggleGroupItem]` (directive, hosts `BrnToggleGroupItem`)
|
|
123
|
+
|
|
124
|
+
| Input | Type | Default | Description |
|
|
125
|
+
| --------- | --------------------------- | ----------- | ----------------------------------------------------------------------------------------------------- |
|
|
126
|
+
| `variant` | `ToggleVariants['variant']` | `'default'` | Overrides the group variant when set (group wins when the group value is truthy — see surprise note). |
|
|
127
|
+
| `size` | `ToggleVariants['size']` | `'default'` | Overrides the group size when set (same precedence rule). |
|
|
128
|
+
|
|
129
|
+
Forwarded to `BrnToggleGroupItem`: `id`, `value` (required per item), `disabled`, `state`, `aria-label`, `type` inputs and `stateChange` output.
|
|
130
|
+
|
|
131
|
+
Host: `data-slot="toggle-group-item"`, reflects resolved `data-variant` / `data-size` and group `data-spacing`. Styling = item overrides + `toggleVariants({ variant, size })`.
|
|
132
|
+
|
|
133
|
+
### Token helpers — `hlm-toggle-group.token.ts`
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
interface HlmToggleGroupContext {
|
|
137
|
+
readonly variant: InputSignal<ToggleVariants['variant']>;
|
|
138
|
+
readonly size: InputSignal<ToggleVariants['size']>;
|
|
139
|
+
readonly spacing: InputSignalWithTransform<number, NumberInput>;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`provideHlmToggleGroup(HlmToggleGroup)` is wired automatically on the group directive; call it manually only for custom container components. `injectHlmToggleGroup()` reads the parent context (throws outside a group).
|
|
144
|
+
|
|
145
|
+
## Examples
|
|
146
|
+
|
|
147
|
+
### 1. Basic single-select formatting group
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
// demo-basic.component.ts
|
|
151
|
+
import { Component } from '@angular/core';
|
|
152
|
+
import { HlmToggleGroupImports } from '@egose/shadcn-theme-ng/toggle-group';
|
|
153
|
+
import { NgIcon, provideIcons } from '@ng-icons/core';
|
|
154
|
+
import { lucideBold, lucideItalic, lucideUnderline } from '@ng-icons/lucide';
|
|
155
|
+
|
|
156
|
+
@Component({
|
|
157
|
+
selector: 'demo-basic',
|
|
158
|
+
standalone: true,
|
|
159
|
+
imports: [...HlmToggleGroupImports, NgIcon],
|
|
160
|
+
providers: [provideIcons({ lucideBold, lucideItalic, lucideUnderline })],
|
|
161
|
+
template: `
|
|
162
|
+
<div hlmToggleGroup type="single" variant="outline">
|
|
163
|
+
<button hlmToggleGroupItem value="bold" aria-label="Toggle bold"><ng-icon name="lucideBold" /></button>
|
|
164
|
+
<button hlmToggleGroupItem value="italic" aria-label="Toggle italic"><ng-icon name="lucideItalic" /></button>
|
|
165
|
+
<button hlmToggleGroupItem value="underline" aria-label="Toggle underline">
|
|
166
|
+
<ng-icon name="lucideUnderline" />
|
|
167
|
+
</button>
|
|
168
|
+
</div>
|
|
169
|
+
`,
|
|
170
|
+
})
|
|
171
|
+
export class DemoBasic {}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### 2. Controlled value (`value` / `valueChange`)
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
// demo-controlled.component.ts
|
|
178
|
+
import { Component, signal } from '@angular/core';
|
|
179
|
+
import { HlmToggleGroupImports } from '@egose/shadcn-theme-ng/toggle-group';
|
|
180
|
+
|
|
181
|
+
@Component({
|
|
182
|
+
selector: 'demo-controlled',
|
|
183
|
+
standalone: true,
|
|
184
|
+
imports: [...HlmToggleGroupImports],
|
|
185
|
+
template: `
|
|
186
|
+
<div hlmToggleGroup type="single" [value]="align()" (valueChange)="align.set($event)" variant="outline">
|
|
187
|
+
<button hlmToggleGroupItem value="left">Left</button>
|
|
188
|
+
<button hlmToggleGroupItem value="center">Center</button>
|
|
189
|
+
<button hlmToggleGroupItem value="right">Right</button>
|
|
190
|
+
</div>
|
|
191
|
+
<p class="text-sm text-muted-foreground">Align: {{ align() ?? 'none' }}</p>
|
|
192
|
+
`,
|
|
193
|
+
})
|
|
194
|
+
export class DemoControlled {
|
|
195
|
+
readonly align = signal<string | null>('left');
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Multi-select holds an array:
|
|
200
|
+
|
|
201
|
+
```html
|
|
202
|
+
<div hlmToggleGroup type="multiple" [value]="picked()" (valueChange)="picked.set($event)">
|
|
203
|
+
<button hlmToggleGroupItem value="a">A</button>
|
|
204
|
+
<button hlmToggleGroupItem value="b">B</button>
|
|
205
|
+
<button hlmToggleGroupItem value="c">C</button>
|
|
206
|
+
</div>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
readonly picked = signal<string[]>(['a']);
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 3. Sizes, spacing, and orientation
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
// demo-layout.component.ts
|
|
217
|
+
import { Component } from '@angular/core';
|
|
218
|
+
import { HlmToggleGroupImports } from '@egose/shadcn-theme-ng/toggle-group';
|
|
219
|
+
|
|
220
|
+
@Component({
|
|
221
|
+
selector: 'demo-layout',
|
|
222
|
+
standalone: true,
|
|
223
|
+
imports: [...HlmToggleGroupImports],
|
|
224
|
+
template: `
|
|
225
|
+
<!-- joined segmented control (spacing 0) -->
|
|
226
|
+
<div hlmToggleGroup type="single" variant="outline" size="sm">
|
|
227
|
+
<button hlmToggleGroupItem value="day">Day</button>
|
|
228
|
+
<button hlmToggleGroupItem value="week">Week</button>
|
|
229
|
+
<button hlmToggleGroupItem value="month">Month</button>
|
|
230
|
+
</div>
|
|
231
|
+
|
|
232
|
+
<!-- separated pills -->
|
|
233
|
+
<div hlmToggleGroup type="multiple" variant="default" [spacing]="2" class="mt-4">
|
|
234
|
+
<button hlmToggleGroupItem value="a">A</button>
|
|
235
|
+
<button hlmToggleGroupItem value="b">B</button>
|
|
236
|
+
<button hlmToggleGroupItem value="c">C</button>
|
|
237
|
+
</div>
|
|
238
|
+
|
|
239
|
+
<!-- vertical stack -->
|
|
240
|
+
<div hlmToggleGroup type="single" variant="outline" orientation="vertical" class="mt-4">
|
|
241
|
+
<button hlmToggleGroupItem value="top">Top</button>
|
|
242
|
+
<button hlmToggleGroupItem value="mid">Middle</button>
|
|
243
|
+
<button hlmToggleGroupItem value="bot">Bottom</button>
|
|
244
|
+
</div>
|
|
245
|
+
`,
|
|
246
|
+
})
|
|
247
|
+
export class DemoLayout {}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### 4. Disabled group / disabled item
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
// demo-disabled.component.ts
|
|
254
|
+
import { Component } from '@angular/core';
|
|
255
|
+
import { HlmToggleGroupImports } from '@egose/shadcn-theme-ng/toggle-group';
|
|
256
|
+
|
|
257
|
+
@Component({
|
|
258
|
+
selector: 'demo-disabled',
|
|
259
|
+
standalone: true,
|
|
260
|
+
imports: [...HlmToggleGroupImports],
|
|
261
|
+
template: `
|
|
262
|
+
<div hlmToggleGroup type="single" disabled variant="outline">
|
|
263
|
+
<button hlmToggleGroupItem value="a">A</button>
|
|
264
|
+
<button hlmToggleGroupItem value="b">B</button>
|
|
265
|
+
</div>
|
|
266
|
+
<div hlmToggleGroup type="single" variant="outline" class="mt-2">
|
|
267
|
+
<button hlmToggleGroupItem value="a">A</button>
|
|
268
|
+
<button hlmToggleGroupItem value="b" disabled>B (off)</button>
|
|
269
|
+
</div>
|
|
270
|
+
`,
|
|
271
|
+
})
|
|
272
|
+
export class DemoDisabled {}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### 5. Per-item variant/size override
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
// demo-override.component.ts
|
|
279
|
+
import { Component } from '@angular/core';
|
|
280
|
+
import { HlmToggleGroupImports } from '@egose/shadcn-theme-ng/toggle-group';
|
|
281
|
+
|
|
282
|
+
@Component({
|
|
283
|
+
selector: 'demo-override',
|
|
284
|
+
standalone: true,
|
|
285
|
+
imports: [...HlmToggleGroupImports],
|
|
286
|
+
template: `
|
|
287
|
+
<div hlmToggleGroup type="single" variant="outline" size="sm">
|
|
288
|
+
<button hlmToggleGroupItem value="a">A (group sm)</button>
|
|
289
|
+
<button hlmToggleGroupItem value="b" size="lg">B (own lg)</button>
|
|
290
|
+
</div>
|
|
291
|
+
`,
|
|
292
|
+
})
|
|
293
|
+
export class DemoOverride {}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
> Precedence surprise: `_variant = group.variant() || item.variant()` — the **group value wins whenever truthy**. Since both default to `'default'` (truthy), item overrides only take effect when the group variant/size is set to a falsy value or the group input is removed. In practice, set variant/size on the group _or_ per item, not both.
|
|
297
|
+
|
|
298
|
+
### 6. Advanced: custom item via `injectHlmToggleGroup()`
|
|
299
|
+
|
|
300
|
+
Build your own item that still follows the group:
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
// custom-item.component.ts
|
|
304
|
+
import { Component, computed } from '@angular/core';
|
|
305
|
+
import { hlm } from '@egose/shadcn-theme-ng/utils';
|
|
306
|
+
import { toggleVariants } from '@egose/shadcn-theme-ng/toggle';
|
|
307
|
+
import { injectHlmToggleGroup } from '@egose/shadcn-theme-ng/toggle-group';
|
|
308
|
+
|
|
309
|
+
@Component({
|
|
310
|
+
selector: 'button[customGroupItem]',
|
|
311
|
+
standalone: true,
|
|
312
|
+
template: `<ng-content />`,
|
|
313
|
+
host: { '[class]': 'classes()' },
|
|
314
|
+
})
|
|
315
|
+
export class CustomGroupItem {
|
|
316
|
+
private readonly group = injectHlmToggleGroup(); // must sit inside [hlmToggleGroup]
|
|
317
|
+
protected classes = computed(() =>
|
|
318
|
+
hlm(toggleVariants({ variant: this.group.variant(), size: this.group.size() }), 'uppercase'),
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
```html
|
|
324
|
+
<div hlmToggleGroup type="single" variant="outline">
|
|
325
|
+
<button customGroupItem value="a">A</button>
|
|
326
|
+
</div>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Accessibility notes
|
|
330
|
+
|
|
331
|
+
- Give the group an accessible name (`aria-label` on the group element) when its purpose is not obvious from surrounding headings.
|
|
332
|
+
- Icon-only items need `aria-label` each; text items get names from content.
|
|
333
|
+
- Keyboard follows the toolbar pattern via the Brn primitive (arrows move, Space/Enter toggle). Keep DOM order = visual order, especially in `vertical` orientation.
|
|
334
|
+
- `disabled` on the group disables all items; a single `disabled` item is skipped in navigation — explain why when it blocks a workflow.
|
|
335
|
+
- Single-select groups should allow a null/empty state or document that one option is always active (`nullable` input).
|
|
336
|
+
|
|
337
|
+
## Theming / CSS variables
|
|
338
|
+
|
|
339
|
+
Group and items share the toggle token set (`bg-muted` pressed, `border-input` outline, `ring-ring/50` focus). `spacing="0"` + `outline` renders a joined segmented control with `shadow-xs`; non-zero spacing renders separated pills with `--gap`. Follows your shadcn theme automatically.
|
|
340
|
+
|
|
341
|
+
## Related subpaths
|
|
342
|
+
|
|
343
|
+
- `@egose/shadcn-theme-ng/toggle` — standalone toggle button + `toggleVariants` reused here.
|
|
344
|
+
- `@egose/shadcn-theme-ng/button-group` — action button groups (vs. pressed-state groups).
|
|
345
|
+
- `@egose/shadcn-theme-ng/tooltip` — labels for icon-only items.
|
|
346
|
+
- `@egose/shadcn-theme-ng/utils` — `hlm()` merger used for custom items.
|
package/tooltip/README.md
CHANGED
|
@@ -1,3 +1,270 @@
|
|
|
1
|
-
# Tooltip
|
|
1
|
+
# Tooltip (`@egose/shadcn-theme-ng/tooltip`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Contextual hints, equivalent to [shadcn/ui Tooltip](https://ui.shadcn.com/docs/components/tooltip). This subpath ships a single thin directive, `HlmTooltip` (`[hlmTooltip]`), that configures spartan-ng's `BrnTooltip` primitive with shadcn styling: it provides default content classes (`DEFAULT_TOOLTIP_CONTENT_CLASSES`), arrow SVG classes (`DEFAULT_TOOLTIP_SVG_CLASS`), and per-position arrow placement (`tooltipPositionVariants`). All show/hide behavior comes from `BrnTooltip` — this package only themes it.
|
|
4
|
+
|
|
5
|
+
> **Ships as:** `@egose/shadcn-theme-ng/tooltip` and `@egose/shadcn-theme-ng-tw/tooltip` (the `tw:`-prefixed Tailwind variant). See the [package README](../../README.md) for install steps, peer dependencies, Tailwind setup, and testing/release guidance. Do not publish this project directory independently.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Plain Tailwind (no prefix)
|
|
11
|
+
npm install @egose/shadcn-theme-ng
|
|
12
|
+
|
|
13
|
+
# Or the tw:-prefixed variant
|
|
14
|
+
npm install @egose/shadcn-theme-ng-tw
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`@spartan-ng/brain` and `class-variance-authority` arrive transitively. See the [package README](../../README.md) for the full peer-dependency table.
|
|
18
|
+
|
|
19
|
+
## Imports
|
|
20
|
+
|
|
21
|
+
All public symbols are re-exported from `projects/tooltip/src/public-api.ts`:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import {
|
|
25
|
+
DEFAULT_TOOLTIP_CONTENT_CLASSES,
|
|
26
|
+
DEFAULT_TOOLTIP_SVG_CLASS,
|
|
27
|
+
HlmTooltip,
|
|
28
|
+
HlmTooltipImports,
|
|
29
|
+
HlmTooltipModule,
|
|
30
|
+
tooltipPositionVariants,
|
|
31
|
+
} from '@egose/shadcn-theme-ng/tooltip';
|
|
32
|
+
// tw variant: swap to '@egose/shadcn-theme-ng-tw/tooltip'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Standalone-component usage (preferred):
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { Component } from '@angular/core';
|
|
39
|
+
import { HlmTooltipImports } from '@egose/shadcn-theme-ng/tooltip';
|
|
40
|
+
|
|
41
|
+
@Component({
|
|
42
|
+
selector: 'app-demo',
|
|
43
|
+
standalone: true,
|
|
44
|
+
imports: [...HlmTooltipImports],
|
|
45
|
+
template: `<button [hlmTooltip]="'Save document'">Save</button>`,
|
|
46
|
+
})
|
|
47
|
+
export class DemoComponent {}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
NgModule usage:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { NgModule } from '@angular/core';
|
|
54
|
+
import { HlmTooltipModule } from '@egose/shadcn-theme-ng/tooltip';
|
|
55
|
+
|
|
56
|
+
@NgModule({ imports: [HlmTooltipModule] })
|
|
57
|
+
export class FeatureModule {}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
| Symbol | Kind | Description |
|
|
61
|
+
| --------------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
62
|
+
| `HlmTooltip` | Directive | `[hlmTooltip]` — themed `BrnTooltip` with shadcn defaults. |
|
|
63
|
+
| `DEFAULT_TOOLTIP_CONTENT_CLASSES` | `const` (string) | Default bubble classes (`bg-foreground text-background rounded-md px-3 py-1.5 text-xs …`). |
|
|
64
|
+
| `DEFAULT_TOOLTIP_SVG_CLASS` | `const` (string) | Default arrow classes (`bg-foreground fill-foreground size-2.5 rotate-45 …`). (Note: unprefixed utilities; overridden by the provider with `hlm()`.) |
|
|
65
|
+
| `tooltipPositionVariants` | cva fn | `tooltipPositionVariants({ position })` — arrow placement for `top/bottom/left/right`. |
|
|
66
|
+
| `HlmTooltipImports` | `const` array | `[HlmTooltip]` — spread into `imports: [...]`. |
|
|
67
|
+
| `HlmTooltipModule` | NgModule | Imports + re-exports `HlmTooltip`. |
|
|
68
|
+
|
|
69
|
+
## Anatomy / Structure
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<!-- basic: string content -->
|
|
73
|
+
<button hlmBtn [hlmTooltip]="'Add to library'">Add</button>
|
|
74
|
+
|
|
75
|
+
<!-- positioned, delayed -->
|
|
76
|
+
<button hlmBtn [hlmTooltip]="'Settings'" position="right" [showDelay]="300" [hideDelay]="100">Settings</button>
|
|
77
|
+
|
|
78
|
+
<!-- disabled tooltip -->
|
|
79
|
+
<button hlmBtn [hlmTooltip]="'Hidden hint'" [tooltipDisabled]="true">No tooltip</button>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The directive takes the tooltip **text as its input value** (`brnTooltip: hlmTooltip`) and renders the floating bubble + arrow via the CDK overlay. No extra outlet component is needed.
|
|
83
|
+
|
|
84
|
+
## API reference
|
|
85
|
+
|
|
86
|
+
### `HlmTooltip` — selector `[hlmTooltip]` (directive, hosts `BrnTooltip`)
|
|
87
|
+
|
|
88
|
+
The directive declares **no own inputs** — everything is forwarded to `BrnTooltip` (plus provider defaults):
|
|
89
|
+
|
|
90
|
+
| Input | Type | Default (via provider) | Description |
|
|
91
|
+
| ----------------- | --------------------------------------------------------------- | ---------------------- | -------------------------------------------------------------------- |
|
|
92
|
+
| `hlmTooltip` | `string` (forwarded as `brnTooltip`) | — | Tooltip text content. Required to show anything. |
|
|
93
|
+
| `position` | `BrnTooltipPosition` (`'top' \| 'bottom' \| 'left' \| 'right'`) | — (Brn default) | Bubble side + arrow placement (arrow via `tooltipPositionVariants`). |
|
|
94
|
+
| `showDelay` | `number` (forwarded) | — (Brn default) | ms before the tooltip appears on hover/focus. |
|
|
95
|
+
| `hideDelay` | `number` (forwarded) | — (Brn default) | ms before the tooltip hides on leave/blur. |
|
|
96
|
+
| `tooltipDisabled` | `boolean` (forwarded) | — (Brn default) | Suppress the tooltip entirely. |
|
|
97
|
+
|
|
98
|
+
Provider defaults (`provideBrnTooltipDefaultOptions`, applied automatically): `svgClasses: DEFAULT_TOOLTIP_SVG_CLASS`, `tooltipContentClasses: DEFAULT_TOOLTIP_CONTENT_CLASSES`, `arrowClasses: (position) => hlm(tooltipPositionVariants({ position }))`.
|
|
99
|
+
|
|
100
|
+
No outputs. Can attach to any element (buttons, icons, toggles, links).
|
|
101
|
+
|
|
102
|
+
## Examples
|
|
103
|
+
|
|
104
|
+
### 1. Basic usage
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
// demo-basic.component.ts
|
|
108
|
+
import { Component } from '@angular/core';
|
|
109
|
+
import { HlmTooltipImports } from '@egose/shadcn-theme-ng/tooltip';
|
|
110
|
+
import { HlmButtonImports } from '@egose/shadcn-theme-ng/button';
|
|
111
|
+
|
|
112
|
+
@Component({
|
|
113
|
+
selector: 'demo-basic',
|
|
114
|
+
standalone: true,
|
|
115
|
+
imports: [...HlmTooltipImports, ...HlmButtonImports],
|
|
116
|
+
template: ` <button hlmBtn variant="outline" [hlmTooltip]="'Add to library'">Add</button> `,
|
|
117
|
+
})
|
|
118
|
+
export class DemoBasic {}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 2. All positions
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
// demo-positions.component.ts
|
|
125
|
+
import { Component } from '@angular/core';
|
|
126
|
+
import { HlmTooltipImports } from '@egose/shadcn-theme-ng/tooltip';
|
|
127
|
+
import { HlmButtonImports } from '@egose/shadcn-theme-ng/button';
|
|
128
|
+
|
|
129
|
+
@Component({
|
|
130
|
+
selector: 'demo-positions',
|
|
131
|
+
standalone: true,
|
|
132
|
+
imports: [...HlmTooltipImports, ...HlmButtonImports],
|
|
133
|
+
template: `
|
|
134
|
+
<div class="flex flex-wrap gap-2">
|
|
135
|
+
<button hlmBtn variant="outline" [hlmTooltip]="'On top'" position="top">Top</button>
|
|
136
|
+
<button hlmBtn variant="outline" [hlmTooltip]="'Below'" position="bottom">Bottom</button>
|
|
137
|
+
<button hlmBtn variant="outline" [hlmTooltip]="'On the left'" position="left">Left</button>
|
|
138
|
+
<button hlmBtn variant="outline" [hlmTooltip]="'On the right'" position="right">Right</button>
|
|
139
|
+
</div>
|
|
140
|
+
`,
|
|
141
|
+
})
|
|
142
|
+
export class DemoPositions {}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The arrow repositions automatically per side via `tooltipPositionVariants({ position })`.
|
|
146
|
+
|
|
147
|
+
### 3. Delays + disabled state
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
// demo-delays.component.ts
|
|
151
|
+
import { Component, signal } from '@angular/core';
|
|
152
|
+
import { HlmTooltipImports } from '@egose/shadcn-theme-ng/tooltip';
|
|
153
|
+
import { HlmButtonImports } from '@egose/shadcn-theme-ng/button';
|
|
154
|
+
|
|
155
|
+
@Component({
|
|
156
|
+
selector: 'demo-delays',
|
|
157
|
+
standalone: true,
|
|
158
|
+
imports: [...HlmTooltipImports, ...HlmButtonImports],
|
|
159
|
+
template: `
|
|
160
|
+
<div class="flex gap-2">
|
|
161
|
+
<button hlmBtn variant="outline" [hlmTooltip]="'Slow to appear'" [showDelay]="600" [hideDelay]="100">
|
|
162
|
+
Hover me
|
|
163
|
+
</button>
|
|
164
|
+
<button hlmBtn variant="outline" [hlmTooltip]="'Never shows'" [tooltipDisabled]="muted()">
|
|
165
|
+
{{ muted() ? 'Muted (no tip)' : 'Unmuted' }}
|
|
166
|
+
</button>
|
|
167
|
+
<button hlmBtn size="sm" (click)="muted.set(!muted())">Toggle mute</button>
|
|
168
|
+
</div>
|
|
169
|
+
`,
|
|
170
|
+
})
|
|
171
|
+
export class DemoDelays {
|
|
172
|
+
readonly muted = signal(false);
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 4. Icon-only buttons and toggles (accessible names still required)
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
// demo-icons.component.ts
|
|
180
|
+
import { Component } from '@angular/core';
|
|
181
|
+
import { HlmTooltipImports } from '@egose/shadcn-theme-ng/tooltip';
|
|
182
|
+
import { HlmToggleImports } from '@egose/shadcn-theme-ng/toggle';
|
|
183
|
+
import { NgIcon, provideIcons } from '@ng-icons/core';
|
|
184
|
+
import { lucideBold, lucideItalic } from '@ng-icons/lucide';
|
|
185
|
+
|
|
186
|
+
@Component({
|
|
187
|
+
selector: 'demo-icons',
|
|
188
|
+
standalone: true,
|
|
189
|
+
imports: [...HlmTooltipImports, ...HlmToggleImports, NgIcon],
|
|
190
|
+
providers: [provideIcons({ lucideBold, lucideItalic })],
|
|
191
|
+
template: `
|
|
192
|
+
<div class="flex gap-1">
|
|
193
|
+
<button hlmToggle aria-label="Toggle bold" [hlmTooltip]="'Bold (Ctrl+B)'">
|
|
194
|
+
<ng-icon name="lucideBold" />
|
|
195
|
+
</button>
|
|
196
|
+
<button hlmToggle aria-label="Toggle italic" [hlmTooltip]="'Italic (Ctrl+I)'" position="bottom">
|
|
197
|
+
<ng-icon name="lucideItalic" />
|
|
198
|
+
</button>
|
|
199
|
+
</div>
|
|
200
|
+
`,
|
|
201
|
+
})
|
|
202
|
+
export class DemoIcons {}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
> The tooltip is a visual hint only — icon buttons still need `aria-label` (tooltips are not reliably announced).
|
|
206
|
+
|
|
207
|
+
### 5. Dynamic content from signals
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
// demo-dynamic.component.ts
|
|
211
|
+
import { Component, computed, signal } from '@angular/core';
|
|
212
|
+
import { HlmTooltipImports } from '@egose/shadcn-theme-ng/tooltip';
|
|
213
|
+
import { HlmButtonImports } from '@egose/shadcn-theme-ng/button';
|
|
214
|
+
|
|
215
|
+
@Component({
|
|
216
|
+
selector: 'demo-dynamic',
|
|
217
|
+
standalone: true,
|
|
218
|
+
imports: [...HlmTooltipImports, ...HlmButtonImports],
|
|
219
|
+
template: `
|
|
220
|
+
<button hlmBtn variant="outline" [hlmTooltip]="tip()" (click)="count.set(count() + 1)">
|
|
221
|
+
Clicked {{ count() }}×
|
|
222
|
+
</button>
|
|
223
|
+
`,
|
|
224
|
+
})
|
|
225
|
+
export class DemoDynamic {
|
|
226
|
+
readonly count = signal(0);
|
|
227
|
+
readonly tip = computed(() => (this.count() === 0 ? 'Click to start' : `Clicked ${this.count()} times`));
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### 6. Advanced: reusing the class constants
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
// demo-classes.component.ts
|
|
235
|
+
import { Component } from '@angular/core';
|
|
236
|
+
import { DEFAULT_TOOLTIP_CONTENT_CLASSES, tooltipPositionVariants } from '@egose/shadcn-theme-ng/tooltip';
|
|
237
|
+
import { hlm } from '@egose/shadcn-theme-ng/utils';
|
|
238
|
+
|
|
239
|
+
@Component({
|
|
240
|
+
selector: 'demo-classes',
|
|
241
|
+
standalone: true,
|
|
242
|
+
template: `<p class="text-sm">Content classes length: {{ len }}</p>`,
|
|
243
|
+
})
|
|
244
|
+
export class DemoClasses {
|
|
245
|
+
readonly len = DEFAULT_TOOLTIP_CONTENT_CLASSES.length;
|
|
246
|
+
|
|
247
|
+
arrowFor(position: 'top' | 'bottom' | 'left' | 'right') {
|
|
248
|
+
return hlm(tooltipPositionVariants({ position }));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Accessibility notes
|
|
254
|
+
|
|
255
|
+
- Tooltips appear on hover **and** focus (via Brn) — keyboard users get them automatically; do not gate hints behind hover-only behavior.
|
|
256
|
+
- Never put essential information _only_ in a tooltip: screen-reader and touch support is best-effort. Mirror critical hints as visible text or `aria-label`s.
|
|
257
|
+
- Icon-only triggers need `aria-label` regardless of tooltip text.
|
|
258
|
+
- Keep tooltip text short (a few words); long prose belongs in a popover/dialog.
|
|
259
|
+
- `tooltipDisabled` removes the hint entirely — only use it when the control is self-explanatory in that state, not to hide errors.
|
|
260
|
+
|
|
261
|
+
## Theming / CSS variables
|
|
262
|
+
|
|
263
|
+
The bubble uses `bg-foreground text-background` with entrance/exit animations per side and theme-aware shadows; the arrow inherits the same fill. Follows your shadcn theme automatically. Override globally by providing your own `provideBrnTooltipDefaultOptions`, or per case by wrapping triggers with custom classes.
|
|
264
|
+
|
|
265
|
+
## Related subpaths
|
|
266
|
+
|
|
267
|
+
- `@egose/shadcn-theme-ng/button` — most common tooltip anchor.
|
|
268
|
+
- `@egose/shadcn-theme-ng/toggle` / `@egose/shadcn-theme-ng/toggle-group` — icon toggles that pair well with hints.
|
|
269
|
+
- `@egose/shadcn-theme-ng/popover` / `@egose/shadcn-theme-ng/hover-card` — richer floating content (vs. short tooltip text).
|
|
270
|
+
- `@egose/shadcn-theme-ng/utils` — `hlm()` used to compose arrow/content classes.
|