@digicreon/mucss 1.0.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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +145 -0
  3. package/dist/mu.amber.css +2 -0
  4. package/dist/mu.azure.css +2 -0
  5. package/dist/mu.blue.css +2 -0
  6. package/dist/mu.css +2 -0
  7. package/dist/mu.cyan.css +2 -0
  8. package/dist/mu.fuchsia.css +2 -0
  9. package/dist/mu.green.css +2 -0
  10. package/dist/mu.grey.css +2 -0
  11. package/dist/mu.indigo.css +2 -0
  12. package/dist/mu.jade.css +2 -0
  13. package/dist/mu.lime.css +2 -0
  14. package/dist/mu.orange.css +2 -0
  15. package/dist/mu.pink.css +2 -0
  16. package/dist/mu.pumpkin.css +2 -0
  17. package/dist/mu.purple.css +2 -0
  18. package/dist/mu.red.css +2 -0
  19. package/dist/mu.sand.css +2 -0
  20. package/dist/mu.slate.css +2 -0
  21. package/dist/mu.violet.css +2 -0
  22. package/dist/mu.yellow.css +2 -0
  23. package/dist/mu.zinc.css +2 -0
  24. package/documentation/mu.accordion.md +119 -0
  25. package/documentation/mu.alert.md +134 -0
  26. package/documentation/mu.badge.md +155 -0
  27. package/documentation/mu.breadcrumb.md +140 -0
  28. package/documentation/mu.button.md +147 -0
  29. package/documentation/mu.card.md +135 -0
  30. package/documentation/mu.checkbox-radio.md +121 -0
  31. package/documentation/mu.dropdown.md +183 -0
  32. package/documentation/mu.forms-advanced.md +164 -0
  33. package/documentation/mu.forms.md +147 -0
  34. package/documentation/mu.grid.md +175 -0
  35. package/documentation/mu.group.md +102 -0
  36. package/documentation/mu.loading.md +99 -0
  37. package/documentation/mu.modal.md +163 -0
  38. package/documentation/mu.pagination.md +196 -0
  39. package/documentation/mu.progress.md +123 -0
  40. package/documentation/mu.range.md +103 -0
  41. package/documentation/mu.spinner.md +102 -0
  42. package/documentation/mu.switch.md +110 -0
  43. package/documentation/mu.table.md +147 -0
  44. package/documentation/mu.tabs.md +164 -0
  45. package/documentation/mu.tooltip.md +98 -0
  46. package/documentation/mu.typography.md +196 -0
  47. package/package.json +31 -0
