@egose/shadcn-theme-ng-tw 0.0.28 → 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 +130 -13
- package/accordion/README.md +376 -34
- package/accordion/fesm2022/accordion.mjs +20 -20
- package/alert/README.md +343 -34
- package/alert/fesm2022/alert.mjs +18 -18
- package/alert-dialog/README.md +471 -5
- package/alert-dialog/fesm2022/alert-dialog.mjs +48 -48
- package/alert-dialog/types/alert-dialog.d.ts +1 -1
- package/aspect-ratio/README.md +272 -5
- package/aspect-ratio/fesm2022/aspect-ratio.mjs +9 -9
- package/autocomplete/README.md +473 -34
- package/autocomplete/fesm2022/autocomplete.mjs +54 -54
- package/autocomplete/types/autocomplete.d.ts +1 -1
- package/avatar/README.md +357 -5
- package/avatar/fesm2022/avatar.mjs +32 -32
- package/badge/README.md +289 -34
- package/badge/fesm2022/badge.mjs +4 -4
- package/basic-alert/README.md +324 -34
- package/basic-alert/fesm2022/basic-alert.mjs +4 -4
- package/basic-alert/types/basic-alert.d.ts +1 -1
- package/breadcrumb/README.md +406 -5
- package/breadcrumb/fesm2022/breadcrumb.mjs +34 -34
- package/button/README.md +453 -34
- package/button/fesm2022/button.mjs +96 -118
- package/button/types/button.d.ts +7 -10
- package/button-group/README.md +318 -5
- package/button-group/fesm2022/button-group.mjs +20 -20
- package/calendar/README.md +328 -34
- package/calendar/fesm2022/calendar.mjs +154 -154
- package/card/README.md +331 -5
- package/card/fesm2022/card.mjs +33 -33
- package/carousel/README.md +333 -5
- package/carousel/fesm2022/carousel.mjs +47 -44
- package/carousel/types/carousel.d.ts +1 -1
- package/checkbox/README.md +291 -34
- package/checkbox/fesm2022/checkbox.mjs +22 -20
- package/checkbox/types/checkbox.d.ts +5 -4
- package/collapsible/README.md +332 -5
- package/collapsible/fesm2022/collapsible.mjs +15 -15
- package/combobox/README.md +507 -5
- package/combobox/fesm2022/combobox.mjs +95 -92
- package/combobox/types/combobox.d.ts +1 -1
- package/command/README.md +435 -5
- package/command/fesm2022/command.mjs +56 -56
- package/confirmation-dialog/README.md +272 -34
- package/confirmation-dialog/fesm2022/confirmation-dialog.mjs +13 -12
- package/confirmation-dialog/types/confirmation-dialog.d.ts +9 -5
- package/context-menu/README.md +366 -5
- package/context-menu/fesm2022/context-menu.mjs +9 -9
- package/date-picker/README.md +436 -34
- package/date-picker/fesm2022/date-picker.mjs +79 -68
- package/date-picker/types/date-picker.d.ts +8 -4
- package/dialog/README.md +419 -34
- package/dialog/fesm2022/dialog.mjs +48 -48
- package/drawer/README.md +395 -5
- package/drawer/fesm2022/drawer.mjs +45 -45
- package/dropdown-menu/README.md +417 -5
- package/dropdown-menu/fesm2022/dropdown-menu.mjs +85 -73
- package/dropdown-menu/types/dropdown-menu.d.ts +4 -0
- package/empty/README.md +329 -5
- package/empty/fesm2022/empty.mjs +31 -31
- package/field/README.md +385 -5
- package/field/fesm2022/field.mjs +59 -59
- package/field/types/field.d.ts +1 -1
- package/form-checkbox/README.md +283 -34
- package/form-checkbox/fesm2022/form-checkbox.mjs +37 -19
- package/form-checkbox/types/form-checkbox.d.ts +7 -1
- package/form-date-picker/README.md +293 -34
- package/form-date-picker/fesm2022/form-date-picker.mjs +59 -24
- package/form-date-picker/types/form-date-picker.d.ts +7 -1
- package/form-field/README.md +327 -34
- package/form-field/fesm2022/form-field.mjs +30 -16
- package/form-field/types/form-field.d.ts +28 -20
- package/form-field-simple/README.md +311 -34
- package/form-field-simple/fesm2022/form-field-simple.mjs +4 -4
- package/form-searchable-multiselect/README.md +332 -34
- package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +41 -21
- package/form-searchable-multiselect/types/form-searchable-multiselect.d.ts +8 -2
- package/form-select/README.md +321 -34
- package/form-select/fesm2022/form-select.mjs +62 -29
- package/form-select/types/form-select.d.ts +7 -1
- package/form-text-input/README.md +342 -34
- package/form-text-input/fesm2022/form-text-input.mjs +43 -55
- package/form-text-input/types/form-text-input.d.ts +9 -12
- package/form-textarea/README.md +318 -34
- package/form-textarea/fesm2022/form-textarea.mjs +42 -23
- package/form-textarea/types/form-textarea.d.ts +8 -1
- package/hover-card/README.md +256 -5
- package/hover-card/fesm2022/hover-card.mjs +19 -19
- package/icon/README.md +210 -34
- package/icon/fesm2022/icon.mjs +8 -8
- package/input/README.md +240 -34
- package/input/fesm2022/input.mjs +17 -12
- package/input/types/input.d.ts +2 -1
- package/input-group/README.md +335 -5
- package/input-group/fesm2022/input-group.mjs +37 -37
- package/input-group/types/input-group.d.ts +3 -3
- package/input-otp/README.md +375 -5
- package/input-otp/fesm2022/input-otp.mjs +27 -27
- package/item/README.md +385 -5
- package/item/fesm2022/item.mjs +54 -54
- package/kbd/README.md +291 -5
- package/kbd/fesm2022/kbd.mjs +13 -13
- package/label/README.md +243 -34
- package/label/fesm2022/label.mjs +9 -9
- package/label/types/label.d.ts +1 -1
- package/layout-simple/README.md +174 -44
- package/layout-simple/fesm2022/layout-simple.mjs +917 -398
- package/layout-simple/types/layout-simple.d.ts +180 -129
- package/menu/README.md +418 -0
- package/menu/fesm2022/menu.mjs +461 -0
- package/menu/package.json +24 -0
- package/menu/types/menu.d.ts +137 -0
- package/menubar/README.md +343 -5
- package/menubar/fesm2022/menubar.mjs +13 -13
- package/native-select/README.md +323 -5
- package/native-select/fesm2022/native-select.mjs +19 -19
- package/navigation-menu/README.md +369 -5
- package/navigation-menu/fesm2022/navigation-menu.mjs +37 -37
- package/package.json +183 -154
- package/pagination/README.md +388 -5
- package/pagination/fesm2022/pagination.mjs +63 -63
- package/popover/README.md +302 -34
- package/popover/fesm2022/popover.mjs +30 -30
- package/progress/README.md +311 -5
- package/progress/fesm2022/progress.mjs +13 -13
- package/radio-group/README.md +335 -34
- package/radio-group/fesm2022/radio-group.mjs +26 -19
- package/resizable/README.md +269 -5
- package/resizable/fesm2022/resizable.mjs +19 -19
- package/scroll-area/README.md +233 -5
- package/scroll-area/fesm2022/scroll-area.mjs +9 -9
- package/searchable-multiselect/README.md +294 -34
- package/searchable-multiselect/fesm2022/searchable-multiselect.mjs +63 -16
- package/searchable-multiselect/types/searchable-multiselect.d.ts +8 -2
- package/select/README.md +408 -34
- package/select/fesm2022/select.mjs +80 -72
- package/select/types/select.d.ts +3 -1
- package/separator/README.md +193 -34
- package/separator/fesm2022/separator.mjs +9 -9
- package/separator/types/separator.d.ts +1 -1
- package/sheet/README.md +282 -34
- package/sheet/fesm2022/sheet.mjs +30 -30
- package/sidebar/README.md +457 -5
- package/sidebar/fesm2022/sidebar.mjs +136 -134
- package/sidebar/types/sidebar.d.ts +3 -3
- package/skeleton/README.md +217 -5
- package/skeleton/fesm2022/skeleton.mjs +9 -9
- package/slider/README.md +273 -5
- package/slider/fesm2022/slider.mjs +29 -25
- package/sonner/README.md +317 -34
- package/sonner/fesm2022/sonner.mjs +9 -9
- package/spinner/README.md +255 -34
- package/spinner/fesm2022/spinner.mjs +8 -8
- package/switch/README.md +281 -34
- package/switch/fesm2022/switch.mjs +12 -14
- package/table/README.md +423 -5
- package/table/fesm2022/table.mjs +41 -41
- package/tabs/README.md +382 -34
- package/tabs/fesm2022/tabs.mjs +48 -38
- package/textarea/README.md +282 -5
- package/textarea/fesm2022/textarea.mjs +9 -9
- package/toggle/README.md +270 -5
- package/toggle/fesm2022/toggle.mjs +14 -14
- package/toggle-group/README.md +340 -5
- package/toggle-group/fesm2022/toggle-group.mjs +13 -13
- package/toggle-group/types/toggle-group.d.ts +13 -7
- package/tooltip/README.md +240 -34
- package/tooltip/fesm2022/tooltip.mjs +14 -14
- package/typography/README.md +271 -5
- package/typography/fesm2022/typography.mjs +53 -53
- package/typography/types/typography.d.ts +12 -12
- package/utils/README.md +274 -34
- package/utils/fesm2022/utils.mjs +68 -44
- package/accordion/fesm2022/accordion.mjs.map +0 -1
- package/alert/fesm2022/alert.mjs.map +0 -1
- package/alert-dialog/fesm2022/alert-dialog.mjs.map +0 -1
- package/aspect-ratio/fesm2022/aspect-ratio.mjs.map +0 -1
- package/autocomplete/fesm2022/autocomplete.mjs.map +0 -1
- package/avatar/fesm2022/avatar.mjs.map +0 -1
- package/badge/fesm2022/badge.mjs.map +0 -1
- package/basic-alert/fesm2022/basic-alert.mjs.map +0 -1
- package/breadcrumb/fesm2022/breadcrumb.mjs.map +0 -1
- package/button/fesm2022/button.mjs.map +0 -1
- package/button-group/fesm2022/button-group.mjs.map +0 -1
- package/calendar/fesm2022/calendar.mjs.map +0 -1
- package/card/fesm2022/card.mjs.map +0 -1
- package/carousel/fesm2022/carousel.mjs.map +0 -1
- package/checkbox/fesm2022/checkbox.mjs.map +0 -1
- package/collapsible/fesm2022/collapsible.mjs.map +0 -1
- package/combobox/fesm2022/combobox.mjs.map +0 -1
- package/command/fesm2022/command.mjs.map +0 -1
- package/confirmation-dialog/fesm2022/confirmation-dialog.mjs.map +0 -1
- package/context-menu/fesm2022/context-menu.mjs.map +0 -1
- package/date-picker/fesm2022/date-picker.mjs.map +0 -1
- package/dialog/fesm2022/dialog.mjs.map +0 -1
- package/drawer/fesm2022/drawer.mjs.map +0 -1
- package/dropdown-menu/fesm2022/dropdown-menu.mjs.map +0 -1
- package/empty/fesm2022/empty.mjs.map +0 -1
- package/field/fesm2022/field.mjs.map +0 -1
- package/form-checkbox/fesm2022/form-checkbox.mjs.map +0 -1
- package/form-date-picker/fesm2022/form-date-picker.mjs.map +0 -1
- package/form-field/fesm2022/form-field.mjs.map +0 -1
- package/form-field-simple/fesm2022/form-field-simple.mjs.map +0 -1
- package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs.map +0 -1
- package/form-select/fesm2022/form-select.mjs.map +0 -1
- package/form-text-input/fesm2022/form-text-input.mjs.map +0 -1
- package/form-textarea/fesm2022/form-textarea.mjs.map +0 -1
- package/hover-card/fesm2022/hover-card.mjs.map +0 -1
- package/icon/fesm2022/icon.mjs.map +0 -1
- package/input/fesm2022/input.mjs.map +0 -1
- package/input-group/fesm2022/input-group.mjs.map +0 -1
- package/input-otp/fesm2022/input-otp.mjs.map +0 -1
- package/item/fesm2022/item.mjs.map +0 -1
- package/kbd/fesm2022/kbd.mjs.map +0 -1
- package/label/fesm2022/label.mjs.map +0 -1
- package/layout-simple/fesm2022/layout-simple.mjs.map +0 -1
- package/menubar/fesm2022/menubar.mjs.map +0 -1
- package/native-select/fesm2022/native-select.mjs.map +0 -1
- package/navigation-menu/fesm2022/navigation-menu.mjs.map +0 -1
- package/pagination/fesm2022/pagination.mjs.map +0 -1
- package/popover/fesm2022/popover.mjs.map +0 -1
- package/progress/fesm2022/progress.mjs.map +0 -1
- package/radio-group/fesm2022/radio-group.mjs.map +0 -1
- package/resizable/fesm2022/resizable.mjs.map +0 -1
- package/scroll-area/fesm2022/scroll-area.mjs.map +0 -1
- package/searchable-multiselect/fesm2022/searchable-multiselect.mjs.map +0 -1
- package/select/fesm2022/select.mjs.map +0 -1
- package/separator/fesm2022/separator.mjs.map +0 -1
- package/sheet/fesm2022/sheet.mjs.map +0 -1
- package/sidebar/fesm2022/sidebar.mjs.map +0 -1
- package/skeleton/fesm2022/skeleton.mjs.map +0 -1
- package/slider/fesm2022/slider.mjs.map +0 -1
- package/sonner/fesm2022/sonner.mjs.map +0 -1
- package/spinner/fesm2022/spinner.mjs.map +0 -1
- package/switch/fesm2022/switch.mjs.map +0 -1
- package/table/fesm2022/table.mjs.map +0 -1
- package/tabs/fesm2022/tabs.mjs.map +0 -1
- package/textarea/fesm2022/textarea.mjs.map +0 -1
- package/toggle/fesm2022/toggle.mjs.map +0 -1
- package/toggle-group/fesm2022/toggle-group.mjs.map +0 -1
- package/tooltip/fesm2022/tooltip.mjs.map +0 -1
- package/typography/fesm2022/typography.mjs.map +0 -1
- package/utils/fesm2022/utils.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -14,17 +14,28 @@ npm install @egose/shadcn-theme-ng
|
|
|
14
14
|
npm install @egose/shadcn-theme-ng-tw
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
`pnpm` / `yarn` equivalents work too.
|
|
17
|
+
`pnpm` / `yarn` equivalents work too. npm installs peer dependencies automatically when it can resolve compatible
|
|
18
|
+
versions; applications must keep their existing framework versions inside the supported ranges below.
|
|
18
19
|
|
|
19
20
|
### Peer dependencies
|
|
20
21
|
|
|
21
|
-
| Package | Supported version
|
|
22
|
-
| ------------------- |
|
|
23
|
-
| `@angular/
|
|
24
|
-
| `@angular/
|
|
25
|
-
| `@
|
|
22
|
+
| Package | Supported version | Tested version |
|
|
23
|
+
| ------------------- | ------------------ | -------------- |
|
|
24
|
+
| `@angular/cdk` | `>=22.0.0 <23.0.0` | `22.1.3` |
|
|
25
|
+
| `@angular/common` | `>=22.0.0 <23.0.0` | `22.1.3` |
|
|
26
|
+
| `@angular/core` | `>=22.0.0 <23.0.0` | `22.1.3` |
|
|
27
|
+
| `@angular/forms` | `>=22.0.0 <23.0.0` | `22.1.3` |
|
|
28
|
+
| `@angular/router` | `>=22.0.0 <23.0.0` | `22.1.3` |
|
|
29
|
+
| `@ng-icons/core` | `>=35.0.1 <36.0.0` | `35.0.1` |
|
|
30
|
+
| `@spartan-ng/brain` | `>=1.3.2 <2.0.0` | `1.3.2` |
|
|
31
|
+
| `rxjs` | `>=7.8.0 <8.0.0` | `7.8.2` |
|
|
26
32
|
|
|
27
|
-
|
|
33
|
+
Angular and CDK must use the same major version. The tested consumer contract is Angular 22, CDK 22, and Spartan 1.3.2;
|
|
34
|
+
the ranges above are copied from the published peer metadata and validated with strict isolated installs.
|
|
35
|
+
|
|
36
|
+
Runtime implementation dependencies such as `@ng-icons/lucide`, `@ng-icons/tabler-icons`, `class-variance-authority`,
|
|
37
|
+
`clsx`, `embla-carousel`, `embla-carousel-angular`, `ngx-scrollbar`, `ngx-sonner`, `tailwind-merge`, and `tslib` are
|
|
38
|
+
installed transitively. Do not install them directly unless your application also imports them.
|
|
28
39
|
|
|
29
40
|
### Tailwind variants
|
|
30
41
|
|
|
@@ -37,6 +48,59 @@ There are two published variants of this package. They produce identical markup
|
|
|
37
48
|
|
|
38
49
|
If your project mixes shadcn styles with other Tailwind utilities that share class names, use the `-tw` variant to avoid collisions.
|
|
39
50
|
|
|
51
|
+
Class utilities are normalized to one unprefixed canonical representation during packaging. The plain artifact emits
|
|
52
|
+
unprefixed utilities, while the `-tw` artifact prefixes every recognized utility with `tw:`. Generated JavaScript source
|
|
53
|
+
maps are intentionally excluded because this post-build class and package-identity transformation invalidates ng-packagr's
|
|
54
|
+
maps; shipping no map is safer than shipping a map that points at different generated code.
|
|
55
|
+
|
|
56
|
+
## Release preparation
|
|
57
|
+
|
|
58
|
+
Prepare both release candidates without publishing by supplying the intended version explicitly:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pnpm --dir packages/angular prepare:release --version 1.2.3
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This runs `@repo-toolkit/publish-package` with `publish.config.mjs`: it serially
|
|
65
|
+
builds, validates, and packs the plain (`release/plain` → `@egose/shadcn-theme-ng`)
|
|
66
|
+
and `tw:` (`release/tw` → `@egose/shadcn-theme-ng-tw`) variants. The inspectable
|
|
67
|
+
stages and two exact `.tgz` artifacts are written under `packages/angular/release/`.
|
|
68
|
+
Neither package is published unless both candidates pass every step. Publishing is
|
|
69
|
+
intended to run from protected CI with npm trusted publishing/OIDC; `--otp` remains
|
|
70
|
+
available for manual publishes (passed to the toolkit publish command, never logged).
|
|
71
|
+
|
|
72
|
+
## Source tests
|
|
73
|
+
|
|
74
|
+
Headless-test prerequisite (local and CI): the Karma suites need a
|
|
75
|
+
Chrome-compatible binary. The repository-supported setup downloads it into
|
|
76
|
+
the repo-local `.puppeteer-cache/` directory:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pnpm --dir packages/angular install:browser
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Alternatively, set `CHROME_BIN` to any Chrome/Chromium binary yourself
|
|
83
|
+
(`test/karma.conf.js` honors a pre-set `CHROME_BIN`, then falls back to a
|
|
84
|
+
system Chrome).
|
|
85
|
+
|
|
86
|
+
Focused library tests are intentionally separate from staged-package and artifact validation:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# One selected library
|
|
90
|
+
pnpm --dir packages/angular test:library form-text-input
|
|
91
|
+
pnpm --dir packages/angular test:library utils
|
|
92
|
+
|
|
93
|
+
# Source export contracts plus every selected library, serially and headlessly
|
|
94
|
+
pnpm --dir packages/angular test:libraries
|
|
95
|
+
|
|
96
|
+
# The example shell and router behavior
|
|
97
|
+
pnpm --dir packages/angular/@examples/standard test:ci
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The browser suites share `packages/angular/test/setup.ts`, which provides zoneless Angular setup and assertions for form
|
|
101
|
+
bindings and resource teardown. DOM reconciliation uses real `MutationObserver` and animation-frame scheduling; server-mode
|
|
102
|
+
coverage verifies those browser resources are not created. All CI commands disable watch mode so they terminate after one run.
|
|
103
|
+
|
|
40
104
|
## Import forms
|
|
41
105
|
|
|
42
106
|
Import each component via its own npm subpath:
|
|
@@ -72,23 +136,27 @@ export class MyModule {}
|
|
|
72
136
|
|
|
73
137
|
Import by component name. Component `NameX` is reachable at `@egose/shadcn-theme-ng/<name-x>` (kebab-case). The current surface:
|
|
74
138
|
|
|
75
|
-
|
|
139
|
+
<!-- BEGIN GENERATED SUBPATHS -->
|
|
140
|
+
|
|
141
|
+
`accordion`, `alert`, `alert-dialog`, `aspect-ratio`, `autocomplete`, `avatar`, `badge`, `basic-alert`, `breadcrumb`, `button`, `button-group`, `calendar`, `card`, `carousel`, `checkbox`, `collapsible`, `combobox`, `command`, `confirmation-dialog`, `context-menu`, `date-picker`, `dialog`, `drawer`, `dropdown-menu`, `empty`, `field`, `form-checkbox`, `form-date-picker`, `form-field`, `form-field-simple`, `form-searchable-multiselect`, `form-select`, `form-text-input`, `form-textarea`, `hover-card`, `icon`, `input`, `input-group`, `input-otp`, `item`, `kbd`, `label`, `layout-simple`, `menu`, `menubar`, `native-select`, `navigation-menu`, `pagination`, `popover`, `progress`, `radio-group`, `resizable`, `scroll-area`, `searchable-multiselect`, `select`, `separator`, `sheet`, `sidebar`, `skeleton`, `slider`, `sonner`, `spinner`, `switch`, `table`, `tabs`, `textarea`, `toggle`, `toggle-group`, `tooltip`, `typography`, `utils`.
|
|
142
|
+
|
|
143
|
+
<!-- END GENERATED SUBPATHS -->
|
|
76
144
|
|
|
77
145
|
Anything not in this list is not part of the public surface. The published `exports` map in `package.json` reflects this set exactly — if a subpath is not listed, do not assume it is importable.
|
|
78
146
|
|
|
79
147
|
## Quick start (Angular standalone)
|
|
80
148
|
|
|
81
149
|
```ts
|
|
82
|
-
import { Component } from
|
|
83
|
-
import { HlmButtonImports } from
|
|
84
|
-
import { EgLayoutSimple, MenuItem } from
|
|
150
|
+
import { Component } from '@angular/core';
|
|
151
|
+
import { HlmButtonImports } from '@egose/shadcn-theme-ng/button';
|
|
152
|
+
import { EgLayoutSimple, MenuItem } from '@egose/shadcn-theme-ng/layout-simple';
|
|
85
153
|
|
|
86
154
|
@Component({
|
|
87
155
|
selector: "app-demo",
|
|
88
156
|
standalone: true,
|
|
89
|
-
imports: [...HlmButtonImports],
|
|
157
|
+
imports: [EgLayoutSimple, ...HlmButtonImports],
|
|
90
158
|
template: \`
|
|
91
|
-
<eg-layout-simple [
|
|
159
|
+
<eg-layout-simple brandName="My workspace" [primaryNavigation]="items">
|
|
92
160
|
<button hlmBtn variant="primary">Click</button>
|
|
93
161
|
</eg-layout-simple>
|
|
94
162
|
\`,
|
|
@@ -98,6 +166,55 @@ export class DemoComponent {
|
|
|
98
166
|
}
|
|
99
167
|
```
|
|
100
168
|
|
|
169
|
+
## Date picker values
|
|
170
|
+
|
|
171
|
+
`hlm-date-picker` emits a native JS `Date` (or `null` when cleared) via the `dateChange` output. Read it in the
|
|
172
|
+
controller with `(dateChange)`, a template ref (`picker.value()`), or a form binding (`ngModel`/`formControlName`,
|
|
173
|
+
the picker is a `ControlValueAccessor`):
|
|
174
|
+
|
|
175
|
+
```html
|
|
176
|
+
<hlm-date-picker (dateChange)="onDate($event)">
|
|
177
|
+
<hlm-date-picker-input placeholder="Pick a date" />
|
|
178
|
+
</hlm-date-picker>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
onDate(date: Date | null) {
|
|
183
|
+
// date is a JS Date, e.g. 2026-09-23T00:00:00 local time (or null on clear)
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Unlike the React `FormDatePicker` (which normalizes to local midnight), the Angular picker passes dates through
|
|
188
|
+
untouched by default: calendar clicks usually arrive at local midnight already, but dates typed into the input are
|
|
189
|
+
parsed with `new Date(value)`, where `"YYYY-MM-DD"` means UTC midnight — so the time portion can be non-zero. To
|
|
190
|
+
normalize every value reaching the controller to local midnight, provide a custom config (no library changes needed):
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
import { provideHlmDatePickerConfig } from '@egose/shadcn-theme-ng/date-picker';
|
|
194
|
+
|
|
195
|
+
@Component({
|
|
196
|
+
// ...
|
|
197
|
+
providers: [
|
|
198
|
+
provideHlmDatePickerConfig({
|
|
199
|
+
// Strip the time portion, mirroring React's normalizeDate.
|
|
200
|
+
transformDate: (date: Date) => new Date(date.getFullYear(), date.getMonth(), date.getDate()),
|
|
201
|
+
// Parse typed "YYYY-MM-DD" as a local date instead of new Date(value) (UTC).
|
|
202
|
+
parseDate: (value: string) => {
|
|
203
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
204
|
+
if (!match) return null;
|
|
205
|
+
const date = new Date(+match[1], +match[2] - 1, +match[3]);
|
|
206
|
+
return isNaN(date.getTime()) ? null : date;
|
|
207
|
+
},
|
|
208
|
+
}),
|
|
209
|
+
],
|
|
210
|
+
})
|
|
211
|
+
export class MyComponent {}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
`transformDate` runs on every path into the model (calendar selection, typed input, `writeValue`), so the controller
|
|
215
|
+
then always sees local-midnight dates. Related: the picker stays open after selection by default; add the
|
|
216
|
+
`autoCloseOnSelect` attribute (or set it in the same config) to close it on select.
|
|
217
|
+
|
|
101
218
|
## Working example
|
|
102
219
|
|
|
103
220
|
A complete Angular consumer app lives at [`@examples/standard`](https://github.com/egose/shadcn-theme/tree/main/packages/angular/@examples/standard) — see its `src/app/...` for real usage of `@egose/shadcn-theme-ng/button`, `.../layout-simple`, `.../form-text-input`, `.../autocomplete`, `.../select`, `.../form-checkbox`, `.../sheet`, etc.
|
package/accordion/README.md
CHANGED
|
@@ -1,64 +1,406 @@
|
|
|
1
|
-
# Accordion
|
|
1
|
+
# Accordion (`@egose/shadcn-theme-ng/accordion`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A collapsible content panel set in the shadcn/ui Accordion style. Each section pairs a clickable
|
|
4
|
+
trigger row with an expanding content region, so long option lists, FAQs, and settings groups stay
|
|
5
|
+
compact until the user opens them.
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
The Angular implementation is a thin styling layer over the headless
|
|
8
|
+
[`BrnAccordion*` primitives from `@spartan-ng/brain/accordion`](https://www.spartan-ng.com/):
|
|
9
|
+
`HlmAccordion` / `HlmAccordionItem` / `HlmAccordionTrigger` / `HlmAccordionContent` compose
|
|
10
|
+
`BrnAccordion` / `BrnAccordionItem` / `BrnAccordionTrigger` / `BrnAccordionContent` via
|
|
11
|
+
`hostDirectives` (or inheritance for the content), adding shadcn spacing, borders, typography, and
|
|
12
|
+
`class` merging through `hlm()` from `@egose/shadcn-theme-ng/utils`. `HlmAccordionIcon` is a
|
|
13
|
+
companion directive that styles an `ng-icon` (chevron-down) placed inside a trigger.
|
|
6
14
|
|
|
7
|
-
|
|
15
|
+
> **Ships as:** `@egose/shadcn-theme-ng/accordion` and `@egose/shadcn-theme-ng-tw/accordion`
|
|
16
|
+
> (the `tw:`-prefixed Tailwind variant). Both expose the identical TypeScript surface; only the
|
|
17
|
+
> emitted Tailwind class strings differ. See the [package README](../../README.md) for install
|
|
18
|
+
> steps, peer dependencies, and Tailwind setup. Do not publish this project directory independently.
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
8
21
|
|
|
9
22
|
```bash
|
|
10
|
-
|
|
23
|
+
# Plain Tailwind (no prefix)
|
|
24
|
+
npm install @egose/shadcn-theme-ng
|
|
25
|
+
|
|
26
|
+
# tw:-prefixed Tailwind variant
|
|
27
|
+
npm install @egose/shadcn-theme-ng-tw
|
|
11
28
|
```
|
|
12
29
|
|
|
13
|
-
|
|
30
|
+
Peer dependencies (Angular, `@spartan-ng/brain`, `@ng-icons/*`, `rxjs`, …) are documented in the
|
|
31
|
+
[package README](../../README.md#peer-dependencies). This subpath additionally relies at runtime on
|
|
32
|
+
`@egose/shadcn-theme-ng/utils` (`hlm()`), `@egose/shadcn-theme-ng/icon` (`provideHlmIconConfig`),
|
|
33
|
+
and `@ng-icons/lucide` (`lucideChevronDown`) for the icon directive.
|
|
14
34
|
|
|
15
|
-
|
|
16
|
-
|
|
35
|
+
## Imports
|
|
36
|
+
|
|
37
|
+
All symbols are exported from the subpath root (`projects/accordion/src/public-api.ts`):
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import {
|
|
41
|
+
HlmAccordion,
|
|
42
|
+
HlmAccordionItem,
|
|
43
|
+
HlmAccordionTrigger,
|
|
44
|
+
HlmAccordionContent,
|
|
45
|
+
HlmAccordionIcon,
|
|
46
|
+
HlmAccordionImports,
|
|
47
|
+
HlmAccordionModule,
|
|
48
|
+
} from '@egose/shadcn-theme-ng/accordion';
|
|
49
|
+
// tw variant: replace with '@egose/shadcn-theme-ng-tw/accordion'
|
|
17
50
|
```
|
|
18
51
|
|
|
19
|
-
|
|
52
|
+
Standalone component — spread the `*Imports` array:
|
|
20
53
|
|
|
21
|
-
|
|
54
|
+
```ts
|
|
55
|
+
import { Component } from '@angular/core';
|
|
56
|
+
import { HlmAccordionImports } from '@egose/shadcn-theme-ng/accordion';
|
|
22
57
|
|
|
23
|
-
|
|
24
|
-
|
|
58
|
+
@Component({
|
|
59
|
+
selector: 'app-demo',
|
|
60
|
+
standalone: true,
|
|
61
|
+
imports: [...HlmAccordionImports],
|
|
62
|
+
template: `...`,
|
|
63
|
+
})
|
|
64
|
+
export class DemoComponent {}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
NgModule-based consumer — import the module:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { NgModule } from '@angular/core';
|
|
71
|
+
import { HlmAccordionModule } from '@egose/shadcn-theme-ng/accordion';
|
|
72
|
+
|
|
73
|
+
@NgModule({ imports: [HlmAccordionModule] })
|
|
74
|
+
export class DemoModule {}
|
|
25
75
|
```
|
|
26
76
|
|
|
27
|
-
|
|
77
|
+
## Anatomy / Structure
|
|
28
78
|
|
|
29
|
-
|
|
79
|
+
```html
|
|
80
|
+
<!-- hlm-accordion OR any element with hlmAccordion -->
|
|
81
|
+
<hlm-accordion type="single" orientation="vertical">
|
|
82
|
+
<!-- hlm-accordion-item OR [hlmAccordionItem] OR brn-accordion-item[hlm] -->
|
|
83
|
+
<hlm-accordion-item>
|
|
84
|
+
<!-- any element with hlmAccordionTrigger -->
|
|
85
|
+
<button hlmAccordionTrigger>
|
|
86
|
+
Section title
|
|
87
|
+
<!-- chevron icon (either attribute spelling works) -->
|
|
88
|
+
<ng-icon hlmAccIcon name="lucideChevronDown" />
|
|
89
|
+
</button>
|
|
90
|
+
<!-- content element -->
|
|
91
|
+
<hlm-accordion-content>
|
|
92
|
+
<p>Collapsible body.</p>
|
|
93
|
+
</hlm-accordion-content>
|
|
94
|
+
</hlm-accordion-item>
|
|
95
|
+
</hlm-accordion>
|
|
96
|
+
```
|
|
30
97
|
|
|
31
|
-
|
|
98
|
+
Real selectors (from source):
|
|
32
99
|
|
|
33
|
-
|
|
100
|
+
| Class | Selector(s) | Kind |
|
|
101
|
+
| --------------------- | ----------------------------------------------------------------- | --------- |
|
|
102
|
+
| `HlmAccordion` | `[hlmAccordion], hlm-accordion` | Directive |
|
|
103
|
+
| `HlmAccordionItem` | `[hlmAccordionItem], brn-accordion-item[hlm], hlm-accordion-item` | Directive |
|
|
104
|
+
| `HlmAccordionTrigger` | `[hlmAccordionTrigger]` | Directive |
|
|
105
|
+
| `HlmAccordionContent` | `hlm-accordion-content` | Component |
|
|
106
|
+
| `HlmAccordionIcon` | `ng-icon[egAccordionIcon], ng-icon[hlmAccIcon]` | Directive |
|
|
34
107
|
|
|
35
|
-
|
|
36
|
-
cd dist/accordion
|
|
37
|
-
```
|
|
108
|
+
## API reference
|
|
38
109
|
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npm publish
|
|
42
|
-
```
|
|
110
|
+
### `HlmAccordion` — `[hlmAccordion], hlm-accordion`
|
|
43
111
|
|
|
44
|
-
|
|
112
|
+
Thin directive wrapper around `BrnAccordion` (inputs forwarded via `hostDirectives`).
|
|
45
113
|
|
|
46
|
-
|
|
114
|
+
| Input | Type | Default | Description |
|
|
115
|
+
| ------------- | --------------------------- | --------------- | --------------------------------------------------------------------------- |
|
|
116
|
+
| `type` | forwarded to `BrnAccordion` | (brain default) | `'single'` or `'multiple'` open-item behavior. |
|
|
117
|
+
| `orientation` | forwarded to `BrnAccordion` | (brain default) | `'horizontal'` renders the root as `flex-row`, anything else as `flex-col`. |
|
|
118
|
+
| `class` | `ClassValue` | `''` | Extra classes merged via `hlm()`. |
|
|
47
119
|
|
|
48
|
-
|
|
49
|
-
|
|
120
|
+
### `HlmAccordionItem` — `[hlmAccordionItem], brn-accordion-item[hlm], hlm-accordion-item`
|
|
121
|
+
|
|
122
|
+
Thin wrapper around `BrnAccordionItem`.
|
|
123
|
+
|
|
124
|
+
| Input | Type | Default | Description |
|
|
125
|
+
| ---------- | ------------------------------- | ------- | ----------------------------------------- |
|
|
126
|
+
| `isOpened` | forwarded to `BrnAccordionItem` | — | Whether this item starts/sets open state. |
|
|
127
|
+
| `class` | `ClassValue` | `''` | Extra classes merged via `hlm()`. |
|
|
128
|
+
|
|
129
|
+
### `HlmAccordionTrigger` — `[hlmAccordionTrigger]`
|
|
130
|
+
|
|
131
|
+
Thin wrapper around `BrnAccordionTrigger` (no extra inputs — the whole `BrnAccordionTrigger`
|
|
132
|
+
surface is inherited through `hostDirectives`).
|
|
133
|
+
|
|
134
|
+
| Input | Type | Default | Description |
|
|
135
|
+
| ------- | ------------ | ------- | --------------------------------- |
|
|
136
|
+
| `class` | `ClassValue` | `''` | Extra classes merged via `hlm()`. |
|
|
137
|
+
|
|
138
|
+
### `HlmAccordionContent` — `hlm-accordion-content`
|
|
139
|
+
|
|
140
|
+
Component **extending** `BrnAccordionContent`, so the `state()` signal (`'open' | 'closed'`) and
|
|
141
|
+
all brain behavior are inherited. The open state switches the host between
|
|
142
|
+
`grid-rows-[1fr]` and `hidden`; an inner `div[attr.inert]` keeps closed content out of the
|
|
143
|
+
tab order.
|
|
144
|
+
|
|
145
|
+
| Input | Type | Default | Description |
|
|
146
|
+
| ------- | ------------ | ------- | --------------------------------- |
|
|
147
|
+
| `class` | `ClassValue` | `''` | Extra classes merged via `hlm()`. |
|
|
148
|
+
|
|
149
|
+
### `HlmAccordionIcon` — `ng-icon[egAccordionIcon], ng-icon[hlmAccIcon]`
|
|
150
|
+
|
|
151
|
+
Styling directive for the chevron `ng-icon` inside a trigger. It registers
|
|
152
|
+
`provideIcons({ lucideChevronDown })` and `provideHlmIconConfig({ size: 'sm' })`, and applies the
|
|
153
|
+
muted, small, animated sizing classes.
|
|
154
|
+
|
|
155
|
+
| Input | Type | Default | Description |
|
|
156
|
+
| ------- | ------------ | ------- | --------------------------------- |
|
|
157
|
+
| `class` | `ClassValue` | `''` | Extra classes merged via `hlm()`. |
|
|
158
|
+
|
|
159
|
+
> **Selector quirk (read from source):** the trigger stylesheet contains a
|
|
160
|
+
> `[&[data-state=open]>[egAccIcon]]:rotate-180` rule, but the icon directive itself matches
|
|
161
|
+
> `egAccordionIcon` / `hlmAccIcon`. If you want the chevron to rotate automatically on open, add a
|
|
162
|
+
> plain `egAccIcon` attribute to the icon element alongside the directive attribute
|
|
163
|
+
> (see the rotation example below).
|
|
164
|
+
|
|
165
|
+
## Examples
|
|
166
|
+
|
|
167
|
+
### 1. Basic single accordion
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
import { Component } from '@angular/core';
|
|
171
|
+
import { HlmAccordionImports } from '@egose/shadcn-theme-ng/accordion';
|
|
172
|
+
|
|
173
|
+
@Component({
|
|
174
|
+
selector: 'app-accordion-basic',
|
|
175
|
+
standalone: true,
|
|
176
|
+
imports: [...HlmAccordionImports],
|
|
177
|
+
template: `
|
|
178
|
+
<hlm-accordion type="single">
|
|
179
|
+
<hlm-accordion-item>
|
|
180
|
+
<button hlmAccordionTrigger>
|
|
181
|
+
Is it accessible?
|
|
182
|
+
<ng-icon hlmAccIcon name="lucideChevronDown" />
|
|
183
|
+
</button>
|
|
184
|
+
<hlm-accordion-content>
|
|
185
|
+
<p>Yes. Triggers are real buttons and closed panels are inert.</p>
|
|
186
|
+
</hlm-accordion-content>
|
|
187
|
+
</hlm-accordion-item>
|
|
188
|
+
<hlm-accordion-item>
|
|
189
|
+
<button hlmAccordionTrigger>
|
|
190
|
+
Is it styled?
|
|
191
|
+
<ng-icon hlmAccIcon name="lucideChevronDown" />
|
|
192
|
+
</button>
|
|
193
|
+
<hlm-accordion-content>
|
|
194
|
+
<p>Yes. It follows the shadcn/ui accordion look.</p>
|
|
195
|
+
</hlm-accordion-content>
|
|
196
|
+
</hlm-accordion-item>
|
|
197
|
+
</hlm-accordion>
|
|
198
|
+
`,
|
|
199
|
+
})
|
|
200
|
+
export class AccordionBasicComponent {}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
```html
|
|
204
|
+
<app-accordion-basic />
|
|
50
205
|
```
|
|
51
206
|
|
|
52
|
-
|
|
207
|
+
### 2. Multiple open panels + attribute selectors on native elements
|
|
53
208
|
|
|
54
|
-
|
|
209
|
+
`HlmAccordion` also works as an attribute on a `div`, and items accept the long
|
|
210
|
+
`brn-accordion-item[hlm]` spelling for interop with raw brain templates.
|
|
55
211
|
|
|
56
|
-
```
|
|
57
|
-
|
|
212
|
+
```ts
|
|
213
|
+
import { Component } from '@angular/core';
|
|
214
|
+
import { HlmAccordionImports } from '@egose/shadcn-theme-ng/accordion';
|
|
215
|
+
|
|
216
|
+
@Component({
|
|
217
|
+
selector: 'app-accordion-multiple',
|
|
218
|
+
standalone: true,
|
|
219
|
+
imports: [...HlmAccordionImports],
|
|
220
|
+
template: `
|
|
221
|
+
<div hlmAccordion type="multiple">
|
|
222
|
+
<div hlmAccordionItem>
|
|
223
|
+
<button hlmAccordionTrigger>
|
|
224
|
+
Shipping
|
|
225
|
+
<ng-icon egAccordionIcon name="lucideChevronDown" />
|
|
226
|
+
</button>
|
|
227
|
+
<hlm-accordion-content><p>Ships worldwide.</p></hlm-accordion-content>
|
|
228
|
+
</div>
|
|
229
|
+
<div hlmAccordionItem>
|
|
230
|
+
<button hlmAccordionTrigger>
|
|
231
|
+
Returns
|
|
232
|
+
<ng-icon egAccordionIcon name="lucideChevronDown" />
|
|
233
|
+
</button>
|
|
234
|
+
<hlm-accordion-content><p>30-day returns.</p></hlm-accordion-content>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
`,
|
|
238
|
+
})
|
|
239
|
+
export class AccordionMultipleComponent {}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### 3. Pre-opened item via `isOpened`
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
import { Component } from '@angular/core';
|
|
246
|
+
import { HlmAccordionImports } from '@egose/shadcn-theme-ng/accordion';
|
|
247
|
+
|
|
248
|
+
@Component({
|
|
249
|
+
selector: 'app-accordion-open',
|
|
250
|
+
standalone: true,
|
|
251
|
+
imports: [...HlmAccordionImports],
|
|
252
|
+
template: `
|
|
253
|
+
<hlm-accordion type="single">
|
|
254
|
+
<hlm-accordion-item [isOpened]="true">
|
|
255
|
+
<button hlmAccordionTrigger>
|
|
256
|
+
Open by default
|
|
257
|
+
<ng-icon hlmAccIcon name="lucideChevronDown" />
|
|
258
|
+
</button>
|
|
259
|
+
<hlm-accordion-content>
|
|
260
|
+
<p>This panel renders expanded on first paint.</p>
|
|
261
|
+
</hlm-accordion-content>
|
|
262
|
+
</hlm-accordion-item>
|
|
263
|
+
<hlm-accordion-item>
|
|
264
|
+
<button hlmAccordionTrigger>
|
|
265
|
+
Closed by default
|
|
266
|
+
<ng-icon hlmAccIcon name="lucideChevronDown" />
|
|
267
|
+
</button>
|
|
268
|
+
<hlm-accordion-content><p>Opens on click.</p></hlm-accordion-content>
|
|
269
|
+
</hlm-accordion-item>
|
|
270
|
+
</hlm-accordion>
|
|
271
|
+
`,
|
|
272
|
+
})
|
|
273
|
+
export class AccordionOpenComponent {}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### 4. Chevron that rotates on open
|
|
277
|
+
|
|
278
|
+
The stylesheet rotates a child carrying a bare `egAccIcon` attribute when the trigger reports
|
|
279
|
+
`data-state="open"`. Combine it with the icon directive so you keep both the sizing and the
|
|
280
|
+
rotation:
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
import { Component } from '@angular/core';
|
|
284
|
+
import { HlmAccordionImports } from '@egose/shadcn-theme-ng/accordion';
|
|
285
|
+
|
|
286
|
+
@Component({
|
|
287
|
+
selector: 'app-accordion-rotate',
|
|
288
|
+
standalone: true,
|
|
289
|
+
imports: [...HlmAccordionImports],
|
|
290
|
+
template: `
|
|
291
|
+
<hlm-accordion type="single">
|
|
292
|
+
@for (faq of faqs; track faq.q) {
|
|
293
|
+
<hlm-accordion-item>
|
|
294
|
+
<button hlmAccordionTrigger>
|
|
295
|
+
{{ faq.q }}
|
|
296
|
+
<ng-icon hlmAccIcon egAccIcon name="lucideChevronDown" />
|
|
297
|
+
</button>
|
|
298
|
+
<hlm-accordion-content>
|
|
299
|
+
<p>{{ faq.a }}</p>
|
|
300
|
+
</hlm-accordion-content>
|
|
301
|
+
</hlm-accordion-item>
|
|
302
|
+
}
|
|
303
|
+
</hlm-accordion>
|
|
304
|
+
`,
|
|
305
|
+
})
|
|
306
|
+
export class AccordionRotateComponent {
|
|
307
|
+
readonly faqs = [
|
|
308
|
+
{ q: 'What is shadcn?', a: 'A set of re-usable UI patterns.' },
|
|
309
|
+
{ q: 'What is spartan-ng?', a: 'Headless Angular primitives (brain) plus styled (helm) components.' },
|
|
310
|
+
];
|
|
311
|
+
}
|
|
58
312
|
```
|
|
59
313
|
|
|
60
|
-
|
|
314
|
+
### 5. Data-driven FAQ with custom classes
|
|
315
|
+
|
|
316
|
+
Every piece accepts a `class` input merged through `hlm()`, so per-item tweaks compose cleanly:
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
import { Component, signal } from '@angular/core';
|
|
320
|
+
import { HlmAccordionImports } from '@egose/shadcn-theme-ng/accordion';
|
|
321
|
+
|
|
322
|
+
@Component({
|
|
323
|
+
selector: 'app-accordion-faq',
|
|
324
|
+
standalone: true,
|
|
325
|
+
imports: [...HlmAccordionImports],
|
|
326
|
+
template: `
|
|
327
|
+
<hlm-accordion type="single" class="tw:rounded-lg tw:border tw:px-4">
|
|
328
|
+
@for (faq of faqs(); track faq.q) {
|
|
329
|
+
<hlm-accordion-item class="tw:last:border-b-0">
|
|
330
|
+
<button hlmAccordionTrigger class="tw:text-base">
|
|
331
|
+
{{ faq.q }}
|
|
332
|
+
<ng-icon hlmAccIcon name="lucideChevronDown" />
|
|
333
|
+
</button>
|
|
334
|
+
<hlm-accordion-content class="tw:text-muted-foreground">
|
|
335
|
+
<p>{{ faq.a }}</p>
|
|
336
|
+
@if (faq.link) {
|
|
337
|
+
<a class="tw:underline" [href]="faq.link">Learn more</a>
|
|
338
|
+
}
|
|
339
|
+
</hlm-accordion-content>
|
|
340
|
+
</hlm-accordion-item>
|
|
341
|
+
}
|
|
342
|
+
</hlm-accordion>
|
|
343
|
+
`,
|
|
344
|
+
})
|
|
345
|
+
export class AccordionFaqComponent {
|
|
346
|
+
readonly faqs = signal([
|
|
347
|
+
{ q: 'How do I install?', a: 'npm install @egose/shadcn-theme-ng', link: '' },
|
|
348
|
+
{ q: 'Which Tailwind setup?', a: 'Pick the plain or tw: variant.', link: '' },
|
|
349
|
+
]);
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### 6. Horizontal orientation
|
|
354
|
+
|
|
355
|
+
`HlmAccordion` reads the brain `orientation()` signal: `'horizontal'` switches the root to
|
|
356
|
+
`flex-row`, anything else stays `flex-col`.
|
|
357
|
+
|
|
358
|
+
```ts
|
|
359
|
+
import { Component } from '@angular/core';
|
|
360
|
+
import { HlmAccordionImports } from '@egose/shadcn-theme-ng/accordion';
|
|
361
|
+
|
|
362
|
+
@Component({
|
|
363
|
+
selector: 'app-accordion-horizontal',
|
|
364
|
+
standalone: true,
|
|
365
|
+
imports: [...HlmAccordionImports],
|
|
366
|
+
template: `
|
|
367
|
+
<hlm-accordion type="multiple" orientation="horizontal" class="tw:gap-2">
|
|
368
|
+
<hlm-accordion-item class="tw:border tw:rounded-md tw:px-3">
|
|
369
|
+
<button hlmAccordionTrigger>A <ng-icon hlmAccIcon name="lucideChevronDown" /></button>
|
|
370
|
+
<hlm-accordion-content><p>First column.</p></hlm-accordion-content>
|
|
371
|
+
</hlm-accordion-item>
|
|
372
|
+
<hlm-accordion-item class="tw:border tw:rounded-md tw:px-3">
|
|
373
|
+
<button hlmAccordionTrigger>B <ng-icon hlmAccIcon name="lucideChevronDown" /></button>
|
|
374
|
+
<hlm-accordion-content><p>Second column.</p></hlm-accordion-content>
|
|
375
|
+
</hlm-accordion-item>
|
|
376
|
+
</hlm-accordion>
|
|
377
|
+
`,
|
|
378
|
+
})
|
|
379
|
+
export class AccordionHorizontalComponent {}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
## Accessibility notes
|
|
383
|
+
|
|
384
|
+
- Triggers are native `<button>` elements enhanced by `BrnAccordionTrigger`: keyboard focus,
|
|
385
|
+
`Enter`/`Space` activation, and arrow-key navigation between items come from the brain primitive.
|
|
386
|
+
- `HlmAccordionContent` marks its inner wrapper `inert` while closed so hidden content is removed
|
|
387
|
+
from the tab order and assistive-technology traversal.
|
|
388
|
+
- The icon is decorative (`pointer-events-none`); keep the trigger label as real text so screen
|
|
389
|
+
readers announce the section name. If you add `sr-only` helper text, put it inside the trigger,
|
|
390
|
+
not the icon.
|
|
391
|
+
- `HlmAccordionIcon` sets the icon size through `provideHlmIconConfig({ size: 'sm' })` — overriding
|
|
392
|
+
the global icon config locally, so surrounding icons are unaffected.
|
|
393
|
+
|
|
394
|
+
## Theming / CSS variables
|
|
395
|
+
|
|
396
|
+
Styling is class-based (`hlm()` + Tailwind tokens such as `border-border`, `text-muted-foreground`,
|
|
397
|
+
`ring-ring/50`); no component-specific CSS variables are declared. Pass `class` to any piece to
|
|
398
|
+
extend the look, and configure the shadcn theme tokens globally as described in the
|
|
399
|
+
[package README](../../README.md).
|
|
61
400
|
|
|
62
|
-
##
|
|
401
|
+
## Related subpaths
|
|
63
402
|
|
|
64
|
-
|
|
403
|
+
- `@egose/shadcn-theme-ng/icon` — `provideHlmIconConfig`, `HlmIcon` (icon sizing used by the trigger icon)
|
|
404
|
+
- `@egose/shadcn-theme-ng/collapsible` — single-region expand/collapse primitive
|
|
405
|
+
- `@egose/shadcn-theme-ng/separator` — dividers between accordion items
|
|
406
|
+
- `@egose/shadcn-theme-ng/typography` — prose styling for rich accordion bodies
|