semmet-angular 0.27.0 → 0.28.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.en.md +244 -0
- package/README.md +137 -121
- package/README.pt-BR.md +256 -0
- package/package.json +3 -1
package/README.en.md
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# semmet-angular
|
|
2
|
+
|
|
3
|
+
**Accessible UI Delivery Kit for Angular.**
|
|
4
|
+
|
|
5
|
+
`semmet-angular` is a delivery-focused schematic collection for Angular teams that want to ship accessible UI faster: components with real ARIA behavior, a consistent visual identity, and generated test files from the first command.
|
|
6
|
+
|
|
7
|
+
Semmet Angular helps teams generate, test, verify, and package accessible Angular UI using the Angular CLI ecosystem.
|
|
8
|
+
|
|
9
|
+
**Gerar. Testar. Verificar. Empacotar.**
|
|
10
|
+
|
|
11
|
+
Read the broader product direction in [PRODUCT_VISION.md](./PRODUCT_VISION.md).
|
|
12
|
+
|
|
13
|
+
Brazilian Portuguese documentation is available in [README.md](./README.md).
|
|
14
|
+
|
|
15
|
+
`ng generate semmet-angular:accordion my-faq` scaffolds a standalone, signals-based Angular component — `.ts`/`.html`/`.css` — plus `.spec.ts` and `.e2e-spec.ts` smoke tests. The generated component implements a W3C ARIA Authoring Practices Guide pattern for real: correct roles and `aria-*` wiring, the keyboard/focus behavior the pattern requires (arrow-key navigation, focus traps, focus restoration...), and a consistent visual identity out of the box.
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
ng add semmet-angular
|
|
21
|
+
ng generate semmet-angular:accordion my-faq
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`ng add semmet-angular` installs the package and configures the delivery workflow once for the target application, including Playwright e2e support and npm scripts. Each generated component is dropped into your project exactly like `ng generate component` would (respecting your `angular.json` project, source root, and selector prefix), and has **zero runtime dependency** on this package — `semmet-angular` is only needed at generation time.
|
|
25
|
+
|
|
26
|
+
## Generated tests
|
|
27
|
+
|
|
28
|
+
Every component schematic generates test files next to the component:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
my-faq.ts
|
|
32
|
+
my-faq.html
|
|
33
|
+
my-faq.css
|
|
34
|
+
my-faq.spec.ts
|
|
35
|
+
my-faq.e2e-spec.ts
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The unit test uses Angular's `TestBed` to verify the component through its public selector. Interactive components also generate behavior-focused tests for their ARIA state, keyboard flow, value changes, focus management, and open/close behavior. The e2e test uses Playwright and becomes active as soon as the component is mounted in a route or host component. If the component has not been added to any rendered page yet, the generated e2e smoke test is skipped with a clear message instead of failing the whole suite.
|
|
39
|
+
|
|
40
|
+
After running `ng add semmet-angular`, use:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
npm test
|
|
44
|
+
npm run e2e
|
|
45
|
+
npm run e2e:ui
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`npm run e2e` runs Playwright against the Angular dev server configured by `playwright.config.ts`; `npm run e2e:ui` opens Playwright's interactive UI.
|
|
49
|
+
|
|
50
|
+
## Projected content containers
|
|
51
|
+
|
|
52
|
+
Some generated components are containers: they own the ARIA wiring, keyboard behavior, focus management, and visual shell, while your app owns the content rendered inside them.
|
|
53
|
+
|
|
54
|
+
`accordion`, `tabs`, `carousel`, `disclosure`, `card`, `button`, `badge`, `navbar`, `table`, and `button-group` use Angular's modern projection pattern with `ng-template`, signal queries, and `NgTemplateOutlet`. This means you can place real app components inside generated components without dynamic component factories.
|
|
55
|
+
|
|
56
|
+
Example after generating `faq`:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
import { Component, signal } from '@angular/core';
|
|
60
|
+
import { Faq, FaqItem } from './faq/faq';
|
|
61
|
+
import { ProfilePanel } from './profile-panel/profile-panel';
|
|
62
|
+
import { SettingsPanel } from './settings-panel/settings-panel';
|
|
63
|
+
|
|
64
|
+
@Component({
|
|
65
|
+
selector: 'app-root',
|
|
66
|
+
imports: [Faq, FaqItem, ProfilePanel, SettingsPanel],
|
|
67
|
+
templateUrl: './app.html',
|
|
68
|
+
})
|
|
69
|
+
export class App {
|
|
70
|
+
readonly userId = signal(123);
|
|
71
|
+
|
|
72
|
+
reload(): void {}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
<app-faq>
|
|
78
|
+
<ng-template faqItem id="profile" title="Profile" [expanded]="true">
|
|
79
|
+
<app-profile-panel />
|
|
80
|
+
</ng-template>
|
|
81
|
+
|
|
82
|
+
<ng-template faqItem id="settings" title="Settings">
|
|
83
|
+
<app-settings-panel [userId]="userId()" (saved)="reload()" />
|
|
84
|
+
</ng-template>
|
|
85
|
+
</app-faq>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The same pattern applies to `tabs`, `carousel`, and `disclosure`:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
<app-settings-tabs>
|
|
92
|
+
<ng-template settingsTabsItem id="profile" label="Profile" [selected]="true">
|
|
93
|
+
<app-profile-panel />
|
|
94
|
+
</ng-template>
|
|
95
|
+
</app-settings-tabs>
|
|
96
|
+
|
|
97
|
+
<app-featured-carousel>
|
|
98
|
+
<ng-template featuredCarouselSlide id="intro" label="Introduction">
|
|
99
|
+
<app-intro-slide />
|
|
100
|
+
</ng-template>
|
|
101
|
+
</app-featured-carousel>
|
|
102
|
+
|
|
103
|
+
<app-details label="Show profile details" [(expanded)]="profileDetailsOpen">
|
|
104
|
+
<ng-template detailsContent>
|
|
105
|
+
<app-profile-details [userId]="userId()" />
|
|
106
|
+
</ng-template>
|
|
107
|
+
</app-details>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
By default, projected panel/slide content is preserved after its first render. Set `[preserveContent]="false"` on the generated container to destroy inactive content when it closes or becomes inactive.
|
|
111
|
+
|
|
112
|
+
The smaller structural schematics keep their simple input APIs and add safe slots where the generated component still owns the accessible structure:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
<app-product-card title="Accessible components">
|
|
116
|
+
<ng-template productCardMedia>
|
|
117
|
+
<img src="/assets/card.png" alt="Generated Angular component preview" />
|
|
118
|
+
</ng-template>
|
|
119
|
+
|
|
120
|
+
<ng-template productCardDescription>
|
|
121
|
+
Generate Angular components with ARIA, keyboard behavior and signals.
|
|
122
|
+
</ng-template>
|
|
123
|
+
|
|
124
|
+
<ng-template productCardActions>
|
|
125
|
+
<a href="/docs">Read docs</a>
|
|
126
|
+
</ng-template>
|
|
127
|
+
</app-product-card>
|
|
128
|
+
|
|
129
|
+
<app-save-button label="Save">
|
|
130
|
+
<ng-template saveButtonLeading>
|
|
131
|
+
<app-save-icon aria-hidden="true" />
|
|
132
|
+
</ng-template>
|
|
133
|
+
</app-save-button>
|
|
134
|
+
|
|
135
|
+
<app-status-badge accessibleLabel="Build passed">
|
|
136
|
+
<ng-template statusBadgeLabel>Passed</ng-template>
|
|
137
|
+
</app-status-badge>
|
|
138
|
+
|
|
139
|
+
<app-main-navbar brand="Acme">
|
|
140
|
+
<ng-template mainNavbarActions>
|
|
141
|
+
<a href="/account">Account</a>
|
|
142
|
+
</ng-template>
|
|
143
|
+
</app-main-navbar>
|
|
144
|
+
|
|
145
|
+
<app-results-table caption="Quarterly revenue" [rows]="results">
|
|
146
|
+
<ng-template resultsTableEmpty>No revenue results yet.</ng-template>
|
|
147
|
+
</app-results-table>
|
|
148
|
+
|
|
149
|
+
<app-view-switcher [items]="views">
|
|
150
|
+
<ng-template viewSwitcherItem let-item>
|
|
151
|
+
{{ item.label }}
|
|
152
|
+
</ng-template>
|
|
153
|
+
</app-view-switcher>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Schematics (43)
|
|
157
|
+
|
|
158
|
+
**Overlays & disclosure**
|
|
159
|
+
|
|
160
|
+
| Command | Generates | Keyboard/focus behavior implemented |
|
|
161
|
+
|---|---|---|
|
|
162
|
+
| `ng generate semmet-angular:accordion <name>` | [Accordion](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/) | Click/Enter/Space toggle; Up/Down/Home/End moves focus between headers |
|
|
163
|
+
| `ng generate semmet-angular:disclosure <name>` | [Disclosure](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/) | Click/Enter/Space toggle |
|
|
164
|
+
| `ng generate semmet-angular:dialog <name>` | [Dialog (Modal)](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/) | Focus moves in on open; Tab/Shift+Tab focus trap; Escape closes; focus returns to trigger on close |
|
|
165
|
+
| `ng generate semmet-angular:alert-dialog <name>` | [Alert Dialog](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/) | Same focus trap as Dialog; initial focus on the least destructive action (Cancel) |
|
|
166
|
+
| `ng generate semmet-angular:offcanvas <name>` | Offcanvas / Drawer | Modal dialog semantics; focus moves in; Tab/Shift+Tab focus trap; Escape/backdrop close; focus returns to trigger |
|
|
167
|
+
| `ng generate semmet-angular:popover <name>` | Popover | Disclosure trigger with `aria-haspopup="dialog"`; Escape closes; outside click dismisses |
|
|
168
|
+
| `ng generate semmet-angular:tooltip <name>` | [Tooltip](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/) | Shows on hover **and** focus (required for keyboard users); hides on blur/mouseleave/Escape |
|
|
169
|
+
| `ng generate semmet-angular:menu-button <name>` | [Menu Button](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/) | Up/Down/Home/End/Escape inside the menu; closes on outside click; focus returns to the trigger |
|
|
170
|
+
| `ng generate semmet-angular:button <name>` | Button | Native `<button>` with variant, size, disabled, busy, optional pressed state, and safe label/icon slots |
|
|
171
|
+
| `ng generate semmet-angular:button-group <name>` | Button Group | Native grouped buttons with `role="group"`, optional `aria-pressed` toggle state, and safe item-label projection |
|
|
172
|
+
| `ng generate semmet-angular:close-button <name>` | Close Button | Native icon button with required accessible label |
|
|
173
|
+
|
|
174
|
+
**Navigation & structure**
|
|
175
|
+
|
|
176
|
+
| Command | Generates | Keyboard/focus behavior implemented |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| `ng generate semmet-angular:tabs <name>` | [Tabs](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/) | Automatic activation; Left/Right/Home/End with roving `tabindex` |
|
|
179
|
+
| `ng generate semmet-angular:breadcrumb <name>` | [Breadcrumb](https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/) | Static — plain links + `aria-current="page"` |
|
|
180
|
+
| `ng generate semmet-angular:navigation-menu <name>` | [Navigation Menu (Disclosure)](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/) | Click/Enter/Space toggles the submenu — deliberately avoids `role="menu"`, reserved for app-style menus |
|
|
181
|
+
| `ng generate semmet-angular:navbar <name>` | Navbar | Semantic `nav`/list/link structure with responsive disclosure toggle, `aria-current`, and safe brand/action slots |
|
|
182
|
+
| `ng generate semmet-angular:pagination <name>` | Pagination | Working page state; Previous/Next disable at the boundaries |
|
|
183
|
+
| `ng generate semmet-angular:skip-link <name>` | [Skip Link](https://www.w3.org/WAI/WCAG21/Techniques/general/G1) | Hidden until focused, per the standard skip-link pattern |
|
|
184
|
+
| `ng generate semmet-angular:landmarks <name>` | [Landmarks (Page Skeleton)](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/) | Content-projected layout wrapper (`header`/`nav`/`main`/`aside`/`footer` slots) |
|
|
185
|
+
| `ng generate semmet-angular:tree-view <name>` | [Tree View](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/) | Up/Down/Left/Right/Home/End/Enter with roving `tabindex` across visible nodes |
|
|
186
|
+
| `ng generate semmet-angular:toolbar <name>` | [Toolbar](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/) | Left/Right/Home/End with roving `tabindex` |
|
|
187
|
+
| `ng generate semmet-angular:card <name>` | Card | Semantic `<article>` with owned heading/description/action/media structure and safe projection slots |
|
|
188
|
+
| `ng generate semmet-angular:list-group <name>` | List Group | Semantic list structure with action items, active state, optional badges, and disabled states |
|
|
189
|
+
| `ng generate semmet-angular:table <name>` | [Table](https://www.w3.org/WAI/ARIA/apg/patterns/table/) | Caption + scoped headers, input rows, and safe caption/empty-state slots |
|
|
190
|
+
|
|
191
|
+
**Forms & inputs**
|
|
192
|
+
|
|
193
|
+
| Command | Generates | Keyboard/focus behavior implemented |
|
|
194
|
+
|---|---|---|
|
|
195
|
+
| `ng generate semmet-angular:form <name>` | Form | Native `<form>` with labeled controls, inline validation, and status messaging |
|
|
196
|
+
| `ng generate semmet-angular:input <name>` | Input | Native `<input>` with label, hint, validation message wiring, and signal-backed value |
|
|
197
|
+
| `ng generate semmet-angular:select <name>` | Select | Native `<select>` with label, hint, validation message wiring, and signal-backed value |
|
|
198
|
+
| `ng generate semmet-angular:input-group <name>` | Input Group | Native `<input>` with prefix/suffix addons announced via `aria-describedby` and optional action button |
|
|
199
|
+
| `ng generate semmet-angular:textarea <name>` | Textarea | Native `<textarea>` with label, hint, counter, validation message wiring, and signal-backed value |
|
|
200
|
+
| `ng generate semmet-angular:checkbox <name>` | [Checkbox](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/) | Click/Enter/Space toggle |
|
|
201
|
+
| `ng generate semmet-angular:radio-group <name>` | [Radio Group](https://www.w3.org/WAI/ARIA/apg/patterns/radio/) | Up/Down/Left/Right/Home/End move focus and selection together |
|
|
202
|
+
| `ng generate semmet-angular:switch <name>` | [Switch](https://www.w3.org/WAI/ARIA/apg/patterns/switch/) | Native `<button>` — Click/Enter/Space toggle |
|
|
203
|
+
| `ng generate semmet-angular:combobox <name>` | [Combobox](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) | Live filtering; Up/Down/Home/End/Enter/Escape via `aria-activedescendant` |
|
|
204
|
+
| `ng generate semmet-angular:listbox <name>` | [Listbox](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/) | Up/Down/Home/End via `aria-activedescendant` |
|
|
205
|
+
| `ng generate semmet-angular:slider <name>` | [Slider](https://www.w3.org/WAI/ARIA/apg/patterns/slider/) | Arrow keys/PageUp/PageDown/Home/End, plus pointer drag |
|
|
206
|
+
| `ng generate semmet-angular:spinbutton <name>` | [Spinbutton](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/) | Up/Down/Home/End, plus increment/decrement buttons |
|
|
207
|
+
| `ng generate semmet-angular:meter <name>` | [Meter](https://www.w3.org/TR/wai-aria-1.2/#meter) | Static — native `<meter>` bound to a signal |
|
|
208
|
+
| `ng generate semmet-angular:progress-bar <name>` | [Progress Bar](https://www.w3.org/TR/wai-aria-1.2/#progressbar) | Native `<progress>` bound to a signal |
|
|
209
|
+
|
|
210
|
+
**Feedback & media**
|
|
211
|
+
|
|
212
|
+
| Command | Generates | Keyboard/focus behavior implemented |
|
|
213
|
+
|---|---|---|
|
|
214
|
+
| `ng generate semmet-angular:alert <name>` | [Alert](https://www.w3.org/WAI/ARIA/apg/patterns/alert/) | Dismissible assertive live region |
|
|
215
|
+
| `ng generate semmet-angular:toast <name>` | Toast / Notification | Auto-dismisses after 5s (cleaned up via `DestroyRef`); dismissible early |
|
|
216
|
+
| `ng generate semmet-angular:skeleton <name>` | Skeleton Loading | Composable loading placeholder for text, media, circles, cards, and custom blocks |
|
|
217
|
+
| `ng generate semmet-angular:badge <name>` | Badge | Compact status label/counter with decorative mode, optional accessible label, and safe label projection |
|
|
218
|
+
| `ng generate semmet-angular:spinner <name>` | Spinner | Loading status with `role="status"`, visually hidden label by default, and reduced-motion support |
|
|
219
|
+
| `ng generate semmet-angular:carousel <name>` | [Carousel](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/) | Previous/Next controls; `aria-live="polite"` slide region |
|
|
220
|
+
|
|
221
|
+
## What every generated component looks like
|
|
222
|
+
|
|
223
|
+
- Standalone (implicit — no `standalone: true` needed, matches Angular's current default).
|
|
224
|
+
- State via `signal()`/`computed()`, not plain class fields.
|
|
225
|
+
- Templates use the built-in control flow (`@for`, `@if`), not `*ngFor`/`*ngIf`.
|
|
226
|
+
- No `.component` suffix on file names or class names (`accordion.ts`, `export class Accordion`), matching the current `ng generate component` convention.
|
|
227
|
+
- A unique per-instance id (`<name>-0`, `<name>-1`, ...) so multiple instances of the same generated component never collide on `id`/`aria-controls`/`aria-labelledby`.
|
|
228
|
+
- A generated unit test (`.spec.ts`) and Playwright e2e smoke test (`.e2e-spec.ts`) so the component starts life with a test surface.
|
|
229
|
+
|
|
230
|
+
## Visual identity
|
|
231
|
+
|
|
232
|
+
Every generated component shares the same Material Design-informed look — clean surfaces, subtle elevation, a consistent radius/motion scale — using its own color palette (not Material's colors, to stay clear of any lookalike/plagiarism concern). The tokens are plain CSS custom properties declared on each component's `:host` (e.g. `--semmet-color-primary`, `--semmet-radius-md`, `--semmet-elevation-1`), so you can either use the defaults as-is or override the whole family from a global stylesheet without touching the generated files.
|
|
233
|
+
|
|
234
|
+
## Options
|
|
235
|
+
|
|
236
|
+
Every schematic accepts the same three options (same as `ng generate component`):
|
|
237
|
+
|
|
238
|
+
- `name` (required, positional) — component name.
|
|
239
|
+
- `project` — target project; defaults to the current/default project.
|
|
240
|
+
- `path` — target directory; defaults to the project's `src/app`.
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
MIT
|
package/README.md
CHANGED
|
@@ -1,59 +1,75 @@
|
|
|
1
1
|
# semmet-angular
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Kit de entrega de UI acessível para Angular.**
|
|
4
4
|
|
|
5
|
-
`semmet-angular`
|
|
5
|
+
`semmet-angular` é uma coleção de schematics focada em entrega para times Angular que querem publicar interfaces acessíveis mais rápido: componentes com comportamento ARIA real, identidade visual consistente e arquivos de teste gerados desde o primeiro comando.
|
|
6
6
|
|
|
7
|
-
Semmet Angular
|
|
7
|
+
Semmet Angular ajuda times a gerar, testar, verificar e empacotar UI acessível usando o ecossistema do Angular CLI.
|
|
8
8
|
|
|
9
9
|
**Gerar. Testar. Verificar. Empacotar.**
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Leia a direção geral do produto em [PRODUCT_VISION.md](./PRODUCT_VISION.md).
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
English documentation is available in [README.en.md](./README.en.md).
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
`ng generate semmet-angular:accordion minha-faq` cria um componente Angular standalone baseado em signals — `.ts`/`.html`/`.css` — junto com testes `.spec.ts` e `.e2e-spec.ts`. O componente gerado implementa de verdade um padrão do W3C ARIA Authoring Practices Guide: roles corretos, ligação de atributos `aria-*`, comportamento de teclado/foco exigido pelo padrão (navegação por setas, focus trap, restauração de foco...) e uma identidade visual consistente logo de saída.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
## Uso
|
|
18
|
+
|
|
19
|
+
```bash
|
|
18
20
|
ng add semmet-angular
|
|
19
|
-
ng generate semmet-angular:accordion
|
|
21
|
+
ng generate semmet-angular:accordion minha-faq
|
|
20
22
|
```
|
|
21
23
|
|
|
22
|
-
`ng add semmet-angular`
|
|
24
|
+
`ng add semmet-angular` instala o pacote e configura uma vez o fluxo de entrega da aplicação alvo, incluindo suporte a e2e com Playwright e scripts npm. Cada componente gerado entra no seu projeto do mesmo jeito que entraria com `ng generate component` (respeitando `angular.json`, `sourceRoot` e prefixo de seletor), e tem **zero dependência em tempo de execução** deste pacote — `semmet-angular` só é necessário na geração.
|
|
23
25
|
|
|
24
|
-
##
|
|
26
|
+
## Fluxo de Entrega
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
Depois de rodar `ng add semmet-angular`, use:
|
|
27
29
|
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
my-faq.e2e-spec.ts
|
|
30
|
+
```bash
|
|
31
|
+
npm test
|
|
32
|
+
npm run e2e
|
|
33
|
+
npm run e2e:ui
|
|
34
|
+
npm run verify
|
|
34
35
|
```
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
`npm run e2e` executa o Playwright contra o servidor de desenvolvimento Angular configurado por `playwright.config.ts`; `npm run e2e:ui` abre a interface interativa do Playwright.
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
O script `npm run verify` é criado sem sobrescrever um script `verify` existente. Quando os scripts estão disponíveis no `package.json` da aplicação, ele compõe um fluxo simples com:
|
|
39
40
|
|
|
40
|
-
```
|
|
41
|
-
npm test
|
|
41
|
+
```bash
|
|
42
|
+
npm test -- --watch=false
|
|
42
43
|
npm run e2e
|
|
43
|
-
npm run
|
|
44
|
+
npm run build
|
|
45
|
+
npm run lint
|
|
44
46
|
```
|
|
45
47
|
|
|
46
|
-
`
|
|
48
|
+
`lint` só entra quando a aplicação já tem um script `lint`; `build` e `test` seguem a mesma lógica. O `e2e` entra depois da configuração do Playwright feita pelo `ng add`.
|
|
47
49
|
|
|
48
|
-
##
|
|
50
|
+
## Testes Gerados
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
Todo schematic de componente gera arquivos de teste ao lado do componente:
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
```text
|
|
55
|
+
minha-faq.ts
|
|
56
|
+
minha-faq.html
|
|
57
|
+
minha-faq.css
|
|
58
|
+
minha-faq.spec.ts
|
|
59
|
+
minha-faq.e2e-spec.ts
|
|
60
|
+
```
|
|
53
61
|
|
|
54
|
-
|
|
62
|
+
O teste unitário usa o `TestBed` do Angular para verificar o componente pelo seletor público. Componentes interativos também geram testes focados em comportamento: estado ARIA, fluxo de teclado, mudanças de valor, gerenciamento de foco e abertura/fechamento. O teste e2e usa Playwright e passa a valer assim que o componente estiver montado em uma rota ou componente host. Se o componente ainda não estiver em nenhuma página renderizada, o smoke test e2e gerado é pulado com uma mensagem clara, sem quebrar a suíte inteira.
|
|
55
63
|
|
|
56
|
-
|
|
64
|
+
## Containers com Conteúdo Projetado
|
|
65
|
+
|
|
66
|
+
Alguns componentes gerados são containers: eles cuidam da ligação ARIA, comportamento de teclado, gerenciamento de foco e casca visual, enquanto a sua aplicação controla o conteúdo renderizado dentro deles.
|
|
67
|
+
|
|
68
|
+
`accordion`, `tabs`, `carousel`, `disclosure`, `card`, `button`, `badge`, `navbar`, `table` e `button-group` usam o padrão moderno de projeção do Angular com `ng-template`, signal queries e `NgTemplateOutlet`. Isso permite colocar componentes reais da aplicação dentro dos componentes gerados sem factories de componente dinâmico.
|
|
69
|
+
|
|
70
|
+
Exemplo depois de gerar `faq`:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
57
73
|
import { Component, signal } from '@angular/core';
|
|
58
74
|
import { Faq, FaqItem } from './faq/faq';
|
|
59
75
|
import { ProfilePanel } from './profile-panel/profile-panel';
|
|
@@ -71,77 +87,77 @@ export class App {
|
|
|
71
87
|
}
|
|
72
88
|
```
|
|
73
89
|
|
|
74
|
-
```
|
|
90
|
+
```html
|
|
75
91
|
<app-faq>
|
|
76
|
-
<ng-template faqItem id="profile" title="
|
|
92
|
+
<ng-template faqItem id="profile" title="Perfil" [expanded]="true">
|
|
77
93
|
<app-profile-panel />
|
|
78
94
|
</ng-template>
|
|
79
95
|
|
|
80
|
-
<ng-template faqItem id="settings" title="
|
|
96
|
+
<ng-template faqItem id="settings" title="Configurações">
|
|
81
97
|
<app-settings-panel [userId]="userId()" (saved)="reload()" />
|
|
82
98
|
</ng-template>
|
|
83
99
|
</app-faq>
|
|
84
100
|
```
|
|
85
101
|
|
|
86
|
-
|
|
102
|
+
O mesmo padrão vale para `tabs`, `carousel` e `disclosure`:
|
|
87
103
|
|
|
88
|
-
```
|
|
104
|
+
```html
|
|
89
105
|
<app-settings-tabs>
|
|
90
|
-
<ng-template settingsTabsItem id="profile" label="
|
|
106
|
+
<ng-template settingsTabsItem id="profile" label="Perfil" [selected]="true">
|
|
91
107
|
<app-profile-panel />
|
|
92
108
|
</ng-template>
|
|
93
109
|
</app-settings-tabs>
|
|
94
110
|
|
|
95
111
|
<app-featured-carousel>
|
|
96
|
-
<ng-template featuredCarouselSlide id="intro" label="
|
|
112
|
+
<ng-template featuredCarouselSlide id="intro" label="Introdução">
|
|
97
113
|
<app-intro-slide />
|
|
98
114
|
</ng-template>
|
|
99
115
|
</app-featured-carousel>
|
|
100
116
|
|
|
101
|
-
<app-details label="
|
|
117
|
+
<app-details label="Mostrar detalhes do perfil" [(expanded)]="profileDetailsOpen">
|
|
102
118
|
<ng-template detailsContent>
|
|
103
119
|
<app-profile-details [userId]="userId()" />
|
|
104
120
|
</ng-template>
|
|
105
121
|
</app-details>
|
|
106
122
|
```
|
|
107
123
|
|
|
108
|
-
|
|
124
|
+
Por padrão, o conteúdo projetado de painel/slide é preservado depois da primeira renderização. Use `[preserveContent]="false"` no container gerado para destruir conteúdo inativo quando ele fechar ou ficar inativo.
|
|
109
125
|
|
|
110
|
-
|
|
126
|
+
Os schematics estruturais menores mantêm APIs simples por input e adicionam slots seguros onde o componente gerado continua dono da estrutura acessível:
|
|
111
127
|
|
|
112
|
-
```
|
|
113
|
-
<app-product-card title="
|
|
128
|
+
```html
|
|
129
|
+
<app-product-card title="Componentes acessíveis">
|
|
114
130
|
<ng-template productCardMedia>
|
|
115
|
-
<img src="/assets/card.png" alt="
|
|
131
|
+
<img src="/assets/card.png" alt="Prévia de componente Angular gerado" />
|
|
116
132
|
</ng-template>
|
|
117
133
|
|
|
118
134
|
<ng-template productCardDescription>
|
|
119
|
-
|
|
135
|
+
Gere componentes Angular com ARIA, comportamento de teclado e signals.
|
|
120
136
|
</ng-template>
|
|
121
137
|
|
|
122
138
|
<ng-template productCardActions>
|
|
123
|
-
<a href="/docs">
|
|
139
|
+
<a href="/docs">Ler docs</a>
|
|
124
140
|
</ng-template>
|
|
125
141
|
</app-product-card>
|
|
126
142
|
|
|
127
|
-
<app-save-button label="
|
|
143
|
+
<app-save-button label="Salvar">
|
|
128
144
|
<ng-template saveButtonLeading>
|
|
129
145
|
<app-save-icon aria-hidden="true" />
|
|
130
146
|
</ng-template>
|
|
131
147
|
</app-save-button>
|
|
132
148
|
|
|
133
|
-
<app-status-badge accessibleLabel="Build
|
|
134
|
-
<ng-template statusBadgeLabel>
|
|
149
|
+
<app-status-badge accessibleLabel="Build passou">
|
|
150
|
+
<ng-template statusBadgeLabel>Passou</ng-template>
|
|
135
151
|
</app-status-badge>
|
|
136
152
|
|
|
137
153
|
<app-main-navbar brand="Acme">
|
|
138
154
|
<ng-template mainNavbarActions>
|
|
139
|
-
<a href="/
|
|
155
|
+
<a href="/conta">Conta</a>
|
|
140
156
|
</ng-template>
|
|
141
157
|
</app-main-navbar>
|
|
142
158
|
|
|
143
|
-
<app-results-table caption="
|
|
144
|
-
<ng-template resultsTableEmpty>
|
|
159
|
+
<app-results-table caption="Receita trimestral" [rows]="results">
|
|
160
|
+
<ng-template resultsTableEmpty>Nenhum resultado de receita ainda.</ng-template>
|
|
145
161
|
</app-results-table>
|
|
146
162
|
|
|
147
163
|
<app-view-switcher [items]="views">
|
|
@@ -153,90 +169,90 @@ The smaller structural schematics keep their simple input APIs and add safe slot
|
|
|
153
169
|
|
|
154
170
|
## Schematics (43)
|
|
155
171
|
|
|
156
|
-
**Overlays
|
|
172
|
+
**Overlays e disclosure**
|
|
157
173
|
|
|
158
|
-
|
|
|
174
|
+
| Comando | Gera | Comportamento de teclado/foco implementado |
|
|
159
175
|
|---|---|---|
|
|
160
|
-
| `ng generate semmet-angular:accordion <
|
|
161
|
-
| `ng generate semmet-angular:disclosure <
|
|
162
|
-
| `ng generate semmet-angular:dialog <
|
|
163
|
-
| `ng generate semmet-angular:alert-dialog <
|
|
164
|
-
| `ng generate semmet-angular:offcanvas <
|
|
165
|
-
| `ng generate semmet-angular:popover <
|
|
166
|
-
| `ng generate semmet-angular:tooltip <
|
|
167
|
-
| `ng generate semmet-angular:menu-button <
|
|
168
|
-
| `ng generate semmet-angular:button <
|
|
169
|
-
| `ng generate semmet-angular:button-group <
|
|
170
|
-
| `ng generate semmet-angular:close-button <
|
|
171
|
-
|
|
172
|
-
**
|
|
173
|
-
|
|
174
|
-
|
|
|
176
|
+
| `ng generate semmet-angular:accordion <nome>` | [Accordion](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/) | Clique/Enter/Espaço alterna; Cima/Baixo/Home/End move foco entre cabeçalhos |
|
|
177
|
+
| `ng generate semmet-angular:disclosure <nome>` | [Disclosure](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/) | Clique/Enter/Espaço alterna |
|
|
178
|
+
| `ng generate semmet-angular:dialog <nome>` | [Dialog (Modal)](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/) | Foco entra ao abrir; Tab/Shift+Tab prende o foco; Escape fecha; foco volta para o acionador |
|
|
179
|
+
| `ng generate semmet-angular:alert-dialog <nome>` | [Alert Dialog](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/) | Mesmo focus trap do Dialog; foco inicial na ação menos destrutiva (Cancelar) |
|
|
180
|
+
| `ng generate semmet-angular:offcanvas <nome>` | Offcanvas / Drawer | Semântica de dialog modal; foco entra; Tab/Shift+Tab prende o foco; Escape/backdrop fecha; foco volta para o acionador |
|
|
181
|
+
| `ng generate semmet-angular:popover <nome>` | Popover | Acionador disclosure com `aria-haspopup="dialog"`; Escape fecha; clique externo dispensa |
|
|
182
|
+
| `ng generate semmet-angular:tooltip <nome>` | [Tooltip](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/) | Aparece no hover **e** no foco; esconde no blur/mouseleave/Escape |
|
|
183
|
+
| `ng generate semmet-angular:menu-button <nome>` | [Menu Button](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/) | Cima/Baixo/Home/End/Escape dentro do menu; fecha em clique externo; foco volta para o acionador |
|
|
184
|
+
| `ng generate semmet-angular:button <nome>` | Button | `<button>` nativo com variante, tamanho, desabilitado, ocupado, estado pressionado opcional e slots seguros de rótulo/ícone |
|
|
185
|
+
| `ng generate semmet-angular:button-group <nome>` | Button Group | Botões nativos agrupados com `role="group"`, estado toggle opcional com `aria-pressed` e projeção segura de rótulo por item |
|
|
186
|
+
| `ng generate semmet-angular:close-button <nome>` | Close Button | Botão de ícone nativo com rótulo acessível obrigatório |
|
|
187
|
+
|
|
188
|
+
**Navegação e estrutura**
|
|
189
|
+
|
|
190
|
+
| Comando | Gera | Comportamento de teclado/foco implementado |
|
|
175
191
|
|---|---|---|
|
|
176
|
-
| `ng generate semmet-angular:tabs <
|
|
177
|
-
| `ng generate semmet-angular:breadcrumb <
|
|
178
|
-
| `ng generate semmet-angular:navigation-menu <
|
|
179
|
-
| `ng generate semmet-angular:navbar <
|
|
180
|
-
| `ng generate semmet-angular:pagination <
|
|
181
|
-
| `ng generate semmet-angular:skip-link <
|
|
182
|
-
| `ng generate semmet-angular:landmarks <
|
|
183
|
-
| `ng generate semmet-angular:tree-view <
|
|
184
|
-
| `ng generate semmet-angular:toolbar <
|
|
185
|
-
| `ng generate semmet-angular:card <
|
|
186
|
-
| `ng generate semmet-angular:list-group <
|
|
187
|
-
| `ng generate semmet-angular:table <
|
|
188
|
-
|
|
189
|
-
**
|
|
190
|
-
|
|
191
|
-
|
|
|
192
|
+
| `ng generate semmet-angular:tabs <nome>` | [Tabs](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/) | Ativação automática; Esquerda/Direita/Home/End com `tabindex` roving |
|
|
193
|
+
| `ng generate semmet-angular:breadcrumb <nome>` | [Breadcrumb](https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/) | Estático — links simples + `aria-current="page"` |
|
|
194
|
+
| `ng generate semmet-angular:navigation-menu <nome>` | [Navigation Menu (Disclosure)](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/) | Clique/Enter/Espaço alterna submenu; evita `role="menu"` de propósito, reservado para menus de aplicação |
|
|
195
|
+
| `ng generate semmet-angular:navbar <nome>` | Navbar | Estrutura semântica `nav`/lista/link com toggle responsivo, `aria-current` e slots seguros de marca/ações |
|
|
196
|
+
| `ng generate semmet-angular:pagination <nome>` | Pagination | Estado de página funcional; Anterior/Próximo desabilitam nos limites |
|
|
197
|
+
| `ng generate semmet-angular:skip-link <nome>` | [Skip Link](https://www.w3.org/WAI/WCAG21/Techniques/general/G1) | Escondido até receber foco, conforme o padrão de skip link |
|
|
198
|
+
| `ng generate semmet-angular:landmarks <nome>` | [Landmarks (Page Skeleton)](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/) | Wrapper de layout com projeção de conteúdo (`header`/`nav`/`main`/`aside`/`footer`) |
|
|
199
|
+
| `ng generate semmet-angular:tree-view <nome>` | [Tree View](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/) | Cima/Baixo/Esquerda/Direita/Home/End/Enter com `tabindex` roving nos nós visíveis |
|
|
200
|
+
| `ng generate semmet-angular:toolbar <nome>` | [Toolbar](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/) | Esquerda/Direita/Home/End com `tabindex` roving |
|
|
201
|
+
| `ng generate semmet-angular:card <nome>` | Card | `<article>` semântico com heading/descrição/ações/mídia e slots seguros |
|
|
202
|
+
| `ng generate semmet-angular:list-group <nome>` | List Group | Estrutura semântica de lista com itens de ação, estado ativo, badges opcionais e estados desabilitados |
|
|
203
|
+
| `ng generate semmet-angular:table <nome>` | [Table](https://www.w3.org/WAI/ARIA/apg/patterns/table/) | Caption + cabeçalhos escopados, linhas por input e slots seguros de caption/estado vazio |
|
|
204
|
+
|
|
205
|
+
**Formulários e inputs**
|
|
206
|
+
|
|
207
|
+
| Comando | Gera | Comportamento de teclado/foco implementado |
|
|
192
208
|
|---|---|---|
|
|
193
|
-
| `ng generate semmet-angular:form <
|
|
194
|
-
| `ng generate semmet-angular:input <
|
|
195
|
-
| `ng generate semmet-angular:select <
|
|
196
|
-
| `ng generate semmet-angular:input-group <
|
|
197
|
-
| `ng generate semmet-angular:textarea <
|
|
198
|
-
| `ng generate semmet-angular:checkbox <
|
|
199
|
-
| `ng generate semmet-angular:radio-group <
|
|
200
|
-
| `ng generate semmet-angular:switch <
|
|
201
|
-
| `ng generate semmet-angular:combobox <
|
|
202
|
-
| `ng generate semmet-angular:listbox <
|
|
203
|
-
| `ng generate semmet-angular:slider <
|
|
204
|
-
| `ng generate semmet-angular:spinbutton <
|
|
205
|
-
| `ng generate semmet-angular:meter <
|
|
206
|
-
| `ng generate semmet-angular:progress-bar <
|
|
207
|
-
|
|
208
|
-
**Feedback
|
|
209
|
-
|
|
210
|
-
|
|
|
209
|
+
| `ng generate semmet-angular:form <nome>` | Form | `<form>` nativo com controles rotulados, validação inline e mensagens de status |
|
|
210
|
+
| `ng generate semmet-angular:input <nome>` | Input | `<input>` nativo com label, dica, mensagem de validação e valor com signal |
|
|
211
|
+
| `ng generate semmet-angular:select <nome>` | Select | `<select>` nativo com label, dica, mensagem de validação e valor com signal |
|
|
212
|
+
| `ng generate semmet-angular:input-group <nome>` | Input Group | `<input>` nativo com prefixo/sufixo anunciados por `aria-describedby` e botão de ação opcional |
|
|
213
|
+
| `ng generate semmet-angular:textarea <nome>` | Textarea | `<textarea>` nativo com label, dica, contador, mensagem de validação e valor com signal |
|
|
214
|
+
| `ng generate semmet-angular:checkbox <nome>` | [Checkbox](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/) | Clique/Enter/Espaço alterna |
|
|
215
|
+
| `ng generate semmet-angular:radio-group <nome>` | [Radio Group](https://www.w3.org/WAI/ARIA/apg/patterns/radio/) | Cima/Baixo/Esquerda/Direita/Home/End movem foco e seleção juntos |
|
|
216
|
+
| `ng generate semmet-angular:switch <nome>` | [Switch](https://www.w3.org/WAI/ARIA/apg/patterns/switch/) | `<button>` nativo — Clique/Enter/Espaço alterna |
|
|
217
|
+
| `ng generate semmet-angular:combobox <nome>` | [Combobox](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) | Filtro em tempo real; Cima/Baixo/Home/End/Enter/Escape via `aria-activedescendant` |
|
|
218
|
+
| `ng generate semmet-angular:listbox <nome>` | [Listbox](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/) | Cima/Baixo/Home/End via `aria-activedescendant` |
|
|
219
|
+
| `ng generate semmet-angular:slider <nome>` | [Slider](https://www.w3.org/WAI/ARIA/apg/patterns/slider/) | Setas/PageUp/PageDown/Home/End, além de arraste por ponteiro |
|
|
220
|
+
| `ng generate semmet-angular:spinbutton <nome>` | [Spinbutton](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/) | Cima/Baixo/Home/End, além de botões incrementar/decrementar |
|
|
221
|
+
| `ng generate semmet-angular:meter <nome>` | [Meter](https://www.w3.org/TR/wai-aria-1.2/#meter) | Estático — `<meter>` nativo ligado a um signal |
|
|
222
|
+
| `ng generate semmet-angular:progress-bar <nome>` | [Progress Bar](https://www.w3.org/TR/wai-aria-1.2/#progressbar) | `<progress>` nativo ligado a um signal |
|
|
223
|
+
|
|
224
|
+
**Feedback e mídia**
|
|
225
|
+
|
|
226
|
+
| Comando | Gera | Comportamento de teclado/foco implementado |
|
|
211
227
|
|---|---|---|
|
|
212
|
-
| `ng generate semmet-angular:alert <
|
|
213
|
-
| `ng generate semmet-angular:toast <
|
|
214
|
-
| `ng generate semmet-angular:skeleton <
|
|
215
|
-
| `ng generate semmet-angular:badge <
|
|
216
|
-
| `ng generate semmet-angular:spinner <
|
|
217
|
-
| `ng generate semmet-angular:carousel <
|
|
228
|
+
| `ng generate semmet-angular:alert <nome>` | [Alert](https://www.w3.org/WAI/ARIA/apg/patterns/alert/) | Região live assertiva e dispensável |
|
|
229
|
+
| `ng generate semmet-angular:toast <nome>` | Toast / Notification | Auto-dismiss após 5s (limpo via `DestroyRef`); pode ser dispensado antes |
|
|
230
|
+
| `ng generate semmet-angular:skeleton <nome>` | Skeleton Loading | Placeholder de carregamento composível para texto, mídia, círculos, cards e blocos customizados |
|
|
231
|
+
| `ng generate semmet-angular:badge <nome>` | Badge | Rótulo/contador compacto com modo decorativo, rótulo acessível opcional e projeção segura de label |
|
|
232
|
+
| `ng generate semmet-angular:spinner <nome>` | Spinner | Status de carregamento com `role="status"`, rótulo visualmente escondido por padrão e suporte a reduced motion |
|
|
233
|
+
| `ng generate semmet-angular:carousel <nome>` | [Carousel](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/) | Controles Anterior/Próximo; região de slide com `aria-live="polite"` |
|
|
218
234
|
|
|
219
|
-
##
|
|
235
|
+
## Como Cada Componente Gerado É
|
|
220
236
|
|
|
221
|
-
- Standalone (
|
|
222
|
-
-
|
|
223
|
-
- Templates
|
|
224
|
-
-
|
|
225
|
-
-
|
|
226
|
-
-
|
|
237
|
+
- Standalone (implícito — sem `standalone: true`, alinhado ao padrão atual do Angular).
|
|
238
|
+
- Estado via `signal()`/`computed()`, não campos simples de classe.
|
|
239
|
+
- Templates usam o control flow embutido (`@for`, `@if`), não `*ngFor`/`*ngIf`.
|
|
240
|
+
- Sem sufixo `.component` nos nomes de arquivos ou classes (`accordion.ts`, `export class Accordion`), seguindo a convenção atual de `ng generate component`.
|
|
241
|
+
- Id único por instância (`<nome>-0`, `<nome>-1`, ...) para múltiplas instâncias do mesmo componente nunca colidirem em `id`/`aria-controls`/`aria-labelledby`.
|
|
242
|
+
- Teste unitário (`.spec.ts`) e smoke test e2e Playwright (`.e2e-spec.ts`) gerados para o componente já nascer com uma superfície de teste.
|
|
227
243
|
|
|
228
|
-
## Visual
|
|
244
|
+
## Identidade Visual
|
|
229
245
|
|
|
230
|
-
|
|
246
|
+
Todo componente gerado compartilha um visual inspirado em Material Design — superfícies limpas, elevação sutil e escala consistente de raio/movimento — usando sua própria paleta de cores (não as cores do Material, para evitar qualquer risco de cópia visual). Os tokens são CSS custom properties declaradas no `:host` de cada componente (por exemplo, `--semmet-color-primary`, `--semmet-radius-md`, `--semmet-elevation-1`), então você pode usar os defaults como estão ou sobrescrever a família inteira em uma stylesheet global sem tocar nos arquivos gerados.
|
|
231
247
|
|
|
232
|
-
##
|
|
248
|
+
## Opções
|
|
233
249
|
|
|
234
|
-
|
|
250
|
+
Todo schematic aceita as mesmas três opções de `ng generate component`:
|
|
235
251
|
|
|
236
|
-
- `name` (
|
|
237
|
-
- `project` —
|
|
238
|
-
- `path` —
|
|
252
|
+
- `name` (obrigatório, posicional) — nome do componente.
|
|
253
|
+
- `project` — projeto alvo; por padrão, usa o projeto atual/default.
|
|
254
|
+
- `path` — diretório alvo; por padrão, usa `src/app` do projeto.
|
|
239
255
|
|
|
240
|
-
##
|
|
256
|
+
## Licença
|
|
241
257
|
|
|
242
258
|
MIT
|
package/README.pt-BR.md
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# semmet-angular
|
|
2
|
+
|
|
3
|
+
**Kit de entrega de UI acessível para Angular.**
|
|
4
|
+
|
|
5
|
+
`semmet-angular` é uma coleção de schematics focada em entrega para times Angular que querem publicar interfaces acessíveis mais rápido: componentes com comportamento ARIA real, identidade visual consistente e arquivos de teste gerados desde o primeiro comando.
|
|
6
|
+
|
|
7
|
+
Semmet Angular ajuda times a gerar, testar, verificar e empacotar UI acessível usando o ecossistema do Angular CLI.
|
|
8
|
+
|
|
9
|
+
**Gerar. Testar. Verificar. Empacotar.**
|
|
10
|
+
|
|
11
|
+
Leia a direção geral do produto em [PRODUCT_VISION.md](./PRODUCT_VISION.md).
|
|
12
|
+
|
|
13
|
+
`ng generate semmet-angular:accordion minha-faq` cria um componente Angular standalone baseado em signals — `.ts`/`.html`/`.css` — junto com testes `.spec.ts` e `.e2e-spec.ts`. O componente gerado implementa de verdade um padrão do W3C ARIA Authoring Practices Guide: roles corretos, ligação de atributos `aria-*`, comportamento de teclado/foco exigido pelo padrão (navegação por setas, focus trap, restauração de foco...) e uma identidade visual consistente logo de saída.
|
|
14
|
+
|
|
15
|
+
## Uso
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
ng add semmet-angular
|
|
19
|
+
ng generate semmet-angular:accordion minha-faq
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`ng add semmet-angular` instala o pacote e configura uma vez o fluxo de entrega da aplicação alvo, incluindo suporte a e2e com Playwright e scripts npm. Cada componente gerado entra no seu projeto do mesmo jeito que entraria com `ng generate component` (respeitando `angular.json`, `sourceRoot` e prefixo de seletor), e tem **zero dependência em tempo de execução** deste pacote — `semmet-angular` só é necessário na geração.
|
|
23
|
+
|
|
24
|
+
## Fluxo de Entrega
|
|
25
|
+
|
|
26
|
+
Depois de rodar `ng add semmet-angular`, use:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm test
|
|
30
|
+
npm run e2e
|
|
31
|
+
npm run e2e:ui
|
|
32
|
+
npm run verify
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`npm run e2e` executa o Playwright contra o servidor de desenvolvimento Angular configurado por `playwright.config.ts`; `npm run e2e:ui` abre a interface interativa do Playwright.
|
|
36
|
+
|
|
37
|
+
O script `npm run verify` é criado sem sobrescrever um script `verify` existente. Quando os scripts estão disponíveis no `package.json` da aplicação, ele compõe um fluxo simples com:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm test -- --watch=false
|
|
41
|
+
npm run e2e
|
|
42
|
+
npm run build
|
|
43
|
+
npm run lint
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`lint` só entra quando a aplicação já tem um script `lint`; `build` e `test` seguem a mesma lógica. O `e2e` entra depois da configuração do Playwright feita pelo `ng add`.
|
|
47
|
+
|
|
48
|
+
## Testes Gerados
|
|
49
|
+
|
|
50
|
+
Todo schematic de componente gera arquivos de teste ao lado do componente:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
minha-faq.ts
|
|
54
|
+
minha-faq.html
|
|
55
|
+
minha-faq.css
|
|
56
|
+
minha-faq.spec.ts
|
|
57
|
+
minha-faq.e2e-spec.ts
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
O teste unitário usa o `TestBed` do Angular para verificar o componente pelo seletor público. Componentes interativos também geram testes focados em comportamento: estado ARIA, fluxo de teclado, mudanças de valor, gerenciamento de foco e abertura/fechamento. O teste e2e usa Playwright e passa a valer assim que o componente estiver montado em uma rota ou componente host. Se o componente ainda não estiver em nenhuma página renderizada, o smoke test e2e gerado é pulado com uma mensagem clara, sem quebrar a suíte inteira.
|
|
61
|
+
|
|
62
|
+
## Containers com Conteúdo Projetado
|
|
63
|
+
|
|
64
|
+
Alguns componentes gerados são containers: eles cuidam da ligação ARIA, comportamento de teclado, gerenciamento de foco e casca visual, enquanto a sua aplicação controla o conteúdo renderizado dentro deles.
|
|
65
|
+
|
|
66
|
+
`accordion`, `tabs`, `carousel`, `disclosure`, `card`, `button`, `badge`, `navbar`, `table` e `button-group` usam o padrão moderno de projeção do Angular com `ng-template`, signal queries e `NgTemplateOutlet`. Isso permite colocar componentes reais da aplicação dentro dos componentes gerados sem factories de componente dinâmico.
|
|
67
|
+
|
|
68
|
+
Exemplo depois de gerar `faq`:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { Component, signal } from '@angular/core';
|
|
72
|
+
import { Faq, FaqItem } from './faq/faq';
|
|
73
|
+
import { ProfilePanel } from './profile-panel/profile-panel';
|
|
74
|
+
import { SettingsPanel } from './settings-panel/settings-panel';
|
|
75
|
+
|
|
76
|
+
@Component({
|
|
77
|
+
selector: 'app-root',
|
|
78
|
+
imports: [Faq, FaqItem, ProfilePanel, SettingsPanel],
|
|
79
|
+
templateUrl: './app.html',
|
|
80
|
+
})
|
|
81
|
+
export class App {
|
|
82
|
+
readonly userId = signal(123);
|
|
83
|
+
|
|
84
|
+
reload(): void {}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```html
|
|
89
|
+
<app-faq>
|
|
90
|
+
<ng-template faqItem id="profile" title="Perfil" [expanded]="true">
|
|
91
|
+
<app-profile-panel />
|
|
92
|
+
</ng-template>
|
|
93
|
+
|
|
94
|
+
<ng-template faqItem id="settings" title="Configurações">
|
|
95
|
+
<app-settings-panel [userId]="userId()" (saved)="reload()" />
|
|
96
|
+
</ng-template>
|
|
97
|
+
</app-faq>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
O mesmo padrão vale para `tabs`, `carousel` e `disclosure`:
|
|
101
|
+
|
|
102
|
+
```html
|
|
103
|
+
<app-settings-tabs>
|
|
104
|
+
<ng-template settingsTabsItem id="profile" label="Perfil" [selected]="true">
|
|
105
|
+
<app-profile-panel />
|
|
106
|
+
</ng-template>
|
|
107
|
+
</app-settings-tabs>
|
|
108
|
+
|
|
109
|
+
<app-featured-carousel>
|
|
110
|
+
<ng-template featuredCarouselSlide id="intro" label="Introdução">
|
|
111
|
+
<app-intro-slide />
|
|
112
|
+
</ng-template>
|
|
113
|
+
</app-featured-carousel>
|
|
114
|
+
|
|
115
|
+
<app-details label="Mostrar detalhes do perfil" [(expanded)]="profileDetailsOpen">
|
|
116
|
+
<ng-template detailsContent>
|
|
117
|
+
<app-profile-details [userId]="userId()" />
|
|
118
|
+
</ng-template>
|
|
119
|
+
</app-details>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Por padrão, o conteúdo projetado de painel/slide é preservado depois da primeira renderização. Use `[preserveContent]="false"` no container gerado para destruir conteúdo inativo quando ele fechar ou ficar inativo.
|
|
123
|
+
|
|
124
|
+
Os schematics estruturais menores mantêm APIs simples por input e adicionam slots seguros onde o componente gerado continua dono da estrutura acessível:
|
|
125
|
+
|
|
126
|
+
```html
|
|
127
|
+
<app-product-card title="Componentes acessíveis">
|
|
128
|
+
<ng-template productCardMedia>
|
|
129
|
+
<img src="/assets/card.png" alt="Prévia de componente Angular gerado" />
|
|
130
|
+
</ng-template>
|
|
131
|
+
|
|
132
|
+
<ng-template productCardDescription>
|
|
133
|
+
Gere componentes Angular com ARIA, comportamento de teclado e signals.
|
|
134
|
+
</ng-template>
|
|
135
|
+
|
|
136
|
+
<ng-template productCardActions>
|
|
137
|
+
<a href="/docs">Ler docs</a>
|
|
138
|
+
</ng-template>
|
|
139
|
+
</app-product-card>
|
|
140
|
+
|
|
141
|
+
<app-save-button label="Salvar">
|
|
142
|
+
<ng-template saveButtonLeading>
|
|
143
|
+
<app-save-icon aria-hidden="true" />
|
|
144
|
+
</ng-template>
|
|
145
|
+
</app-save-button>
|
|
146
|
+
|
|
147
|
+
<app-status-badge accessibleLabel="Build passou">
|
|
148
|
+
<ng-template statusBadgeLabel>Passou</ng-template>
|
|
149
|
+
</app-status-badge>
|
|
150
|
+
|
|
151
|
+
<app-main-navbar brand="Acme">
|
|
152
|
+
<ng-template mainNavbarActions>
|
|
153
|
+
<a href="/conta">Conta</a>
|
|
154
|
+
</ng-template>
|
|
155
|
+
</app-main-navbar>
|
|
156
|
+
|
|
157
|
+
<app-results-table caption="Receita trimestral" [rows]="results">
|
|
158
|
+
<ng-template resultsTableEmpty>Nenhum resultado de receita ainda.</ng-template>
|
|
159
|
+
</app-results-table>
|
|
160
|
+
|
|
161
|
+
<app-view-switcher [items]="views">
|
|
162
|
+
<ng-template viewSwitcherItem let-item>
|
|
163
|
+
{{ item.label }}
|
|
164
|
+
</ng-template>
|
|
165
|
+
</app-view-switcher>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Schematics (43)
|
|
169
|
+
|
|
170
|
+
**Overlays e disclosure**
|
|
171
|
+
|
|
172
|
+
| Comando | Gera | Comportamento de teclado/foco implementado |
|
|
173
|
+
|---|---|---|
|
|
174
|
+
| `ng generate semmet-angular:accordion <nome>` | [Accordion](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/) | Clique/Enter/Espaço alterna; Cima/Baixo/Home/End move foco entre cabeçalhos |
|
|
175
|
+
| `ng generate semmet-angular:disclosure <nome>` | [Disclosure](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/) | Clique/Enter/Espaço alterna |
|
|
176
|
+
| `ng generate semmet-angular:dialog <nome>` | [Dialog (Modal)](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/) | Foco entra ao abrir; Tab/Shift+Tab prende o foco; Escape fecha; foco volta para o acionador |
|
|
177
|
+
| `ng generate semmet-angular:alert-dialog <nome>` | [Alert Dialog](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/) | Mesmo focus trap do Dialog; foco inicial na ação menos destrutiva (Cancelar) |
|
|
178
|
+
| `ng generate semmet-angular:offcanvas <nome>` | Offcanvas / Drawer | Semântica de dialog modal; foco entra; Tab/Shift+Tab prende o foco; Escape/backdrop fecha; foco volta para o acionador |
|
|
179
|
+
| `ng generate semmet-angular:popover <nome>` | Popover | Acionador disclosure com `aria-haspopup="dialog"`; Escape fecha; clique externo dispensa |
|
|
180
|
+
| `ng generate semmet-angular:tooltip <nome>` | [Tooltip](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/) | Aparece no hover **e** no foco; esconde no blur/mouseleave/Escape |
|
|
181
|
+
| `ng generate semmet-angular:menu-button <nome>` | [Menu Button](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/) | Cima/Baixo/Home/End/Escape dentro do menu; fecha em clique externo; foco volta para o acionador |
|
|
182
|
+
| `ng generate semmet-angular:button <nome>` | Button | `<button>` nativo com variante, tamanho, desabilitado, ocupado, estado pressionado opcional e slots seguros de rótulo/ícone |
|
|
183
|
+
| `ng generate semmet-angular:button-group <nome>` | Button Group | Botões nativos agrupados com `role="group"`, estado toggle opcional com `aria-pressed` e projeção segura de rótulo por item |
|
|
184
|
+
| `ng generate semmet-angular:close-button <nome>` | Close Button | Botão de ícone nativo com rótulo acessível obrigatório |
|
|
185
|
+
|
|
186
|
+
**Navegação e estrutura**
|
|
187
|
+
|
|
188
|
+
| Comando | Gera | Comportamento de teclado/foco implementado |
|
|
189
|
+
|---|---|---|
|
|
190
|
+
| `ng generate semmet-angular:tabs <nome>` | [Tabs](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/) | Ativação automática; Esquerda/Direita/Home/End com `tabindex` roving |
|
|
191
|
+
| `ng generate semmet-angular:breadcrumb <nome>` | [Breadcrumb](https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/) | Estático — links simples + `aria-current="page"` |
|
|
192
|
+
| `ng generate semmet-angular:navigation-menu <nome>` | [Navigation Menu (Disclosure)](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/) | Clique/Enter/Espaço alterna submenu; evita `role="menu"` de propósito, reservado para menus de aplicação |
|
|
193
|
+
| `ng generate semmet-angular:navbar <nome>` | Navbar | Estrutura semântica `nav`/lista/link com toggle responsivo, `aria-current` e slots seguros de marca/ações |
|
|
194
|
+
| `ng generate semmet-angular:pagination <nome>` | Pagination | Estado de página funcional; Anterior/Próximo desabilitam nos limites |
|
|
195
|
+
| `ng generate semmet-angular:skip-link <nome>` | [Skip Link](https://www.w3.org/WAI/WCAG21/Techniques/general/G1) | Escondido até receber foco, conforme o padrão de skip link |
|
|
196
|
+
| `ng generate semmet-angular:landmarks <nome>` | [Landmarks (Page Skeleton)](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/) | Wrapper de layout com projeção de conteúdo (`header`/`nav`/`main`/`aside`/`footer`) |
|
|
197
|
+
| `ng generate semmet-angular:tree-view <nome>` | [Tree View](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/) | Cima/Baixo/Esquerda/Direita/Home/End/Enter com `tabindex` roving nos nós visíveis |
|
|
198
|
+
| `ng generate semmet-angular:toolbar <nome>` | [Toolbar](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/) | Esquerda/Direita/Home/End com `tabindex` roving |
|
|
199
|
+
| `ng generate semmet-angular:card <nome>` | Card | `<article>` semântico com heading/descrição/ações/mídia e slots seguros |
|
|
200
|
+
| `ng generate semmet-angular:list-group <nome>` | List Group | Estrutura semântica de lista com itens de ação, estado ativo, badges opcionais e estados desabilitados |
|
|
201
|
+
| `ng generate semmet-angular:table <nome>` | [Table](https://www.w3.org/WAI/ARIA/apg/patterns/table/) | Caption + cabeçalhos escopados, linhas por input e slots seguros de caption/estado vazio |
|
|
202
|
+
|
|
203
|
+
**Formulários e inputs**
|
|
204
|
+
|
|
205
|
+
| Comando | Gera | Comportamento de teclado/foco implementado |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| `ng generate semmet-angular:form <nome>` | Form | `<form>` nativo com controles rotulados, validação inline e mensagens de status |
|
|
208
|
+
| `ng generate semmet-angular:input <nome>` | Input | `<input>` nativo com label, dica, mensagem de validação e valor com signal |
|
|
209
|
+
| `ng generate semmet-angular:select <nome>` | Select | `<select>` nativo com label, dica, mensagem de validação e valor com signal |
|
|
210
|
+
| `ng generate semmet-angular:input-group <nome>` | Input Group | `<input>` nativo com prefixo/sufixo anunciados por `aria-describedby` e botão de ação opcional |
|
|
211
|
+
| `ng generate semmet-angular:textarea <nome>` | Textarea | `<textarea>` nativo com label, dica, contador, mensagem de validação e valor com signal |
|
|
212
|
+
| `ng generate semmet-angular:checkbox <nome>` | [Checkbox](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/) | Clique/Enter/Espaço alterna |
|
|
213
|
+
| `ng generate semmet-angular:radio-group <nome>` | [Radio Group](https://www.w3.org/WAI/ARIA/apg/patterns/radio/) | Cima/Baixo/Esquerda/Direita/Home/End movem foco e seleção juntos |
|
|
214
|
+
| `ng generate semmet-angular:switch <nome>` | [Switch](https://www.w3.org/WAI/ARIA/apg/patterns/switch/) | `<button>` nativo — Clique/Enter/Espaço alterna |
|
|
215
|
+
| `ng generate semmet-angular:combobox <nome>` | [Combobox](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) | Filtro em tempo real; Cima/Baixo/Home/End/Enter/Escape via `aria-activedescendant` |
|
|
216
|
+
| `ng generate semmet-angular:listbox <nome>` | [Listbox](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/) | Cima/Baixo/Home/End via `aria-activedescendant` |
|
|
217
|
+
| `ng generate semmet-angular:slider <nome>` | [Slider](https://www.w3.org/WAI/ARIA/apg/patterns/slider/) | Setas/PageUp/PageDown/Home/End, além de arraste por ponteiro |
|
|
218
|
+
| `ng generate semmet-angular:spinbutton <nome>` | [Spinbutton](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/) | Cima/Baixo/Home/End, além de botões incrementar/decrementar |
|
|
219
|
+
| `ng generate semmet-angular:meter <nome>` | [Meter](https://www.w3.org/TR/wai-aria-1.2/#meter) | Estático — `<meter>` nativo ligado a um signal |
|
|
220
|
+
| `ng generate semmet-angular:progress-bar <nome>` | [Progress Bar](https://www.w3.org/TR/wai-aria-1.2/#progressbar) | `<progress>` nativo ligado a um signal |
|
|
221
|
+
|
|
222
|
+
**Feedback e mídia**
|
|
223
|
+
|
|
224
|
+
| Comando | Gera | Comportamento de teclado/foco implementado |
|
|
225
|
+
|---|---|---|
|
|
226
|
+
| `ng generate semmet-angular:alert <nome>` | [Alert](https://www.w3.org/WAI/ARIA/apg/patterns/alert/) | Região live assertiva e dispensável |
|
|
227
|
+
| `ng generate semmet-angular:toast <nome>` | Toast / Notification | Auto-dismiss após 5s (limpo via `DestroyRef`); pode ser dispensado antes |
|
|
228
|
+
| `ng generate semmet-angular:skeleton <nome>` | Skeleton Loading | Placeholder de carregamento composível para texto, mídia, círculos, cards e blocos customizados |
|
|
229
|
+
| `ng generate semmet-angular:badge <nome>` | Badge | Rótulo/contador compacto com modo decorativo, rótulo acessível opcional e projeção segura de label |
|
|
230
|
+
| `ng generate semmet-angular:spinner <nome>` | Spinner | Status de carregamento com `role="status"`, rótulo visualmente escondido por padrão e suporte a reduced motion |
|
|
231
|
+
| `ng generate semmet-angular:carousel <nome>` | [Carousel](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/) | Controles Anterior/Próximo; região de slide com `aria-live="polite"` |
|
|
232
|
+
|
|
233
|
+
## Como Cada Componente Gerado É
|
|
234
|
+
|
|
235
|
+
- Standalone (implícito — sem `standalone: true`, alinhado ao padrão atual do Angular).
|
|
236
|
+
- Estado via `signal()`/`computed()`, não campos simples de classe.
|
|
237
|
+
- Templates usam o control flow embutido (`@for`, `@if`), não `*ngFor`/`*ngIf`.
|
|
238
|
+
- Sem sufixo `.component` nos nomes de arquivos ou classes (`accordion.ts`, `export class Accordion`), seguindo a convenção atual de `ng generate component`.
|
|
239
|
+
- Id único por instância (`<nome>-0`, `<nome>-1`, ...) para múltiplas instâncias do mesmo componente nunca colidirem em `id`/`aria-controls`/`aria-labelledby`.
|
|
240
|
+
- Teste unitário (`.spec.ts`) e smoke test e2e Playwright (`.e2e-spec.ts`) gerados para o componente já nascer com uma superfície de teste.
|
|
241
|
+
|
|
242
|
+
## Identidade Visual
|
|
243
|
+
|
|
244
|
+
Todo componente gerado compartilha um visual inspirado em Material Design — superfícies limpas, elevação sutil e escala consistente de raio/movimento — usando sua própria paleta de cores (não as cores do Material, para evitar qualquer risco de cópia visual). Os tokens são CSS custom properties declaradas no `:host` de cada componente (por exemplo, `--semmet-color-primary`, `--semmet-radius-md`, `--semmet-elevation-1`), então você pode usar os defaults como estão ou sobrescrever a família inteira em uma stylesheet global sem tocar nos arquivos gerados.
|
|
245
|
+
|
|
246
|
+
## Opções
|
|
247
|
+
|
|
248
|
+
Todo schematic aceita as mesmas três opções de `ng generate component`:
|
|
249
|
+
|
|
250
|
+
- `name` (obrigatório, posicional) — nome do componente.
|
|
251
|
+
- `project` — projeto alvo; por padrão, usa o projeto atual/default.
|
|
252
|
+
- `path` — diretório alvo; por padrão, usa `src/app` do projeto.
|
|
253
|
+
|
|
254
|
+
## Licença
|
|
255
|
+
|
|
256
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "semmet-angular",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Accessible UI Delivery Kit for Angular: schematics that generate ARIA-conformant standalone components with styling, keyboard behavior, unit tests, and Playwright e2e smoke tests.",
|
|
5
5
|
"publisher": "danilodevsilva",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
},
|
|
26
26
|
"schematics": "./src/collection.json",
|
|
27
27
|
"files": [
|
|
28
|
+
"README.en.md",
|
|
29
|
+
"README.pt-BR.md",
|
|
28
30
|
"src",
|
|
29
31
|
"!src/**/*_spec.ts",
|
|
30
32
|
"!src/**/*_spec.js",
|