@@ -0,0 +1,147 @@
1
+ # µForms
2
+
3
+ **µForms** extends PicoCSS form controls with size variants and validation states, part of the [µCSS](.) framework. It applies to `<input>`, `<textarea>`, and `<select>` elements.
4
+
5
+ ---
6
+
7
+ ## Input sizes
8
+
9
+ Two size modifiers adjust padding and font size. Without a size class, the default PicoCSS styling applies.
10
+
11
+ ```html
12
+ <label>Small input
13
+ <input type="text" class="input-sm" placeholder="Small input">
14
+ </label>
15
+ <label>Default input
16
+ <input type="text" placeholder="Default input">
17
+ </label>
18
+ <label>Large input
19
+ <input type="text" class="input-lg" placeholder="Large input">
20
+ </label>
21
+ ```
22
+
23
+ ### Size reference
24
+
25
+ | Class | Padding | Font size | Applies to |
26
+ |-------------|--------------------------|---------------|----------------------------------|
27
+ | `.input-sm` | `0.375rem 0.625rem` | `0.8125rem` | `input`, `textarea`, `select` |
28
+ | *(default)* | *(PicoCSS default)* | *(default)* | `input`, `textarea`, `select` |
29
+ | `.input-lg` | `0.75rem 1rem` | `1.125rem` | `input`, `textarea`, `select` |
30
+
31
+ ### Textarea sizes
32
+
33
+ ```html
34
+ <label>Small textarea
35
+ <textarea class="input-sm" placeholder="Small textarea"></textarea>
36
+ </label>
37
+ <label>Large textarea
38
+ <textarea class="input-lg" placeholder="Large textarea"></textarea>
39
+ </label>
40
+ ```
41
+
42
+ ### Select sizes
43
+
44
+ ```html
45
+ <label>Small select
46
+ <select class="input-sm">
47
+ <option>Option 1</option>
48
+ <option>Option 2</option>
49
+ </select>
50
+ </label>
51
+ <label>Large select
52
+ <select class="input-lg">
53
+ <option>Option 1</option>
54
+ <option>Option 2</option>
55
+ </select>
56
+ </label>
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Validation states
62
+
63
+ µForms provides two validation classes that set border color and focus ring color. For error states, use the native `aria-invalid="true"` attribute (handled by PicoCSS).
64
+
65
+ ```html
66
+ <label>Success
67
+ <input type="text" class="input-success" value="Valid value">
68
+ </label>
69
+ <label>Warning
70
+ <input type="text" class="input-warning" value="Needs attention">
71
+ </label>
72
+ <label>Error (native)
73
+ <input type="text" aria-invalid="true" value="Invalid value">
74
+ </label>
75
+ ```
76
+
77
+ ### Validation reference
78
+
79
+ | Class / Attribute | Border color | Focus ring color |
80
+ |--------------------------|-----------------------|---------------------------|
81
+ | `.input-success` | `--pico-success` | `--pico-success-focus` |
82
+ | `.input-warning` | `--pico-warning` | `--pico-warning-focus` |
83
+ | `aria-invalid="true"` | *(PicoCSS built-in)* | *(PicoCSS built-in)* |
84
+
85
+ ### Validation on textarea
86
+
87
+ ```html
88
+ <label>Success textarea
89
+ <textarea class="input-success">This content is valid.</textarea>
90
+ </label>
91
+ <label>Warning textarea
92
+ <textarea class="input-warning">This content needs review.</textarea>
93
+ </label>
94
+ ```
95
+
96
+ ### Validation on select
97
+
98
+ ```html
99
+ <label>Success select
100
+ <select class="input-success">
101
+ <option>Valid choice</option>
102
+ </select>
103
+ </label>
104
+ <label>Warning select
105
+ <select class="input-warning">
106
+ <option>Needs review</option>
107
+ </select>
108
+ </label>
109
+ ```
110
+
111
+ ---
112
+
113
+ ## Combining size and validation
114
+
115
+ Size and validation classes can be used together on the same element:
116
+
117
+ ```html
118
+ <label>Small + success
119
+ <input type="text" class="input-sm input-success" value="Small valid">
120
+ </label>
121
+ <label>Large + warning
122
+ <input type="text" class="input-lg input-warning" value="Large needs attention">
123
+ </label>
124
+ ```
125
+
126
+ ---
127
+
128
+ ## CSS classes reference
129
+
130
+ | Class | Type | Description |
131
+ |-------------------|------------|------------------------------------------------------|
132
+ | `.input-sm` | Size | Smaller padding and font size |
133
+ | `.input-lg` | Size | Larger padding and font size |
134
+ | `.input-success` | Validation | Green border, green focus ring |
135
+ | `.input-warning` | Validation | Orange/yellow border, orange/yellow focus ring |
136
+
137
+ ---
138
+
139
+ ## Accessibility
140
+
141
+ - Use `aria-invalid="true"` for error states (PicoCSS native support).
142
+ - Always wrap form controls inside `<label>` elements for proper association.
143
+ - Validation colors supplement, but do not replace, text-based error messages.
144
+
145
+ ---
146
+
147
+ → [Voir l'exemple](../examples/forms.html)
@@ -0,0 +1,175 @@
1
+ # µGrid
2
+
3
+ **µGrid** is a lightweight flexbox-based 12-column responsive grid system, part of the [µCSS](.) framework. It provides a Bootstrap-compatible grid fallback for CSS frameworks that lack a built-in responsive grid (such as PicoCSS).
4
+
5
+ **Weight:** ~4 KB uncompressed, ~1 KB gzipped.
6
+
7
+ ---
8
+
9
+ ## Breakpoints
10
+
11
+ µGrid uses a mobile-first approach with 4 breakpoints:
12
+
13
+ | Name | Prefix | Min-width | Typical use |
14
+ |------|--------|-----------|----------------------|
15
+ | — | *(none)* | 0 | Mobile (default) |
16
+ | sm | `-sm-` | 640px | Mobile landscape |
17
+ | md | `-md-` | 960px | Tablet |
18
+ | lg | `-lg-` | 1200px | Desktop |
19
+ | xl | `-xl-` | 1400px | Large desktop |
20
+
21
+ All classes without a breakpoint prefix apply to all screen sizes. Prefixed classes apply from the specified breakpoint and up.
22
+
23
+ ---
24
+
25
+ ## Container
26
+
27
+ Containers center and constrain content horizontally.
28
+
29
+ ```html
30
+ <!-- Fixed-width container (max-width: 1200px) -->
31
+ <div class="container">...</div>
32
+
33
+ <!-- Full-width container -->
34
+ <div class="container-fluid">...</div>
35
+ ```
36
+
37
+ Both containers have `1rem` horizontal padding.
38
+
39
+ ---
40
+
41
+ ## Row
42
+
43
+ A `.row` creates a flex container for columns. It uses negative margins to compensate for column gutters.
44
+
45
+ ```html
46
+ <div class="container">
47
+ <div class="row">
48
+ <div class="col-6">Half</div>
49
+ <div class="col-6">Half</div>
50
+ </div>
51
+ </div>
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Columns
57
+
58
+ Columns are defined using `.col-{n}` and `.col-{bp}-{n}` classes, where `{n}` is a number from 1 to 12.
59
+
60
+ Each column has a `0.75rem` padding on each side (1.5rem gutter between columns).
61
+
62
+ ### Basic usage
63
+
64
+ ```html
65
+ <div class="row">
66
+ <div class="col-12">Full width</div>
67
+ </div>
68
+
69
+ <div class="row">
70
+ <div class="col-4">One third</div>
71
+ <div class="col-8">Two thirds</div>
72
+ </div>
73
+ ```
74
+
75
+ ### Responsive columns
76
+
77
+ ```html
78
+ <div class="row">
79
+ <!-- Full width on mobile, half on tablet, one third on desktop -->
80
+ <div class="col-12 col-md-6 col-lg-4">Content</div>
81
+ <div class="col-12 col-md-6 col-lg-4">Content</div>
82
+ <div class="col-12 col-md-12 col-lg-4">Content</div>
83
+ </div>
84
+ ```
85
+
86
+ ### Column reference
87
+
88
+ | Class pattern | Width |
89
+ |------------------|------------|
90
+ | `.col-{bp}-1` | 8.3333% |
91
+ | `.col-{bp}-2` | 16.6667% |
92
+ | `.col-{bp}-3` | 25% |
93
+ | `.col-{bp}-4` | 33.3333% |
94
+ | `.col-{bp}-5` | 41.6667% |
95
+ | `.col-{bp}-6` | 50% |
96
+ | `.col-{bp}-7` | 58.3333% |
97
+ | `.col-{bp}-8` | 66.6667% |
98
+ | `.col-{bp}-9` | 75% |
99
+ | `.col-{bp}-10` | 83.3333% |
100
+ | `.col-{bp}-11` | 91.6667% |
101
+ | `.col-{bp}-12` | 100% |
102
+
103
+ ---
104
+
105
+ ## Offsets
106
+
107
+ Offsets push a column to the right by a given number of columns using `margin-left`.
108
+
109
+ ```html
110
+ <div class="row">
111
+ <div class="col-6 offset-3">Centered content</div>
112
+ </div>
113
+ ```
114
+
115
+ ### Responsive offsets
116
+
117
+ ```html
118
+ <div class="row">
119
+ <div class="col-12 col-md-8 col-lg-4 offset-md-2 offset-lg-4">Content</div>
120
+ </div>
121
+ ```
122
+
123
+ Use `.offset-{bp}-0` to reset an offset at a given breakpoint.
124
+
125
+ ---
126
+
127
+ ## Ordering
128
+
129
+ Change the visual order of columns without changing the HTML source order.
130
+
131
+ ```html
132
+ <div class="row">
133
+ <div class="col-6 order-2">Appears second</div>
134
+ <div class="col-6 order-1">Appears first</div>
135
+ </div>
136
+ ```
137
+
138
+ ### Special values
139
+
140
+ | Class | Effect |
141
+ |------------------------|--------------|
142
+ | `.order-{bp}-first` | `order: -1` |
143
+ | `.order-{bp}-last` | `order: 13` |
144
+ | `.order-{bp}-0` to `.order-{bp}-12` | `order: 0` to `order: 12` |
145
+
146
+ ---
147
+
148
+ ## Display / Visibility
149
+
150
+ | Class | Effect |
151
+ |-------------------|---------------------|
152
+ | `.d-{bp}-none` | `display: none` |
153
+ | `.d-{bp}-block` | `display: block` |
154
+ | `.d-{bp}-flex` | `display: flex` |
155
+
156
+ When showing a `.row` that was previously hidden, use `d-{bp}-flex` instead of `d-{bp}-block` to preserve the flex layout.
157
+
158
+ ```html
159
+ <div class="row d-none d-md-flex">
160
+ <div class="col-md-6">A</div>
161
+ <div class="col-md-6">B</div>
162
+ </div>
163
+ ```
164
+
165
+ ---
166
+
167
+ ## Bootstrap compatibility
168
+
169
+ µGrid uses the same class naming conventions as Bootstrap 5. Main differences:
170
+
171
+ - **4 breakpoints** instead of 5: Bootstrap's `xl` and `xxl` are merged into `xl`.
172
+ - **Breakpoint values differ slightly**: `sm` is 640px (vs 576px), `md` is 960px (vs 768px).
173
+ - **No auto-sizing columns**: `.col` (without a number) is not supported.
174
+ - **No `row-cols-*`**: automatic column count per row is not supported.
175
+ - **No flex alignment utilities**: `justify-content-*`, `align-items-*` are not included.
@@ -0,0 +1,102 @@
1
+ # µGroup
2
+
3
+ **µGroup** permet de regrouper visuellement des champs de formulaire et des boutons en une seule ligne, grace a l'attribut `role="group"` style par [PicoCSS](https://picocss.com) au sein du framework [µCSS](.). Les elements groupes partagent des bordures communes et s'alignent horizontalement.
4
+
5
+ ---
6
+
7
+ ## Groupe de boutons
8
+
9
+ L'attribut `role="group"` sur un conteneur regroupe les boutons en une barre horizontale avec des bordures fusionnees.
10
+
11
+ ```html
12
+ <div role="group">
13
+ <button>Left</button>
14
+ <button>Center</button>
15
+ <button>Right</button>
16
+ </div>
17
+ ```
18
+
19
+ ---
20
+
21
+ ## Input + bouton
22
+
23
+ Combinez un champ de saisie et un bouton dans un meme groupe pour creer un formulaire inline compact.
24
+
25
+ ```html
26
+ <div role="group">
27
+ <input type="email" placeholder="Enter your email">
28
+ <button>Subscribe</button>
29
+ </div>
30
+ ```
31
+
32
+ ---
33
+
34
+ ## Groupe de recherche
35
+
36
+ Utilisez `role="search"` pour un groupe semantiquement identifie comme zone de recherche. Le rendu visuel est identique a `role="group"`.
37
+
38
+ ```html
39
+ <div role="search">
40
+ <input type="search" placeholder="Search...">
41
+ <button>Search</button>
42
+ </div>
43
+ ```
44
+
45
+ ---
46
+
47
+ ## Input + select + bouton
48
+
49
+ Un groupe peut contenir plus de deux elements, par exemple un `<select>`, un `<input>` et un `<button>`.
50
+
51
+ ```html
52
+ <div role="group">
53
+ <select>
54
+ <option>USD</option>
55
+ <option>EUR</option>
56
+ <option>GBP</option>
57
+ </select>
58
+ <input type="number" placeholder="Amount">
59
+ <button>Convert</button>
60
+ </div>
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Boutons outline
66
+
67
+ Les boutons `.outline` fonctionnent egalement dans un groupe, offrant un style de barre de selection (toggle bar).
68
+
69
+ ```html
70
+ <div role="group">
71
+ <button class="outline">Day</button>
72
+ <button class="outline">Week</button>
73
+ <button class="outline">Month</button>
74
+ </div>
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Resume des roles
80
+
81
+ | Attribut | Usage |
82
+ |----------|-------|
83
+ | `role="group"` | Groupe generique (boutons, inputs, selects) |
84
+ | `role="search"` | Groupe de recherche (semantique) |
85
+
86
+ ## Elements supportes dans un groupe
87
+
88
+ | Element | Comportement |
89
+ |---------|-------------|
90
+ | `<button>` | Bouton d'action |
91
+ | `<input>` | Champ de saisie (text, email, search, number, etc.) |
92
+ | `<select>` | Liste de selection |
93
+
94
+ ---
95
+
96
+ ## Accessibilite
97
+
98
+ - `role="group"` informe les technologies d'assistance que les elements sont lies et forment un ensemble logique.
99
+ - `role="search"` identifie semantiquement la zone comme fonctionnalite de recherche, ce qui aide la navigation au lecteur d'ecran.
100
+ - Les elements du groupe restent accessibles individuellement au clavier (navigation par `Tab`).
101
+
102
+ → [Voir l'exemple](../examples/group.html)
@@ -0,0 +1,99 @@
1
+ # µLoading
2
+
3
+ **µLoading** describes the loading indicator states available natively in [µCSS](.) via PicoCSS. Loading states are activated using the standard `aria-busy="true"` attribute on any element, which displays an animated spinner without requiring any additional CSS class or JavaScript library.
4
+
5
+ ---
6
+
7
+ ## Usage
8
+
9
+ Add `aria-busy="true"` to any HTML element to show a loading spinner. The spinner is rendered via CSS and adapts to the element's context (inline for buttons and paragraphs, block-level for containers).
10
+
11
+ ```html
12
+ <button aria-busy="true">Please wait...</button>
13
+ ```
14
+
15
+ Remove the loading state by setting `aria-busy="false"` or removing the attribute entirely.
16
+
17
+ ---
18
+
19
+ ## Button loading
20
+
21
+ Apply `aria-busy="true"` on `<button>` elements to show a spinner alongside the button text. This works with all button variants.
22
+
23
+ ```html
24
+ <button aria-busy="true">Please wait...</button>
25
+ <button aria-busy="true" class="secondary">Loading</button>
26
+ <button aria-busy="true" class="contrast">Processing</button>
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Standalone spinner
32
+
33
+ Use an empty `<div>` with `aria-busy="true"` to display a standalone centered spinner. Set a `min-height` so the spinner has space to render.
34
+
35
+ ```html
36
+ <div aria-busy="true" style="min-height: 3rem;"></div>
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Loading on a card
42
+
43
+ Apply `aria-busy="true"` on an `<article>` to indicate the entire card is in a loading state.
44
+
45
+ ```html
46
+ <article aria-busy="true">
47
+ <p>This card is loading...</p>
48
+ </article>
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Loading paragraph
54
+
55
+ Apply `aria-busy="true"` directly on a `<p>` element to show a spinner inline with text content.
56
+
57
+ ```html
58
+ <p aria-busy="true">Loading content...</p>
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Toggle loading dynamically
64
+
65
+ Use JavaScript to toggle the `aria-busy` attribute on any element to control the loading state at runtime.
66
+
67
+ ```html
68
+ <button onclick="var t = document.getElementById('target'); t.ariaBusy = t.ariaBusy === 'true' ? 'false' : 'true';">
69
+ Toggle loading state
70
+ </button>
71
+ <article id="target" aria-busy="false">
72
+ <p>Click the button above to toggle the loading state on this card.</p>
73
+ </article>
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Supported elements
79
+
80
+ | Element | Behavior |
81
+ |---------------|-----------------------------------------------|
82
+ | `<button>` | Spinner displayed inline before the text |
83
+ | `<div>` | Centered block-level spinner |
84
+ | `<article>` | Spinner overlays the card content |
85
+ | `<p>` | Spinner displayed inline with text |
86
+
87
+ Any element that accepts `aria-busy` can display the loading indicator.
88
+
89
+ ---
90
+
91
+ ## Accessibility
92
+
93
+ - `aria-busy="true"` is a standard WAI-ARIA attribute. Screen readers will announce the element as busy/loading.
94
+ - Always provide descriptive text content (e.g., "Please wait...") alongside the spinner for assistive technologies.
95
+ - Set `aria-busy="false"` when loading completes to notify screen readers that content is ready.
96
+
97
+ ---
98
+
99
+ → [Voir l'exemple](../examples/loading.html)
@@ -0,0 +1,163 @@
1
+ # µModal
2
+
3
+ **µModal** provides size variants and a close button for native `<dialog>` modals, part of the [µCSS](.) framework. It builds on PicoCSS's dialog styling with small, large, and fullscreen options.
4
+
5
+ ---
6
+
7
+ ## Usage
8
+
9
+ Modals use the native HTML `<dialog>` element containing an `<article>`. Open with JavaScript's `.showModal()` method and close with `.close()`.
10
+
11
+ ```html
12
+ <dialog id="my-modal">
13
+ <article>
14
+ <button class="modal-close" aria-label="Close"
15
+ onclick="document.getElementById('my-modal').close()">&times;</button>
16
+ <h3>Modal title</h3>
17
+ <p>Modal content goes here.</p>
18
+ <footer>
19
+ <button class="btn btn-primary"
20
+ onclick="document.getElementById('my-modal').close()">Close</button>
21
+ </footer>
22
+ </article>
23
+ </dialog>
24
+
25
+ <!-- Trigger button -->
26
+ <button onclick="document.getElementById('my-modal').showModal()">Open modal</button>
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Size variants
32
+
33
+ 4 sizes are available. Without a size class, the default PicoCSS dialog width applies.
34
+
35
+ | Class | Max-width | Description |
36
+ |---------------------|--------------|--------------------------------------|
37
+ | `.modal-sm` | 400px | Confirmations and simple prompts |
38
+ | *(default)* | *(PicoCSS)* | Suitable for most content |
39
+ | `.modal-lg` | 900px | Forms or detailed content |
40
+ | `.modal-fullscreen` | 100vw | Full viewport, no border-radius |
41
+
42
+ Size classes are applied on the `<dialog>` element, not on the inner `<article>`.
43
+
44
+ ### Small modal
45
+
46
+ ```html
47
+ <dialog id="modal-sm" class="modal-sm">
48
+ <article>
49
+ <button class="modal-close" aria-label="Close"
50
+ onclick="document.getElementById('modal-sm').close()">&times;</button>
51
+ <h3>Small modal</h3>
52
+ <p>This is a small modal (max-width: 400px). Ideal for confirmations and simple prompts.</p>
53
+ <footer>
54
+ <button class="btn btn-ghost btn-secondary"
55
+ onclick="document.getElementById('modal-sm').close()">Cancel</button>
56
+ <button class="btn btn-primary"
57
+ onclick="document.getElementById('modal-sm').close()">Confirm</button>
58
+ </footer>
59
+ </article>
60
+ </dialog>
61
+ ```
62
+
63
+ ### Large modal
64
+
65
+ ```html
66
+ <dialog id="modal-lg" class="modal-lg">
67
+ <article>
68
+ <button class="modal-close" aria-label="Close"
69
+ onclick="document.getElementById('modal-lg').close()">&times;</button>
70
+ <h3>Large modal</h3>
71
+ <p>This is a large modal (max-width: 900px). Useful for forms or detailed content.</p>
72
+ <div class="row">
73
+ <div class="col-6">
74
+ <label>First name <input type="text" placeholder="First name"></label>
75
+ </div>
76
+ <div class="col-6">
77
+ <label>Last name <input type="text" placeholder="Last name"></label>
78
+ </div>
79
+ </div>
80
+ <label>Email <input type="email" placeholder="Email address"></label>
81
+ <footer>
82
+ <button class="btn btn-ghost btn-secondary"
83
+ onclick="document.getElementById('modal-lg').close()">Cancel</button>
84
+ <button class="btn btn-success"
85
+ onclick="document.getElementById('modal-lg').close()">Save</button>
86
+ </footer>
87
+ </article>
88
+ </dialog>
89
+ ```
90
+
91
+ ### Fullscreen modal
92
+
93
+ ```html
94
+ <dialog id="modal-fullscreen" class="modal-fullscreen">
95
+ <article>
96
+ <button class="modal-close" aria-label="Close"
97
+ onclick="document.getElementById('modal-fullscreen').close()">&times;</button>
98
+ <h3>Fullscreen modal</h3>
99
+ <p>This modal covers the entire viewport. Suitable for immersive experiences,
100
+ image galleries, or complex workflows.</p>
101
+ <footer>
102
+ <button class="btn btn-error"
103
+ onclick="document.getElementById('modal-fullscreen').close()">Close</button>
104
+ </footer>
105
+ </article>
106
+ </dialog>
107
+ ```
108
+
109
+ The fullscreen variant sets `width: 100vw`, `min-height: 100vh`, `border-radius: 0`, and `margin: 0` on the inner `<article>`.
110
+
111
+ ---
112
+
113
+ ## Close button
114
+
115
+ The `.modal-close` class styles a close button positioned absolutely in the top-right corner of the `<article>`.
116
+
117
+ ```html
118
+ <button class="modal-close" aria-label="Close"
119
+ onclick="document.getElementById('my-modal').close()">&times;</button>
120
+ ```
121
+
122
+ | Property | Value |
123
+ |-------------------|---------------------------------|
124
+ | Position | Absolute, top-right corner |
125
+ | Size | 3rem x 3rem |
126
+ | Background | Transparent |
127
+ | Color | `--pico-secondary` |
128
+ | Opacity | 0.6 (1 on hover) |
129
+ | Focus indicator | 2px solid outline, 0.25rem radius |
130
+
131
+ ---
132
+
133
+ ## CSS classes reference
134
+
135
+ | Class | Applied to | Description |
136
+ |---------------------|--------------|-------------------------------------------|
137
+ | `.modal-sm` | `<dialog>` | Small modal (max-width: 400px) |
138
+ | `.modal-lg` | `<dialog>` | Large modal (max-width: 900px) |
139
+ | `.modal-fullscreen` | `<dialog>` | Full viewport modal |
140
+ | `.modal-close` | `<button>` | Positioned close button (top-right) |
141
+
142
+ ---
143
+
144
+ ## Opening and closing
145
+
146
+ Modals rely on the native `<dialog>` API. No JavaScript is bundled with µCSS -- behavior is the application's responsibility.
147
+
148
+ - **Open**: `document.getElementById('modal-id').showModal()`
149
+ - **Close**: `document.getElementById('modal-id').close()`
150
+ - **Backdrop click**: handled natively by `<dialog>` when opened via `.showModal()`
151
+ - **Escape key**: closes the dialog natively
152
+
153
+ ---
154
+
155
+ ## Accessibility
156
+
157
+ - Always include `aria-label="Close"` on the `.modal-close` button.
158
+ - The `.modal-close` button has a `:focus-visible` outline for keyboard navigation.
159
+ - Use `.showModal()` (not `.show()`) to get the modal backdrop and trap focus inside the dialog.
160
+
161
+ ---
162
+
163
+ → [Voir l'exemple](../examples/modal.html)