@edsis/ui 0.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/README.md +40 -0
- package/accordion/README.md +195 -0
- package/alert/README.md +177 -0
- package/alert-dialog/README.md +239 -0
- package/aspect-ratio/README.md +112 -0
- package/avatar/README.md +176 -0
- package/badge/README.md +133 -0
- package/breadcrumb/README.md +216 -0
- package/button/README.md +139 -0
- package/button-group/README.md +204 -0
- package/calendar/README.md +132 -0
- package/card/README.md +220 -0
- package/carousel/README.md +276 -0
- package/chart/README.md +249 -0
- package/checkbox/README.md +149 -0
- package/collapsible/README.md +191 -0
- package/combobox/README.md +198 -0
- package/command/README.md +275 -0
- package/composer/README.md +235 -0
- package/context-menu/README.md +267 -0
- package/date-picker/README.md +177 -0
- package/dialog/README.md +237 -0
- package/drawer/README.md +145 -0
- package/dropdown-menu/README.md +311 -0
- package/editor/README.md +136 -0
- package/empty/README.md +183 -0
- package/fesm2022/edsis-ui-accordion.mjs +174 -0
- package/fesm2022/edsis-ui-accordion.mjs.map +1 -0
- package/fesm2022/edsis-ui-alert-dialog.mjs +242 -0
- package/fesm2022/edsis-ui-alert-dialog.mjs.map +1 -0
- package/fesm2022/edsis-ui-alert.mjs +90 -0
- package/fesm2022/edsis-ui-alert.mjs.map +1 -0
- package/fesm2022/edsis-ui-aspect-ratio.mjs +33 -0
- package/fesm2022/edsis-ui-aspect-ratio.mjs.map +1 -0
- package/fesm2022/edsis-ui-avatar.mjs +123 -0
- package/fesm2022/edsis-ui-avatar.mjs.map +1 -0
- package/fesm2022/edsis-ui-badge.mjs +47 -0
- package/fesm2022/edsis-ui-badge.mjs.map +1 -0
- package/fesm2022/edsis-ui-breadcrumb.mjs +186 -0
- package/fesm2022/edsis-ui-breadcrumb.mjs.map +1 -0
- package/fesm2022/edsis-ui-button-group.mjs +95 -0
- package/fesm2022/edsis-ui-button-group.mjs.map +1 -0
- package/fesm2022/edsis-ui-button.mjs +64 -0
- package/fesm2022/edsis-ui-button.mjs.map +1 -0
- package/fesm2022/edsis-ui-calendar.mjs +78 -0
- package/fesm2022/edsis-ui-calendar.mjs.map +1 -0
- package/fesm2022/edsis-ui-card.mjs +137 -0
- package/fesm2022/edsis-ui-card.mjs.map +1 -0
- package/fesm2022/edsis-ui-carousel.mjs +310 -0
- package/fesm2022/edsis-ui-carousel.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-area.mjs +6 -0
- package/fesm2022/edsis-ui-chart-area.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-bar.mjs +6 -0
- package/fesm2022/edsis-ui-chart-bar.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-line.mjs +6 -0
- package/fesm2022/edsis-ui-chart-line.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-pie.mjs +6 -0
- package/fesm2022/edsis-ui-chart-pie.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-radar.mjs +6 -0
- package/fesm2022/edsis-ui-chart-radar.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-radial.mjs +6 -0
- package/fesm2022/edsis-ui-chart-radial.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-scatter.mjs +6 -0
- package/fesm2022/edsis-ui-chart-scatter.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart.mjs +3714 -0
- package/fesm2022/edsis-ui-chart.mjs.map +1 -0
- package/fesm2022/edsis-ui-checkbox.mjs +104 -0
- package/fesm2022/edsis-ui-checkbox.mjs.map +1 -0
- package/fesm2022/edsis-ui-collapsible.mjs +116 -0
- package/fesm2022/edsis-ui-collapsible.mjs.map +1 -0
- package/fesm2022/edsis-ui-combobox.mjs +263 -0
- package/fesm2022/edsis-ui-combobox.mjs.map +1 -0
- package/fesm2022/edsis-ui-command.mjs +268 -0
- package/fesm2022/edsis-ui-command.mjs.map +1 -0
- package/fesm2022/edsis-ui-composer.mjs +329 -0
- package/fesm2022/edsis-ui-composer.mjs.map +1 -0
- package/fesm2022/edsis-ui-context-menu.mjs +100 -0
- package/fesm2022/edsis-ui-context-menu.mjs.map +1 -0
- package/fesm2022/edsis-ui-date-picker.mjs +155 -0
- package/fesm2022/edsis-ui-date-picker.mjs.map +1 -0
- package/fesm2022/edsis-ui-dialog.mjs +262 -0
- package/fesm2022/edsis-ui-dialog.mjs.map +1 -0
- package/fesm2022/edsis-ui-drawer.mjs +6 -0
- package/fesm2022/edsis-ui-drawer.mjs.map +1 -0
- package/fesm2022/edsis-ui-dropdown-menu.mjs +466 -0
- package/fesm2022/edsis-ui-dropdown-menu.mjs.map +1 -0
- package/fesm2022/edsis-ui-editor.mjs +692 -0
- package/fesm2022/edsis-ui-editor.mjs.map +1 -0
- package/fesm2022/edsis-ui-empty.mjs +132 -0
- package/fesm2022/edsis-ui-empty.mjs.map +1 -0
- package/fesm2022/edsis-ui-form.mjs +334 -0
- package/fesm2022/edsis-ui-form.mjs.map +1 -0
- package/fesm2022/edsis-ui-hover-card.mjs +284 -0
- package/fesm2022/edsis-ui-hover-card.mjs.map +1 -0
- package/fesm2022/edsis-ui-input-group.mjs +164 -0
- package/fesm2022/edsis-ui-input-group.mjs.map +1 -0
- package/fesm2022/edsis-ui-input-otp.mjs +485 -0
- package/fesm2022/edsis-ui-input-otp.mjs.map +1 -0
- package/fesm2022/edsis-ui-input.mjs +43 -0
- package/fesm2022/edsis-ui-input.mjs.map +1 -0
- package/fesm2022/edsis-ui-item.mjs +241 -0
- package/fesm2022/edsis-ui-item.mjs.map +1 -0
- package/fesm2022/edsis-ui-kanban.mjs +289 -0
- package/fesm2022/edsis-ui-kanban.mjs.map +1 -0
- package/fesm2022/edsis-ui-kbd.mjs +51 -0
- package/fesm2022/edsis-ui-kbd.mjs.map +1 -0
- package/fesm2022/edsis-ui-label.mjs +30 -0
- package/fesm2022/edsis-ui-label.mjs.map +1 -0
- package/fesm2022/edsis-ui-menubar.mjs +302 -0
- package/fesm2022/edsis-ui-menubar.mjs.map +1 -0
- package/fesm2022/edsis-ui-native-select.mjs +61 -0
- package/fesm2022/edsis-ui-native-select.mjs.map +1 -0
- package/fesm2022/edsis-ui-navigation-menu.mjs +399 -0
- package/fesm2022/edsis-ui-navigation-menu.mjs.map +1 -0
- package/fesm2022/edsis-ui-pagination.mjs +216 -0
- package/fesm2022/edsis-ui-pagination.mjs.map +1 -0
- package/fesm2022/edsis-ui-pillbox.mjs +777 -0
- package/fesm2022/edsis-ui-pillbox.mjs.map +1 -0
- package/fesm2022/edsis-ui-popover.mjs +163 -0
- package/fesm2022/edsis-ui-popover.mjs.map +1 -0
- package/fesm2022/edsis-ui-progress.mjs +53 -0
- package/fesm2022/edsis-ui-progress.mjs.map +1 -0
- package/fesm2022/edsis-ui-radio.mjs +111 -0
- package/fesm2022/edsis-ui-radio.mjs.map +1 -0
- package/fesm2022/edsis-ui-resizable.mjs +454 -0
- package/fesm2022/edsis-ui-resizable.mjs.map +1 -0
- package/fesm2022/edsis-ui-scroll-area.mjs +48 -0
- package/fesm2022/edsis-ui-scroll-area.mjs.map +1 -0
- package/fesm2022/edsis-ui-select.mjs +164 -0
- package/fesm2022/edsis-ui-select.mjs.map +1 -0
- package/fesm2022/edsis-ui-separator.mjs +33 -0
- package/fesm2022/edsis-ui-separator.mjs.map +1 -0
- package/fesm2022/edsis-ui-sheet.mjs +264 -0
- package/fesm2022/edsis-ui-sheet.mjs.map +1 -0
- package/fesm2022/edsis-ui-skeleton.mjs +29 -0
- package/fesm2022/edsis-ui-skeleton.mjs.map +1 -0
- package/fesm2022/edsis-ui-slider.mjs +405 -0
- package/fesm2022/edsis-ui-slider.mjs.map +1 -0
- package/fesm2022/edsis-ui-spinner.mjs +58 -0
- package/fesm2022/edsis-ui-spinner.mjs.map +1 -0
- package/fesm2022/edsis-ui-switch.mjs +107 -0
- package/fesm2022/edsis-ui-switch.mjs.map +1 -0
- package/fesm2022/edsis-ui-table.mjs +139 -0
- package/fesm2022/edsis-ui-table.mjs.map +1 -0
- package/fesm2022/edsis-ui-tabs.mjs +252 -0
- package/fesm2022/edsis-ui-tabs.mjs.map +1 -0
- package/fesm2022/edsis-ui-textarea.mjs +37 -0
- package/fesm2022/edsis-ui-textarea.mjs.map +1 -0
- package/fesm2022/edsis-ui-timeline.mjs +213 -0
- package/fesm2022/edsis-ui-timeline.mjs.map +1 -0
- package/fesm2022/edsis-ui-toast.mjs +71 -0
- package/fesm2022/edsis-ui-toast.mjs.map +1 -0
- package/fesm2022/edsis-ui-toggle-group.mjs +269 -0
- package/fesm2022/edsis-ui-toggle-group.mjs.map +1 -0
- package/fesm2022/edsis-ui-toggle.mjs +76 -0
- package/fesm2022/edsis-ui-toggle.mjs.map +1 -0
- package/fesm2022/edsis-ui-tooltip.mjs +339 -0
- package/fesm2022/edsis-ui-tooltip.mjs.map +1 -0
- package/fesm2022/edsis-ui-utils.mjs +13 -0
- package/fesm2022/edsis-ui-utils.mjs.map +1 -0
- package/fesm2022/edsis-ui.mjs +11 -0
- package/fesm2022/edsis-ui.mjs.map +1 -0
- package/form/README.md +210 -0
- package/hover-card/README.md +146 -0
- package/input/README.md +159 -0
- package/input-group/README.md +234 -0
- package/input-otp/README.md +273 -0
- package/item/README.md +247 -0
- package/kanban/README.md +81 -0
- package/kbd/README.md +139 -0
- package/label/README.md +136 -0
- package/menubar/README.md +269 -0
- package/native-select/README.md +176 -0
- package/navigation-menu/README.md +160 -0
- package/package.json +310 -0
- package/pagination/README.md +144 -0
- package/pillbox/README.md +67 -0
- package/popover/README.md +43 -0
- package/progress/README.md +160 -0
- package/radio/README.md +209 -0
- package/resizable/README.md +164 -0
- package/scroll-area/README.md +143 -0
- package/select/README.md +174 -0
- package/separator/README.md +170 -0
- package/sheet/README.md +183 -0
- package/skeleton/README.md +158 -0
- package/slider/README.md +207 -0
- package/spinner/README.md +160 -0
- package/switch/README.md +166 -0
- package/table/README.md +291 -0
- package/tabs/README.md +214 -0
- package/textarea/README.md +154 -0
- package/timeline/README.md +94 -0
- package/toast/README.md +321 -0
- package/toggle/README.md +131 -0
- package/toggle-group/README.md +206 -0
- package/tooltip/README.md +211 -0
- package/types/edsis-ui-accordion.d.ts +51 -0
- package/types/edsis-ui-alert-dialog.d.ts +93 -0
- package/types/edsis-ui-alert.d.ts +37 -0
- package/types/edsis-ui-aspect-ratio.d.ts +12 -0
- package/types/edsis-ui-avatar.d.ts +51 -0
- package/types/edsis-ui-badge.d.ts +19 -0
- package/types/edsis-ui-breadcrumb.d.ts +46 -0
- package/types/edsis-ui-button-group.d.ts +26 -0
- package/types/edsis-ui-button.d.ts +22 -0
- package/types/edsis-ui-calendar.d.ts +33 -0
- package/types/edsis-ui-card.d.ts +60 -0
- package/types/edsis-ui-carousel.d.ts +86 -0
- package/types/edsis-ui-chart-area.d.ts +1 -0
- package/types/edsis-ui-chart-bar.d.ts +1 -0
- package/types/edsis-ui-chart-line.d.ts +1 -0
- package/types/edsis-ui-chart-pie.d.ts +1 -0
- package/types/edsis-ui-chart-radar.d.ts +1 -0
- package/types/edsis-ui-chart-radial.d.ts +1 -0
- package/types/edsis-ui-chart-scatter.d.ts +1 -0
- package/types/edsis-ui-chart.d.ts +1094 -0
- package/types/edsis-ui-checkbox.d.ts +35 -0
- package/types/edsis-ui-collapsible.d.ts +42 -0
- package/types/edsis-ui-combobox.d.ts +51 -0
- package/types/edsis-ui-command.d.ts +99 -0
- package/types/edsis-ui-composer.d.ts +90 -0
- package/types/edsis-ui-context-menu.d.ts +35 -0
- package/types/edsis-ui-date-picker.d.ts +41 -0
- package/types/edsis-ui-dialog.d.ts +87 -0
- package/types/edsis-ui-drawer.d.ts +1 -0
- package/types/edsis-ui-dropdown-menu.d.ts +136 -0
- package/types/edsis-ui-editor.d.ts +123 -0
- package/types/edsis-ui-empty.d.ts +50 -0
- package/types/edsis-ui-form.d.ts +141 -0
- package/types/edsis-ui-hover-card.d.ts +74 -0
- package/types/edsis-ui-input-group.d.ts +51 -0
- package/types/edsis-ui-input-otp.d.ts +136 -0
- package/types/edsis-ui-input.d.ts +16 -0
- package/types/edsis-ui-item.d.ts +88 -0
- package/types/edsis-ui-kanban.d.ts +70 -0
- package/types/edsis-ui-kbd.d.ts +16 -0
- package/types/edsis-ui-label.d.ts +11 -0
- package/types/edsis-ui-menubar.d.ts +67 -0
- package/types/edsis-ui-native-select.d.ts +26 -0
- package/types/edsis-ui-navigation-menu.d.ts +96 -0
- package/types/edsis-ui-pagination.d.ts +34 -0
- package/types/edsis-ui-pillbox.d.ts +157 -0
- package/types/edsis-ui-popover.d.ts +43 -0
- package/types/edsis-ui-progress.d.ts +17 -0
- package/types/edsis-ui-radio.d.ts +40 -0
- package/types/edsis-ui-resizable.d.ts +99 -0
- package/types/edsis-ui-scroll-area.d.ts +19 -0
- package/types/edsis-ui-select.d.ts +57 -0
- package/types/edsis-ui-separator.d.ts +14 -0
- package/types/edsis-ui-sheet.d.ts +76 -0
- package/types/edsis-ui-skeleton.d.ts +10 -0
- package/types/edsis-ui-slider.d.ts +74 -0
- package/types/edsis-ui-spinner.d.ts +13 -0
- package/types/edsis-ui-switch.d.ts +40 -0
- package/types/edsis-ui-table.d.ts +52 -0
- package/types/edsis-ui-tabs.d.ts +92 -0
- package/types/edsis-ui-textarea.d.ts +12 -0
- package/types/edsis-ui-timeline.d.ts +63 -0
- package/types/edsis-ui-toast.d.ts +38 -0
- package/types/edsis-ui-toggle-group.d.ts +89 -0
- package/types/edsis-ui-toggle.d.ts +25 -0
- package/types/edsis-ui-tooltip.d.ts +89 -0
- package/types/edsis-ui-utils.d.ts +5 -0
- package/types/edsis-ui.d.ts +2 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Hover Card
|
|
2
|
+
|
|
3
|
+
Preview additional context on hover or keyboard focus without forcing a full click-to-open interaction.
|
|
4
|
+
|
|
5
|
+
The Angular hover card follows the shadcn composition model with a root container for shared defaults, a trigger directive on the interactive host, and a template-backed content surface rendered through the CDK overlay.
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import {
|
|
11
|
+
HoverCardComponent,
|
|
12
|
+
HoverCardContentDirective,
|
|
13
|
+
HoverCardTriggerDirective,
|
|
14
|
+
} from '@your-scope/angular/component/hover-card';
|
|
15
|
+
import { ButtonComponent } from '@your-scope/angular/component/button';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Composition
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
ui-hover-card
|
|
22
|
+
├── [uiHoverCardTrigger]
|
|
23
|
+
└── ng-template[uiHoverCardContent]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Basic usage
|
|
27
|
+
|
|
28
|
+
```html
|
|
29
|
+
<ui-hover-card [openDelay]="100" [closeDelay]="150">
|
|
30
|
+
<button ui-button variant="link" [uiHoverCardTrigger]="profileCard">@nextjs</button>
|
|
31
|
+
|
|
32
|
+
<ng-template uiHoverCardContent #profileCard="uiHoverCardContent">
|
|
33
|
+
<div
|
|
34
|
+
class="flex w-72 flex-col gap-1 rounded-lg border border-border bg-popover p-4 text-popover-foreground shadow-md">
|
|
35
|
+
<div class="font-semibold">@nextjs</div>
|
|
36
|
+
<p class="text-sm text-muted-foreground">The React Framework - created and maintained by @vercel.</p>
|
|
37
|
+
<p class="text-xs text-muted-foreground">Joined December 2021</p>
|
|
38
|
+
</div>
|
|
39
|
+
</ng-template>
|
|
40
|
+
</ui-hover-card>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Common patterns
|
|
44
|
+
|
|
45
|
+
### Trigger delays
|
|
46
|
+
|
|
47
|
+
Use the root or trigger inputs to control when the preview opens and closes.
|
|
48
|
+
|
|
49
|
+
```html
|
|
50
|
+
<ui-hover-card [openDelay]="150" [closeDelay]="200">
|
|
51
|
+
<a href="/profiles/vercel" [uiHoverCardTrigger]="card">Hover profile</a>
|
|
52
|
+
<ng-template uiHoverCardContent #card="uiHoverCardContent">...</ng-template>
|
|
53
|
+
</ui-hover-card>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Positioning
|
|
57
|
+
|
|
58
|
+
Set `side`, `align`, and `sideOffset` on the root for shared defaults or override them on an individual trigger.
|
|
59
|
+
|
|
60
|
+
```html
|
|
61
|
+
<ui-hover-card side="top" align="start" [sideOffset]="12">
|
|
62
|
+
<button ui-button variant="outline" [uiHoverCardTrigger]="card">Top start</button>
|
|
63
|
+
<ng-template uiHoverCardContent #card="uiHoverCardContent">...</ng-template>
|
|
64
|
+
</ui-hover-card>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Interactive content
|
|
68
|
+
|
|
69
|
+
The overlay remains open while either the trigger or the rendered content is hovered or focused, so links and buttons inside the card remain usable.
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<ui-hover-card>
|
|
73
|
+
<a href="/products/headphones" [uiHoverCardTrigger]="productCard">Wireless Headphones</a>
|
|
74
|
+
<ng-template uiHoverCardContent #productCard="uiHoverCardContent">
|
|
75
|
+
<div
|
|
76
|
+
class="flex w-64 flex-col gap-3 rounded-lg border border-border bg-popover p-4 text-popover-foreground shadow-md">
|
|
77
|
+
<div>
|
|
78
|
+
<div class="font-semibold">Wireless Headphones</div>
|
|
79
|
+
<p class="text-sm text-muted-foreground">Noise cancelling with 30-hour battery life.</p>
|
|
80
|
+
</div>
|
|
81
|
+
<a ui-button href="/products/headphones" size="sm">View product</a>
|
|
82
|
+
</div>
|
|
83
|
+
</ng-template>
|
|
84
|
+
</ui-hover-card>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## API reference
|
|
88
|
+
|
|
89
|
+
### `HoverCardComponent`
|
|
90
|
+
|
|
91
|
+
| Input | Type | Default |
|
|
92
|
+
| ------------ | ---------------------------------------- | ---------- |
|
|
93
|
+
| `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | `'bottom'` |
|
|
94
|
+
| `align` | `'start' \| 'center' \| 'end'` | `'center'` |
|
|
95
|
+
| `sideOffset` | `number` | `8` |
|
|
96
|
+
| `openDelay` | `number` | `100` |
|
|
97
|
+
| `closeDelay` | `number` | `100` |
|
|
98
|
+
|
|
99
|
+
### `HoverCardTriggerDirective` (`[uiHoverCardTrigger]`)
|
|
100
|
+
|
|
101
|
+
| Input | Type | Default |
|
|
102
|
+
| -------------------- | ---------------------------------------- | ------------------- |
|
|
103
|
+
| `uiHoverCardTrigger` | `HoverCardContentDirective` | - |
|
|
104
|
+
| `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | Inherited from root |
|
|
105
|
+
| `align` | `'start' \| 'center' \| 'end'` | Inherited from root |
|
|
106
|
+
| `sideOffset` | `number` | Inherited from root |
|
|
107
|
+
| `openDelay` | `number` | Inherited from root |
|
|
108
|
+
| `closeDelay` | `number` | Inherited from root |
|
|
109
|
+
| `disabled` | `boolean` | `false` |
|
|
110
|
+
|
|
111
|
+
Exposes `isOpen()` and `openedChange`. The host reflects `aria-expanded` and `aria-haspopup="dialog"`.
|
|
112
|
+
|
|
113
|
+
### `HoverCardContentDirective`
|
|
114
|
+
|
|
115
|
+
Use `ng-template[uiHoverCardContent]` with `exportAs="uiHoverCardContent"` to provide the overlay body.
|
|
116
|
+
|
|
117
|
+
## Styling and theming
|
|
118
|
+
|
|
119
|
+
The hover card does not force a panel shell. Apply width, border, background, radius, and elevation classes inside the projected template so the content can match compact profile cards, product previews, or custom dashboards.
|
|
120
|
+
|
|
121
|
+
Use `border-border` for visible borders and `bg-popover text-popover-foreground` for the body shell to stay aligned with the theme tokens used across the library.
|
|
122
|
+
|
|
123
|
+
## Accessibility
|
|
124
|
+
|
|
125
|
+
- Open the card from a real interactive host such as `<button>`, `<a>`, or another focusable control.
|
|
126
|
+
- The card opens on hover and keyboard focus, then remains available while the trigger or overlay content stays hovered or focused.
|
|
127
|
+
- Press `Escape` while the trigger or overlay is focused to dismiss the preview.
|
|
128
|
+
- Keep essential actions available outside the hover card as well; hover cards are best for supplemental context, not critical flows.
|
|
129
|
+
|
|
130
|
+
## Keyboard interactions
|
|
131
|
+
|
|
132
|
+
- `Tab` moves focus to the trigger and opens the card after the configured `openDelay`.
|
|
133
|
+
- `Tab` continues into focusable content inside the overlay without forcing an immediate close.
|
|
134
|
+
- `Shift+Tab` back to the trigger keeps the preview open.
|
|
135
|
+
- `Escape` closes the preview.
|
|
136
|
+
|
|
137
|
+
## Angular notes
|
|
138
|
+
|
|
139
|
+
- The root `ui-hover-card` provides shared defaults. Override placement or timing on an individual trigger only when one example needs different behavior.
|
|
140
|
+
- The content stays template-backed instead of adding a dedicated content component so the overlay body can remain fully custom.
|
|
141
|
+
- Because the content renders through the CDK overlay container, set `dir` on the projected body when an individual card needs RTL behavior independent of the application shell.
|
|
142
|
+
- If you need click-to-open behavior instead of hover and focus, use the Popover primitive instead.
|
|
143
|
+
|
|
144
|
+
## Source parity
|
|
145
|
+
|
|
146
|
+
This implementation preserves the shadcn structure, trigger delay inputs, side and alignment controls, and interactive hover path between trigger and content, while adapting the API to Angular selectors and CDK overlay primitives.
|
package/input/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Input
|
|
2
|
+
|
|
3
|
+
Text input for forms and user data entry with shadcn-style visual states and Angular-friendly composition.
|
|
4
|
+
|
|
5
|
+
The input itself stays a native `<input>` element. When the current shadcn docs mention `Field`, `FieldLabel`, or
|
|
6
|
+
`FieldDescription`, the local Angular mapping is the existing form primitives rather than a separate runtime `Form`
|
|
7
|
+
component.
|
|
8
|
+
|
|
9
|
+
## Import
|
|
10
|
+
|
|
11
|
+
For the simplest standalone field:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { InputComponent } from '@edsis/ui/input';
|
|
15
|
+
import { LabelComponent } from '@edsis/ui/label';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
For the richer field composition used throughout the shadcn Input docs:
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import {
|
|
22
|
+
FormControlDirective,
|
|
23
|
+
FormDescriptionComponent,
|
|
24
|
+
FormFieldComponent,
|
|
25
|
+
FormLabelComponent,
|
|
26
|
+
FormMessageComponent,
|
|
27
|
+
} from '@edsis/ui/form';
|
|
28
|
+
import { InputComponent } from '@edsis/ui/input';
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
### Standalone input
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<label ui-label for="email">Email</label> <input id="email" ui-input type="email" placeholder="you@example.com" />
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Field mapping
|
|
40
|
+
|
|
41
|
+
Use the local form primitives when you need the label, helper text, and invalid-state wiring shown in the upstream
|
|
42
|
+
shadcn examples:
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<ui-form-field>
|
|
46
|
+
<ui-form-label>Email</ui-form-label>
|
|
47
|
+
<input ui-input uiFormControl type="email" placeholder="you@example.com" />
|
|
48
|
+
<ui-form-description>We'll only use this address for account updates.</ui-form-description>
|
|
49
|
+
<ui-form-message>Enter a valid email address.</ui-form-message>
|
|
50
|
+
</ui-form-field>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Common Patterns
|
|
54
|
+
|
|
55
|
+
### Reactive forms
|
|
56
|
+
|
|
57
|
+
`ui-input` keeps Angular's standard `DefaultValueAccessor`, so reactive forms and `formControlName` work without a
|
|
58
|
+
wrapper component.
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
readonly profileForm = new FormGroup({
|
|
62
|
+
email: new FormControl('', {
|
|
63
|
+
nonNullable: true,
|
|
64
|
+
validators: [Validators.required, Validators.email],
|
|
65
|
+
}),
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```html
|
|
70
|
+
<ui-form-field>
|
|
71
|
+
<ui-form-label>Email</ui-form-label>
|
|
72
|
+
<input ui-input uiFormControl formControlName="email" type="email" placeholder="john@example.com" />
|
|
73
|
+
<ui-form-description>We'll never share your email with anyone.</ui-form-description>
|
|
74
|
+
<ui-form-message>Enter a valid email address.</ui-form-message>
|
|
75
|
+
</ui-form-field>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Invalid state without Angular forms
|
|
79
|
+
|
|
80
|
+
If the field participates in a validation flow outside Angular forms, forward `aria-invalid="true"` manually.
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<input ui-input aria-invalid="true" placeholder="Error" />
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### File input
|
|
87
|
+
|
|
88
|
+
The same directive styles file inputs while preserving the browser-native file picker.
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<ui-form-field>
|
|
92
|
+
<ui-form-label>Picture</ui-form-label>
|
|
93
|
+
<input ui-input uiFormControl type="file" />
|
|
94
|
+
<ui-form-description>Select a picture to upload.</ui-form-description>
|
|
95
|
+
</ui-form-field>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Inline actions
|
|
99
|
+
|
|
100
|
+
For search bars or quick actions, compose the input with `ui-button` instead of inventing a synthetic group API.
|
|
101
|
+
|
|
102
|
+
```html
|
|
103
|
+
<div class="flex max-w-md items-center gap-2">
|
|
104
|
+
<input ui-input type="search" placeholder="Search..." class="flex-1" />
|
|
105
|
+
<button ui-button type="button">Search</button>
|
|
106
|
+
</div>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## API Reference
|
|
110
|
+
|
|
111
|
+
### `InputComponent`
|
|
112
|
+
|
|
113
|
+
| Input | Type | Default |
|
|
114
|
+
| ------- | -------- | ------- |
|
|
115
|
+
| `class` | `string` | `''` |
|
|
116
|
+
|
|
117
|
+
All native `<input>` attributes such as `type`, `placeholder`, `required`, `disabled`, `autocomplete`, and `value`
|
|
118
|
+
continue to work as usual.
|
|
119
|
+
|
|
120
|
+
### Field Mapping
|
|
121
|
+
|
|
122
|
+
- `Field` maps to `ui-form-field`.
|
|
123
|
+
- `FieldLabel` maps to `ui-form-label`.
|
|
124
|
+
- `FieldDescription` maps to `ui-form-description`.
|
|
125
|
+
- Invalid and helper-text wiring come from `[uiFormControl]` plus `ui-form-message`.
|
|
126
|
+
|
|
127
|
+
## Styling and Theming
|
|
128
|
+
|
|
129
|
+
Theme tokens used by the input styles include `--border`, `--input`, `--foreground`, `--muted-foreground`, `--ring`,
|
|
130
|
+
and `--destructive`.
|
|
131
|
+
|
|
132
|
+
When `aria-invalid="true"` is present, the border and focus ring switch to the destructive treatment. Pass `class`
|
|
133
|
+
for layout utilities such as width, flex growth, or spacing around the native control.
|
|
134
|
+
|
|
135
|
+
## Accessibility
|
|
136
|
+
|
|
137
|
+
- Pair every input with a visible label or another accessible name source.
|
|
138
|
+
- Use `uiFormControl` inside `ui-form-field` when the control should auto-wire `id`, `aria-describedby`, and invalid
|
|
139
|
+
state.
|
|
140
|
+
- Keep helper text and validation messages adjacent to the field so screen readers announce the full context.
|
|
141
|
+
- Do not remove the focus ring; the component keeps a visible keyboard-only focus treatment.
|
|
142
|
+
|
|
143
|
+
## Keyboard Interactions
|
|
144
|
+
|
|
145
|
+
- The component preserves the browser-native keyboard behavior of the underlying input element.
|
|
146
|
+
- File, search, email, password, and text variants continue to use the interactions defined by their native type.
|
|
147
|
+
- Any adjacent action button, such as a search trigger, remains a separate Tab stop.
|
|
148
|
+
|
|
149
|
+
## Angular Notes
|
|
150
|
+
|
|
151
|
+
- `ui-input` is an attribute selector on the native `<input>` element.
|
|
152
|
+
- It works with both `ngModel` and reactive forms because Angular still sees the underlying native control.
|
|
153
|
+
- `uiFormControl` is optional; use it when the field participates in the local form-primitive composition.
|
|
154
|
+
|
|
155
|
+
## Source Parity
|
|
156
|
+
|
|
157
|
+
This Angular implementation follows the current shadcn Input information architecture while translating `Field` to the
|
|
158
|
+
local form primitives. Upstream `Input Group` and `Button Group` examples are intentionally left to their own planned
|
|
159
|
+
components instead of being faked inside the input API.
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Input Group
|
|
2
|
+
|
|
3
|
+
Grouped input primitives for prefixes, suffixes, stacked helper rows, and inline actions.
|
|
4
|
+
|
|
5
|
+
Use Input Group when the field and its addon content should read as a single control boundary instead of separate neighboring elements.
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { FormControlDirective, FormDescriptionComponent, FormFieldComponent, FormLabelComponent } from '@edsis/ui/form';
|
|
11
|
+
import {
|
|
12
|
+
InputGroupAddonComponent,
|
|
13
|
+
InputGroupButtonComponent,
|
|
14
|
+
InputGroupComponent,
|
|
15
|
+
InputGroupInputComponent,
|
|
16
|
+
InputGroupTextComponent,
|
|
17
|
+
InputGroupTextareaComponent,
|
|
18
|
+
} from '@edsis/ui/input-group';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Keep the input or textarea first in the DOM, then append one or more addons after it.
|
|
24
|
+
Use the `align` input on `ui-input-group-addon` to place the addon at the inline or block edge.
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<ui-form-field>
|
|
28
|
+
<ui-form-label>Search</ui-form-label>
|
|
29
|
+
<ui-input-group>
|
|
30
|
+
<input ui-input-group-input uiFormControl placeholder="Search documentation..." />
|
|
31
|
+
<ui-input-group-addon>
|
|
32
|
+
<span aria-hidden="true">⌕</span>
|
|
33
|
+
</ui-input-group-addon>
|
|
34
|
+
<ui-input-group-addon align="inline-end">
|
|
35
|
+
<ui-input-group-text>12 results</ui-input-group-text>
|
|
36
|
+
</ui-input-group-addon>
|
|
37
|
+
</ui-input-group>
|
|
38
|
+
<ui-form-description
|
|
39
|
+
>Keep addons after the control in the DOM and use align for visual placement.</ui-form-description
|
|
40
|
+
>
|
|
41
|
+
</ui-form-field>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Composition
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
ui-input-group
|
|
48
|
+
├── input[ui-input-group-input] or textarea[ui-input-group-textarea]
|
|
49
|
+
├── ui-input-group-addon
|
|
50
|
+
│ ├── ui-input-group-text
|
|
51
|
+
│ └── button[ui-input-group-button]
|
|
52
|
+
└── ui-input-group-addon
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Common Patterns
|
|
56
|
+
|
|
57
|
+
### Inline search
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<ui-input-group class="max-w-md">
|
|
61
|
+
<input ui-input-group-input placeholder="Search..." />
|
|
62
|
+
<ui-input-group-addon>
|
|
63
|
+
<span aria-hidden="true">⌕</span>
|
|
64
|
+
</ui-input-group-addon>
|
|
65
|
+
<ui-input-group-addon align="inline-end">
|
|
66
|
+
<ui-input-group-text>12 results</ui-input-group-text>
|
|
67
|
+
</ui-input-group-addon>
|
|
68
|
+
</ui-input-group>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Text addons
|
|
72
|
+
|
|
73
|
+
```html
|
|
74
|
+
<ui-input-group>
|
|
75
|
+
<input ui-input-group-input placeholder="0.00" />
|
|
76
|
+
<ui-input-group-addon>
|
|
77
|
+
<ui-input-group-text>$</ui-input-group-text>
|
|
78
|
+
</ui-input-group-addon>
|
|
79
|
+
<ui-input-group-addon align="inline-end">
|
|
80
|
+
<ui-input-group-text>USD</ui-input-group-text>
|
|
81
|
+
</ui-input-group-addon>
|
|
82
|
+
</ui-input-group>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Textarea footer
|
|
86
|
+
|
|
87
|
+
```html
|
|
88
|
+
<ui-input-group>
|
|
89
|
+
<textarea ui-input-group-textarea placeholder="Write a comment..."></textarea>
|
|
90
|
+
<ui-input-group-addon align="block-end">
|
|
91
|
+
<ui-input-group-text>0/280</ui-input-group-text>
|
|
92
|
+
<button ui-input-group-button type="button" size="sm" variant="default" class="ml-auto">Post</button>
|
|
93
|
+
</ui-input-group-addon>
|
|
94
|
+
</ui-input-group>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Custom control
|
|
98
|
+
|
|
99
|
+
```html
|
|
100
|
+
<ui-input-group>
|
|
101
|
+
<textarea
|
|
102
|
+
data-slot="input-group-control"
|
|
103
|
+
class="min-h-20 w-full resize-none bg-transparent px-3 py-2.5 text-sm outline-none placeholder:text-muted-foreground"
|
|
104
|
+
placeholder="Use any custom control that matches the group contract..."></textarea>
|
|
105
|
+
<ui-input-group-addon align="block-end">
|
|
106
|
+
<button ui-input-group-button type="button" variant="default" size="sm" class="ml-auto">Submit</button>
|
|
107
|
+
</ui-input-group-addon>
|
|
108
|
+
</ui-input-group>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Keyboard shortcut badge
|
|
112
|
+
|
|
113
|
+
```html
|
|
114
|
+
<ui-input-group class="max-w-sm">
|
|
115
|
+
<input ui-input-group-input placeholder="Search..." />
|
|
116
|
+
<ui-input-group-addon>
|
|
117
|
+
<span aria-hidden="true">⌕</span>
|
|
118
|
+
</ui-input-group-addon>
|
|
119
|
+
<ui-input-group-addon align="inline-end">
|
|
120
|
+
<span
|
|
121
|
+
aria-hidden="true"
|
|
122
|
+
class="inline-flex h-6 items-center rounded-md border border-border bg-background px-2 font-mono text-[11px] font-medium text-foreground shadow-sm">
|
|
123
|
+
⌘K
|
|
124
|
+
</span>
|
|
125
|
+
</ui-input-group-addon>
|
|
126
|
+
</ui-input-group>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Dropdown composition
|
|
130
|
+
|
|
131
|
+
Use the local menu primitives when the grouped field needs scoped actions or search destinations.
|
|
132
|
+
|
|
133
|
+
```html
|
|
134
|
+
<ui-input-group>
|
|
135
|
+
<input ui-input-group-input placeholder="Enter file name" />
|
|
136
|
+
<ui-input-group-addon align="inline-end">
|
|
137
|
+
<button
|
|
138
|
+
ui-input-group-button
|
|
139
|
+
type="button"
|
|
140
|
+
size="icon-xs"
|
|
141
|
+
aria-label="Open file actions"
|
|
142
|
+
[uiMenuTrigger]="fileActionsMenu">
|
|
143
|
+
⋯
|
|
144
|
+
</button>
|
|
145
|
+
</ui-input-group-addon>
|
|
146
|
+
</ui-input-group>
|
|
147
|
+
|
|
148
|
+
<ng-template uiMenuContent #fileActionsMenu="uiMenuContent">
|
|
149
|
+
<ui-menu-surface>
|
|
150
|
+
<ui-menu-label>File actions</ui-menu-label>
|
|
151
|
+
<button ui-menu-item type="button">Settings</button>
|
|
152
|
+
<button ui-menu-item type="button">Copy path</button>
|
|
153
|
+
<ui-menu-separator />
|
|
154
|
+
<button ui-menu-item type="button">Open location</button>
|
|
155
|
+
</ui-menu-surface>
|
|
156
|
+
</ng-template>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Spinner status row
|
|
160
|
+
|
|
161
|
+
```html
|
|
162
|
+
<ui-input-group>
|
|
163
|
+
<input ui-input-group-input placeholder="Saving changes..." />
|
|
164
|
+
<ui-input-group-addon align="inline-end">
|
|
165
|
+
<ui-input-group-text>Saving...</ui-input-group-text>
|
|
166
|
+
<span
|
|
167
|
+
aria-hidden="true"
|
|
168
|
+
class="inline-flex size-4 animate-spin rounded-full border-2 border-muted border-t-foreground"></span>
|
|
169
|
+
</ui-input-group-addon>
|
|
170
|
+
</ui-input-group>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## API Reference
|
|
174
|
+
|
|
175
|
+
### `InputGroupComponent`
|
|
176
|
+
|
|
177
|
+
| Input | Type | Default |
|
|
178
|
+
| ------- | -------- | ------------ |
|
|
179
|
+
| `class` | `string` | empty string |
|
|
180
|
+
|
|
181
|
+
### `InputGroupAddonComponent`
|
|
182
|
+
|
|
183
|
+
| Input | Type | Default |
|
|
184
|
+
| ------- | ------------------------------------------------------------- | ---------------- |
|
|
185
|
+
| `align` | `'inline-start', 'inline-end', 'block-start', or 'block-end'` | `'inline-start'` |
|
|
186
|
+
| `class` | `string` | empty string |
|
|
187
|
+
|
|
188
|
+
### `InputGroupButtonComponent`
|
|
189
|
+
|
|
190
|
+
| Input | Type | Default |
|
|
191
|
+
| --------- | ------------------------------------- | ------------ |
|
|
192
|
+
| `variant` | `ButtonVariant` | `'ghost'` |
|
|
193
|
+
| `size` | `'xs', 'icon-xs', 'sm', or 'icon-sm'` | `'xs'` |
|
|
194
|
+
| `class` | `string` | empty string |
|
|
195
|
+
|
|
196
|
+
### `InputGroupInputComponent` and `InputGroupTextareaComponent`
|
|
197
|
+
|
|
198
|
+
| Input | Type | Default |
|
|
199
|
+
| ------- | -------- | ------------ |
|
|
200
|
+
| `class` | `string` | empty string |
|
|
201
|
+
|
|
202
|
+
All other native input and textarea attributes pass through unchanged.
|
|
203
|
+
|
|
204
|
+
## Styling And Theming
|
|
205
|
+
|
|
206
|
+
- `ui-input-group` owns the shared border, focus ring, radius, and background surface.
|
|
207
|
+
- `ui-input-group-addon` uses logical separators so start and end alignments still read correctly in RTL layouts.
|
|
208
|
+
- Override `--radius` on the group root when the grouped field should be sharper or more pill-shaped.
|
|
209
|
+
- Add spacing or typography utilities through `class` on any primitive without breaking the core layout contract.
|
|
210
|
+
|
|
211
|
+
## Accessibility
|
|
212
|
+
|
|
213
|
+
- Keep the input or textarea before addons in the DOM so tab order and assistive reading order stay predictable.
|
|
214
|
+
- Provide a visible label with `ui-form-label`, `ui-label`, or another accessible name source.
|
|
215
|
+
- Give icon-only `ui-input-group-button` elements an `aria-label`.
|
|
216
|
+
- Use `uiFormControl` inside `ui-form-field` when labels, descriptions, and invalid messaging should auto-wire to the grouped control.
|
|
217
|
+
|
|
218
|
+
## Keyboard Interactions
|
|
219
|
+
|
|
220
|
+
- Text input and textarea editing remain native.
|
|
221
|
+
- Buttons inside addons participate in the normal tab sequence after the text control.
|
|
222
|
+
- Changing `align` only affects visual placement; it does not change keyboard order.
|
|
223
|
+
|
|
224
|
+
## Angular Notes
|
|
225
|
+
|
|
226
|
+
- `ui-input-group-input` and `ui-input-group-textarea` are attribute selectors on native controls, so native input and textarea behavior remains intact.
|
|
227
|
+
- For custom controls, set `data-slot="input-group-control"` and provide your own spacing utilities so the wrapper can still coordinate focus and addon layout.
|
|
228
|
+
- Upstream shadcn `Field` examples map to the local `ui-form-field`, `ui-form-label`, and `ui-form-description` primitives rather than a separate `field` runtime component.
|
|
229
|
+
|
|
230
|
+
## Source Parity
|
|
231
|
+
|
|
232
|
+
This Angular implementation covers the core shadcn Input Group primitives, all four addon alignments, textarea support, custom control guidance, and RTL composition.
|
|
233
|
+
|
|
234
|
+
Keyboard shortcut badges, dropdown triggers, and spinner/status rows are composed from the same primitives plus the local menu surface and inline status markup instead of requiring input-group-specific wrappers.
|