ng-hub-ui-buttons 22.1.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 ADDED
@@ -0,0 +1,426 @@
1
+ # ng-hub-ui-buttons
2
+
3
+ [Español](./README.es.md) | **English**
4
+
5
+ [![NPM Version](https://img.shields.io/npm/v/ng-hub-ui-buttons.svg)](https://www.npmjs.com/package/ng-hub-ui-buttons)
6
+ [![Angular](https://img.shields.io/badge/Angular-21%2B-red.svg)](https://angular.dev)
7
+ [![License](https://img.shields.io/npm/l/ng-hub-ui-buttons.svg)](LICENSE)
8
+
9
+ Complete Angular 21+ button system — standard buttons, FAB, speed dial and overlay dropdown — fully signal-based, zero external dependencies beyond `ng-hub-ui-utils`.
10
+
11
+ ## Documentation and Live Examples
12
+
13
+ This package is part of [Hub UI](https://hubui.dev/), a collection of Angular component libraries for standalone apps.
14
+
15
+ - Docs: https://hubui.dev/buttons/overview/
16
+ - Live examples: https://hubui.dev/buttons/examples/
17
+ - Hub UI: https://hubui.dev/
18
+
19
+ ## Library Family `ng-hub-ui`
20
+
21
+ This library is part of the **ng-hub-ui** ecosystem:
22
+
23
+ - [**ng-hub-ui-accordion**](https://www.npmjs.com/package/ng-hub-ui-accordion) _(deprecated — use ng-hub-ui-panels)_
24
+ - [**ng-hub-ui-action-sheet**](https://www.npmjs.com/package/ng-hub-ui-action-sheet)
25
+ - [**ng-hub-ui-avatar**](https://www.npmjs.com/package/ng-hub-ui-avatar)
26
+ - [**ng-hub-ui-board**](https://www.npmjs.com/package/ng-hub-ui-board)
27
+ - [**ng-hub-ui-breadcrumbs**](https://www.npmjs.com/package/ng-hub-ui-breadcrumbs)
28
+ - [**ng-hub-ui-buttons**](https://www.npmjs.com/package/ng-hub-ui-buttons) ← You are here
29
+ - [**ng-hub-ui-calendar**](https://www.npmjs.com/package/ng-hub-ui-calendar)
30
+ - [**ng-hub-ui-dropdown**](https://www.npmjs.com/package/ng-hub-ui-dropdown) _(deprecated — use ng-hub-ui-buttons)_
31
+ - [**ng-hub-ui-forms**](https://www.npmjs.com/package/ng-hub-ui-forms)
32
+ - [**ng-hub-ui-history**](https://www.npmjs.com/package/ng-hub-ui-history)
33
+ - [**ng-hub-ui-milestones**](https://www.npmjs.com/package/ng-hub-ui-milestones)
34
+ - [**ng-hub-ui-modal**](https://www.npmjs.com/package/ng-hub-ui-modal)
35
+ - [**ng-hub-ui-nav**](https://www.npmjs.com/package/ng-hub-ui-nav)
36
+ - [**ng-hub-ui-paginable**](https://www.npmjs.com/package/ng-hub-ui-paginable)
37
+ - [**ng-hub-ui-panels**](https://www.npmjs.com/package/ng-hub-ui-panels)
38
+ - [**ng-hub-ui-portal**](https://www.npmjs.com/package/ng-hub-ui-portal)
39
+ - [**ng-hub-ui-skeleton**](https://www.npmjs.com/package/ng-hub-ui-skeleton)
40
+ - [**ng-hub-ui-sortable**](https://www.npmjs.com/package/ng-hub-ui-sortable)
41
+ - [**ng-hub-ui-stepper**](https://www.npmjs.com/package/ng-hub-ui-stepper)
42
+ - [**ng-hub-ui-toast**](https://www.npmjs.com/package/ng-hub-ui-toast)
43
+ - [**ng-hub-ui-utils**](https://www.npmjs.com/package/ng-hub-ui-utils)
44
+
45
+ ---
46
+
47
+ ## Description
48
+
49
+ `ng-hub-ui-buttons` is a zero-dependency button library for Angular 21+ standalone applications (peer: `ng-hub-ui-utils`). It ships `HubBtnComponent` and `HubBtnDirective` for in-flow buttons, `HubFabComponent` for fixed-viewport floating actions, `HubSpeedDialComponent` for expandable FAB menus, and `HubDropdownDirective` that attaches any `<ng-template>` panel to any trigger via the `OverlayService` — no CDK required. All inputs use the Angular Signals API. Every visual property is a CSS custom property so the entire system themes with a single stylesheet override.
50
+
51
+ ## Features
52
+
53
+ - **Signal-based API** — all inputs use `input()`, `model()` and `output()`; fully `OnPush`-safe and compatible with zoneless apps.
54
+ - **Five variants × six colours** — `solid`, `outline`, `soft`, `ghost` and `link`, each available in `primary`, `secondary`, `success`, `danger`, `warning` and `info`.
55
+ - **Four sizes** — `sm`, `md`, `lg`, `xl` with proportional padding and font scaling.
56
+ - **FAB with nine positions** — fixed-viewport placement at any corner, edge-center or screen-center via CSS logical properties (RTL-ready).
57
+ - **Speed Dial** — expandable FAB menu with `isOpen` two-way model, directional expansion and Escape close.
58
+ - **Overlay Dropdown** — attaches any `<ng-template>` to any trigger; eight placement options, click or hover trigger, backdrop and scroll close, no CDK dependency.
59
+ - **Extensible SCSS token system** — `:where()` zero-specificity defaults mean any consumer rule wins without `!important`. Public mixin API lets you register custom semantic colors.
60
+
61
+ ---
62
+
63
+ ## Quick Start
64
+
65
+ ### 1. Install
66
+
67
+ ```bash
68
+ npm install ng-hub-ui-buttons ng-hub-ui-utils
69
+ ```
70
+
71
+ > **Theming (recommended):** install the shared design tokens:
72
+ >
73
+ > ```bash
74
+ > npm install ng-hub-ui-ds
75
+ > ```
76
+ > ```css
77
+ > @import 'ng-hub-ui-ds/styles/tokens/hub-tokens.css';
78
+ > ```
79
+
80
+ ### 2. Import the components you need
81
+
82
+ All exports are standalone — import only what you use:
83
+
84
+ ```typescript
85
+ import {
86
+ HubBtnComponent,
87
+ HubDropdownDirective,
88
+ HubDropdownPanelComponent,
89
+ HubDropdownItemComponent
90
+ } from 'ng-hub-ui-buttons';
91
+
92
+ @Component({
93
+ standalone: true,
94
+ imports: [HubBtnComponent, HubDropdownDirective, HubDropdownPanelComponent, HubDropdownItemComponent],
95
+ template: `
96
+ <hub-btn [hubDropdown]="menu" placement="bottom-start">Actions</hub-btn>
97
+
98
+ <ng-template #menu>
99
+ <hub-dropdown-panel>
100
+ <hub-dropdown-item (itemClick)="edit()">Edit</hub-dropdown-item>
101
+ <hub-dropdown-item color="danger" (itemClick)="delete()">Delete</hub-dropdown-item>
102
+ </hub-dropdown-panel>
103
+ </ng-template>
104
+ `
105
+ })
106
+ export class MyComponent { }
107
+ ```
108
+
109
+ ---
110
+
111
+ ## Components and Directives
112
+
113
+ ### `HubBtnComponent` — `<hub-btn>`
114
+
115
+ | Input | Type | Default | Description |
116
+ |-------|------|---------|-------------|
117
+ | `variant` | `solid \| outline \| soft \| ghost \| link` | `solid` | Visual style |
118
+ | `color` | `primary \| secondary \| success \| danger \| warning \| info` | `primary` | Semantic colour |
119
+ | `size` | `sm \| md \| lg \| xl` | `md` | Size scale |
120
+ | `iconOnly` | `boolean` | `false` | Equal-padding square button for icon-only use |
121
+ | `loading` | `boolean` | `false` | Shows spinner and blocks interaction |
122
+ | `disabled` | `boolean` | `false` | Disables the button and sets the `disabled` attribute |
123
+
124
+ ### `HubBtnDirective` — `[hubBtn]`
125
+
126
+ Same inputs as `HubBtnComponent`. Apply to a native `<button>` or `<a>` element.
127
+
128
+ ```html
129
+ <button hubBtn variant="outline" color="success">Confirm</button>
130
+ <a hubBtn variant="link" color="primary" href="/docs">Read more</a>
131
+ ```
132
+
133
+ ### `HubFabComponent` — `<hub-fab>`
134
+
135
+ | Input | Type | Default | Description |
136
+ |-------|------|---------|-------------|
137
+ | `position` | `top-start \| top-center \| top-end \| middle-start \| center \| middle-end \| bottom-start \| bottom-center \| bottom-end` | `bottom-end` | Fixed viewport position |
138
+ | `size` | `mini \| standard \| large` | `standard` | Button size |
139
+ | `color` | semantic | `primary` | Colour variant |
140
+ | `collapseOnScroll` | `boolean` | `false` | Hides extended label on scroll, expands on stop |
141
+ | `disabled` | `boolean` | `false` | Disables the button |
142
+
143
+ Output: `fabClick`.
144
+
145
+ ### `HubSpeedDialComponent` — `<hub-speed-dial>`
146
+
147
+ | Input / Output | Type | Default | Description |
148
+ |---|---|---|---|
149
+ | `isOpen` | `model(false)` | `false` | Two-way binding for open/closed state |
150
+ | `position` | same as FAB | `bottom-end` | Fixed viewport position |
151
+ | `color` | semantic | `primary` | Trigger button colour |
152
+ | `direction` | `up \| down \| left \| right` | `up` | Direction in which action items expand |
153
+
154
+ Methods: `open()`, `close()`, `toggle()`. Closes on Escape.
155
+
156
+ Use `hubTrigger` on the element projected as the trigger button:
157
+
158
+ ```html
159
+ <hub-speed-dial>
160
+ <hub-btn hubTrigger color="primary"><i class="fa-solid fa-plus"></i></hub-btn>
161
+ <hub-speed-dial-item icon="fa-solid fa-pen" label="Edit" (itemClick)="edit()" />
162
+ <hub-speed-dial-item icon="fa-solid fa-trash" label="Delete" color="danger" (itemClick)="delete()" />
163
+ </hub-speed-dial>
164
+ ```
165
+
166
+ ### `HubSpeedDialItemComponent` — `<hub-speed-dial-item>`
167
+
168
+ | Input | Type | Default | Description |
169
+ |-------|------|---------|-------------|
170
+ | `icon` | `string` | — | CSS class(es) applied to an `<i>` element (e.g. `fa-solid fa-pen`) |
171
+ | `label` | `string` | — | Tooltip label shown beside the item |
172
+ | `color` | semantic | `primary` | Item button colour |
173
+ | `disabled` | `boolean` | `false` | Disables the item |
174
+
175
+ Output: `itemClick`.
176
+
177
+ ### `HubDropdownDirective` — `[hubDropdown]`
178
+
179
+ | Input | Type | Default | Description |
180
+ |-------|------|---------|-------------|
181
+ | `hubDropdown` | `TemplateRef` | — | Panel template to render in the overlay (required) |
182
+ | `placement` | `bottom-start \| bottom \| bottom-end \| top-start \| top \| top-end \| start \| end` | `bottom-start` | Overlay position relative to the trigger |
183
+ | `trigger` | `click \| hover` | `click` | Event that opens the dropdown |
184
+ | `closeOnSelect` | `boolean` | `true` | Close when the user clicks inside the panel |
185
+ | `disabled` | `boolean` | `false` | Prevents opening |
186
+ | `offsetY` | `number` | `4` | Gap in px between trigger and panel |
187
+ | `panelClass` | `string` | `''` | Extra CSS class added to the overlay panel |
188
+ | `isOpen` | `model(false)` | — | Two-way open state |
189
+
190
+ Outputs: `opened`, `closed`. Methods: `open()`, `close()`, `toggle()`. Closes on Escape, backdrop click and scroll.
191
+
192
+ ### `HubDropdownPanelComponent` — `<hub-dropdown-panel>`
193
+
194
+ Container for dropdown content. Accepts a `color` input for a semantic accent border on the top edge.
195
+
196
+ ### `HubDropdownItemComponent` — `<hub-dropdown-item>`
197
+
198
+ | Input | Type | Default | Description |
199
+ |-------|------|---------|-------------|
200
+ | `color` | semantic \| `default` | `default` | Text colour variant |
201
+ | `icon` | `string` | — | CSS class(es) applied to an `<i>` element before the label |
202
+ | `disabled` | `boolean` | `false` | Prevents click and dims the item |
203
+ | `selected` | `boolean` | `false` | Shows a checkmark indicator |
204
+
205
+ Output: `itemClick`.
206
+
207
+ ### `HubDropdownDividerComponent` — `<hub-dropdown-divider>`
208
+
209
+ Horizontal separator with `role="separator"`.
210
+
211
+ ### `HubDropdownHeaderComponent` — `<hub-dropdown-header>`
212
+
213
+ Uppercase group label inside a dropdown panel.
214
+
215
+ ---
216
+
217
+ ## CSS Customisation
218
+
219
+ All visual properties are CSS custom properties scoped with `:where()` (zero specificity), so any consumer rule overrides them without `!important`.
220
+
221
+ ```css
222
+ /* Button */
223
+ --hub-btn-padding-x: 0.875rem;
224
+ --hub-btn-padding-y: 0.4375rem;
225
+ --hub-btn-border-radius: var(--hub-sys-radius-md, 0.375rem);
226
+ --hub-btn-border-width: 1.5px;
227
+ --hub-btn-font-size: 1rem;
228
+ --hub-btn-font-weight: 500;
229
+ --hub-btn-gap: 0.375rem;
230
+ --hub-btn-transition: all 0.15s ease;
231
+ --hub-btn-spinner-size: 0.875em;
232
+ --hub-btn-disabled-opacity: 0.55;
233
+
234
+ /* FAB */
235
+ --hub-fab-size-mini: 2.5rem;
236
+ --hub-fab-size-standard: 3.5rem;
237
+ --hub-fab-size-large: 4.5rem;
238
+ --hub-fab-border-radius: 50%;
239
+ --hub-fab-shadow: var(--hub-sys-shadow-md);
240
+ --hub-fab-shadow-hover: var(--hub-sys-shadow-lg);
241
+ --hub-fab-offset: 1rem;
242
+ --hub-fab-z-index: 1030;
243
+ --hub-fab-transition: box-shadow 0.2s ease, transform 0.15s ease;
244
+
245
+ /* Speed Dial */
246
+ --hub-speed-dial-gap: 0.625rem;
247
+ --hub-speed-dial-z-index: 1030;
248
+ --hub-speed-dial-animation: 0.2s ease;
249
+
250
+ /* Dropdown panel */
251
+ --hub-dropdown-panel-min-width: 11.25rem;
252
+ --hub-dropdown-panel-max-height: 20rem;
253
+ --hub-dropdown-panel-padding-y: 0.25rem;
254
+ --hub-dropdown-panel-bg: var(--hub-sys-color-surface-default, #fff);
255
+ --hub-dropdown-panel-border-color: var(--hub-sys-color-border-subtle, #e2e8f0);
256
+ --hub-dropdown-panel-border-radius: var(--hub-sys-radius-md, 0.5rem);
257
+ --hub-dropdown-panel-shadow: var(--hub-sys-shadow-lg);
258
+ --hub-dropdown-panel-z-index: 1000;
259
+
260
+ /* Dropdown item */
261
+ --hub-dropdown-item-padding-x: 0.875rem;
262
+ --hub-dropdown-item-padding-y: 0.4375rem;
263
+ --hub-dropdown-item-hover-bg: var(--hub-sys-color-surface-subtle, #f8fafc);
264
+ --hub-dropdown-item-border-radius: var(--hub-sys-radius-sm, 0.25rem);
265
+ --hub-dropdown-item-disabled-opacity: 0.45;
266
+ ```
267
+
268
+ Semantic colours resolve through `--hub-sys-color-{variant}-*` tokens from `ng-hub-ui-ds`.
269
+
270
+ ---
271
+
272
+ ## SCSS Mixin API
273
+
274
+ Register custom semantic colors without modifying the library. Import the mixin API from the distributed styles:
275
+
276
+ ```scss
277
+ @use 'ng-hub-ui-buttons/styles' as hub;
278
+ ```
279
+
280
+ ### Add a custom color to all five button variants
281
+
282
+ ```scss
283
+ :root {
284
+ --hub-sys-color-brand-default: #ff6b00;
285
+ --hub-sys-color-brand-emphasis: #cc5500;
286
+ --hub-sys-color-brand-subtle: #fff0e6;
287
+ --hub-sys-color-brand-on-default: #fff;
288
+ }
289
+
290
+ hub-btn, [hubBtn] {
291
+ @include hub.hub-btn-color-rules('brand');
292
+ }
293
+ ```
294
+
295
+ ```html
296
+ <hub-btn variant="solid" color="brand">Brand</hub-btn>
297
+ <hub-btn variant="outline" color="brand">Brand</hub-btn>
298
+ ```
299
+
300
+ ### Create a fully custom variant
301
+
302
+ `hub-btn-variant-rules` is the generic primitive. Its defaults match the `ghost` variant — override only the values that differ:
303
+
304
+ ```scss
305
+ hub-btn, [hubBtn] {
306
+ &.hub-btn-inverted.hub-btn-brand {
307
+ @include hub.hub-btn-variant-rules('brand',
308
+ $bg: var(--hub-sys-color-brand-on-default),
309
+ $color: var(--hub-sys-color-brand-default),
310
+ $border: var(--hub-sys-color-brand-default),
311
+ $hover-bg: var(--hub-sys-color-brand-default),
312
+ $hover-color: var(--hub-sys-color-brand-on-default)
313
+ );
314
+ }
315
+ }
316
+ ```
317
+
318
+ ### Add a custom FAB color
319
+
320
+ ```scss
321
+ @include hub.hub-fab-color('brand');
322
+ ```
323
+
324
+ ### Add a custom dropdown color
325
+
326
+ ```scss
327
+ // Panel accent border
328
+ @include hub.hub-dropdown-panel-color('brand');
329
+
330
+ // Item text + hover
331
+ @include hub.hub-dropdown-item-color('brand');
332
+ ```
333
+
334
+ ### Available mixins
335
+
336
+ | Mixin | Context | Description |
337
+ |---|---|---|
338
+ | `hub-btn-variant-rules($type, ...)` | global `hub-btn, [hubBtn]` block | Generic primitive — all variant properties as named params |
339
+ | `hub-btn-color-rules($type)` | global `hub-btn, [hubBtn]` block | All five built-in variants for one custom color |
340
+ | `hub-fab-color($type)` | root | Global `.hub-fab-{type}` color rule |
341
+ | `hub-dropdown-panel-color($type)` | root | Global color rule for `hub-dropdown-panel` |
342
+ | `hub-dropdown-panel-color-rules($type)` | inside `hub-dropdown-panel` selector | CSS properties only — bring your own selector |
343
+ | `hub-dropdown-item-color($type)` | root | Global color rule for `hub-dropdown-item` |
344
+ | `hub-dropdown-item-color-rules($type)` | inside `.hub-dropdown-item__inner` selector | CSS properties only — bring your own selector |
345
+
346
+ ---
347
+
348
+ ## Migrating from `ng-hub-ui-dropdown`
349
+
350
+ `ng-hub-ui-dropdown` is deprecated. Replace:
351
+
352
+ | Old | New |
353
+ |-----|-----|
354
+ | `HubDropdownModule` | `HubDropdownDirective` + `HubDropdownPanelComponent` |
355
+ | `<hub-dropdown>` | `[hubDropdown]="tpl"` on any trigger + `<ng-template #tpl>` |
356
+ | `<hub-dropdown-item>` | `<hub-dropdown-item>` (same selector, new package) |
357
+
358
+ ---
359
+
360
+ ## Contributing
361
+
362
+ Contributions are welcome! Please open an issue or submit a pull request on [GitHub](https://github.com/carlos-morcillo/ng-hub-ui-buttons).
363
+
364
+ ### Pull Request Process
365
+
366
+ 1. Fork the repository
367
+ 2. Create a new branch: `git checkout -b feat/my-new-feature`
368
+ 3. Make your changes
369
+ 4. Add tests for any new functionality
370
+ 5. Update documentation if needed
371
+ 6. Submit a pull request
372
+
373
+ ### Development Guidelines
374
+
375
+ - Write unit tests for new features
376
+ - Follow the Angular style guide
377
+ - Update documentation for API changes
378
+ - Maintain backward compatibility
379
+ - Add JSDoc comments for complex logic
380
+
381
+ ### Commit Guidelines
382
+
383
+ We follow [Conventional Commits](https://www.conventionalcommits.org/):
384
+
385
+ - `feat:` New features
386
+ - `fix:` Bug fixes
387
+ - `docs:` Documentation changes
388
+ - `refactor:` Code refactors
389
+ - `test:` Adding or updating tests
390
+ - `chore:` Maintenance tasks
391
+
392
+ ### Reporting Issues
393
+
394
+ Before creating an issue, please:
395
+
396
+ - Check existing issues
397
+ - Include reproduction steps
398
+ - Specify your environment (Angular version, browser)
399
+
400
+ ---
401
+
402
+ ## Breaking Changes
403
+
404
+ See [BREAKING_CHANGES.md](./BREAKING_CHANGES.md).
405
+
406
+ ## Changelog
407
+
408
+ See [CHANGELOG.md](./CHANGELOG.md).
409
+
410
+ ---
411
+
412
+ ## ☕ Support the Project
413
+
414
+ If you find this project helpful and would like to support its development, you can buy me a coffee:
415
+
416
+ [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/carlosmorcillo)
417
+
418
+ Your support is greatly appreciated and helps maintain and improve this project!
419
+
420
+ ## 📄 License
421
+
422
+ This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
423
+
424
+ ---
425
+
426
+ Made with ❤️ by [Carlos Morcillo Fernández](https://www.carlosmorcillo.com)