material-inspired-component-library 3.1.0 → 4.0.1

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 (92) hide show
  1. package/README.md +12 -5
  2. package/components/README.md +1 -1
  3. package/components/accordion/README.md +29 -5
  4. package/components/alert/README.md +76 -0
  5. package/components/alert/index.scss +1 -0
  6. package/components/appbar/README.md +9 -4
  7. package/components/appbar/index.scss +1 -1
  8. package/components/badge/README.md +8 -3
  9. package/components/badge/index.scss +1 -0
  10. package/components/bottomsheet/README.md +8 -3
  11. package/components/button/README.md +8 -3
  12. package/components/button/index.scss +7 -0
  13. package/components/card/README.md +10 -4
  14. package/components/card/index.scss +1 -1
  15. package/components/checkbox/README.md +8 -3
  16. package/components/checkbox/index.scss +2 -0
  17. package/components/dialog/README.md +8 -3
  18. package/components/dialog/index.scss +1 -0
  19. package/components/divider/README.md +8 -3
  20. package/components/divider/index.scss +2 -2
  21. package/components/iconbutton/README.md +8 -3
  22. package/components/iconbutton/index.scss +3 -1
  23. package/components/list/README.md +26 -19
  24. package/components/list/index.scss +95 -68
  25. package/components/menu/README.md +9 -3
  26. package/components/menu/index.scss +6 -18
  27. package/components/navigationrail/README.md +8 -3
  28. package/components/navigationrail/index.scss +1 -0
  29. package/components/radio/README.md +8 -3
  30. package/components/radio/index.scss +2 -0
  31. package/components/select/README.md +10 -5
  32. package/components/select/index.scss +2 -3
  33. package/components/sidesheet/README.md +21 -22
  34. package/components/sidesheet/index.scss +15 -16
  35. package/components/slider/README.md +8 -3
  36. package/components/slider/index.scss +1 -0
  37. package/components/stepper/README.md +190 -0
  38. package/components/stepper/index.scss +93 -14
  39. package/components/stepper/index.ts +138 -120
  40. package/components/switch/README.md +8 -3
  41. package/components/switch/index.scss +2 -0
  42. package/components/textfield/README.md +8 -3
  43. package/components/textfield/index.ts +8 -40
  44. package/dist/alert.css +1 -1
  45. package/dist/badge.css +1 -1
  46. package/dist/button.css +1 -1
  47. package/dist/card.css +1 -1
  48. package/dist/checkbox.css +1 -1
  49. package/dist/components/textfield/index.d.ts +0 -1
  50. package/dist/dialog.css +1 -1
  51. package/dist/divider.css +1 -1
  52. package/dist/foundations/form/index.d.ts +5 -0
  53. package/dist/iconbutton.css +1 -1
  54. package/dist/list.css +1 -1
  55. package/dist/menu.css +1 -1
  56. package/dist/micl.css +1 -1
  57. package/dist/micl.js +1 -1
  58. package/dist/navigationrail.css +1 -1
  59. package/dist/radio.css +1 -1
  60. package/dist/select.css +1 -1
  61. package/dist/sidesheet.css +1 -1
  62. package/dist/slider.css +1 -1
  63. package/dist/stepper.css +1 -1
  64. package/dist/switch.css +1 -1
  65. package/docs/accordion.html +31 -17
  66. package/docs/alert.html +3 -8
  67. package/docs/bottomsheet.html +2 -2
  68. package/docs/button.html +2 -2
  69. package/docs/card.html +7 -7
  70. package/docs/checkbox.html +2 -2
  71. package/docs/dialog.html +2 -2
  72. package/docs/divider.html +8 -8
  73. package/docs/iconbutton.html +2 -2
  74. package/docs/index.html +53 -39
  75. package/docs/list.html +54 -46
  76. package/docs/menu.html +4 -3
  77. package/docs/micl.css +1 -1
  78. package/docs/micl.js +1 -1
  79. package/docs/radio.html +2 -2
  80. package/docs/select.html +2 -2
  81. package/docs/sidesheet.html +5 -4
  82. package/docs/slider.html +2 -2
  83. package/docs/stepper.html +318 -0
  84. package/docs/switch.html +8 -4
  85. package/docs/textfield.html +2 -2
  86. package/foundations/form/index.ts +174 -0
  87. package/{layout → foundations/layout}/README.md +5 -0
  88. package/{layout → foundations/layout}/index.scss +1 -1
  89. package/micl.ts +1 -3
  90. package/package.json +4 -4
  91. package/styles.scss +1 -1
  92. package/webpack.config.js +1 -1
@@ -1,5 +1,5 @@
1
1
  # Select
2
- This component implements the the [Material Design 3 Expressive Select](https://m3.material.io/components/menus/guidelines#ee2f3664-c926-47ab-acbf-2ab675506932) design. A select component is used to offer the user with a set of options from which the user can select a single one.
2
+ This component implements the [Material Design 3 Expressive Select](https://m3.material.io/components/menus/guidelines#ee2f3664-c926-47ab-acbf-2ab675506932) design. A select component is used to offer the user with a set of options from which the user can select a single one.
3
3
 
4
4
  ## Basic Usage
5
5
 
@@ -29,6 +29,11 @@ The Select component relies on styles from the text field and list components. B
29
29
  @use "material-inspired-component-library/dist/select";
30
30
  ```
31
31
 
32
+ Or import all MICL styles:
33
+ ```CSS
34
+ @use "material-inspired-component-library/styles";
35
+ ```
36
+
32
37
  ### JavaScript
33
38
  This component requires JavaScript for functionality:
34
39
 
@@ -38,11 +43,11 @@ import micl from "material-inspired-component-library/dist/micl";
38
43
 
39
44
  This will initialize any Select component, including those that will be added to the DOM later on.
40
45
 
41
- ### Demo
42
- A live example of the [Select component](https://henkpb.github.io/micl/select.html) is available for you to interact with.
46
+ ### Live Demo
47
+ A live example of the [Select component](https://henkpb.github.io/micl/select.html) is available to interact with.
43
48
 
44
49
  ## Variants
45
- A Select Component can be disabled by adding the `disabled` attribute to the `<select>` element. An option within the component can be disabled by adding the `disabled` attribute to the `<option>` element.
50
+ A Select component can be disabled by adding the `disabled` attribute to the `<select>` element. An option within the component can be disabled by adding the `disabled` attribute to the `<option>` element.
46
51
 
47
52
  You can add [Dividers](../divider/README.md) into the list of options and they will appear as separators to help visually break up the options.
48
53
 
@@ -52,7 +57,7 @@ You can add [Dividers](../divider/README.md) into the list of options and they w
52
57
  <div class="micl-textfield-outlined">
53
58
  <label for="myselect">Country</label>
54
59
  <select id="myselect">
55
- <option class="micl-list-item-two" value=""></option>
60
+ <option class="micl-list-item-two" value="" label="(none)"></option>
56
61
  <option class="micl-list-item-two" value="AR">
57
62
  <span class="micl-list-item__text">Argentina</span>
58
63
  </option>
@@ -56,9 +56,9 @@
56
56
  min-inline-size: max(anchor-size(self-inline), 112px);
57
57
  max-inline-size: 280px;
58
58
  position-try: most-block-size flip-block;
59
- padding: 8px 0;
59
+ padding: var(--md-sys-list-padding, 8px) 0;
60
60
  border: none;
61
- border-radius: var(--md-sys-shape-corner-extra-small);
61
+ border-radius: var(--md-sys-shape-corner-extra-small, 4px);
62
62
  background-color: var(--md-sys-color-surface-container);
63
63
  box-shadow: var(--md-sys-elevation-level2);
64
64
  opacity: 0;
@@ -94,7 +94,6 @@
94
94
  --md-sys-list-item-one-padding: 0;
95
95
  --md-sys-list-item-two-padding: 0;
96
96
  --md-sys-list-item-space: 12px;
97
- --md-sys-list-item-padding-inline: 16px;
98
97
  --md-sys-list-item-container-color: var(--md-sys-color-surface-container);
99
98
 
100
99
  line-height: normal;
@@ -1,5 +1,5 @@
1
1
  # Side sheet
2
- This component implements the the [Material Design 3 Expressive Side sheet](https://m3.material.io/components/side-sheets/overview) design. Side sheets provide optional content and actions without interrupting the main content.
2
+ This component implements the [Material Design 3 Expressive Side sheet](https://m3.material.io/components/side-sheets/overview) design. Side sheets provide optional content and actions without interrupting the main content.
3
3
 
4
4
  ## Basic Usage
5
5
 
@@ -29,16 +29,21 @@ Import the side sheet styles into your project:
29
29
  @use "material-inspired-component-library/dist/sidesheet";
30
30
  ```
31
31
 
32
+ Or import all MICL styles:
33
+ ```CSS
34
+ @use "material-inspired-component-library/styles";
35
+ ```
36
+
32
37
  ### JavaScript
33
38
  No custom JavaScript is required for the core functionality of the side sheet component.
34
39
 
35
- ### Demo
36
- A live example of the [Side sheet component](https://henkpb.github.io/micl/sidesheet.html) is available for you to interact with.
40
+ ### Live Demo
41
+ A live example of the [Side sheet component](https://henkpb.github.io/micl/sidesheet.html) is available to interact with.
37
42
 
38
43
  ## Variants
39
44
  A **modal** side sheet blocks access to the rest of the page and must be dismissed explicitly by the user. This is suitable for critical tasks or information that requires a user's full attention.
40
45
 
41
- To create a modal side sheet, use the `<dialog>` element without the `popover` attribute. Use `closedby="closerequest"` to prevent the side sheet from being dismissed by clicking outside of it. You'll also need a button or other control with popovertarget to close it.
46
+ To create a modal side sheet, use the `<dialog>` element without the `popover` attribute. Use `closedby="closerequest"` to prevent the side sheet from being dismissed by clicking outside of it. You'll also need a button or other control with `popovertarget` to close it.
42
47
 
43
48
  ```HTML
44
49
  <dialog id="mysidesheet" class="micl-sidesheet" closedby="closerequest" aria-labelledby="mytitle">
@@ -57,39 +62,33 @@ To create a modal side sheet, use the `<dialog>` element without the `popover` a
57
62
  <div class="micl-sidesheet__content">
58
63
  ...your content...
59
64
  </div>
65
+ <hr class="micl-divider">
60
66
  <div class="micl-sidesheet__actions">
61
67
  <button type="button" class="micl-button-filled-s">Save</button>
62
68
  </div>
63
69
  </dialog>
64
70
  ```
65
71
 
66
- To open either a standard or modal side sheet, link a button to the side sheet's ID using the `popovertarget` attribute:
72
+ To open a standard or modal side sheet, link a button to the side sheet's ID using the `popovertarget` attribute:
67
73
  ```HTML
68
74
  <button type="button" popovertarget="mysidesheet">Open Side Sheet</button>
69
75
  ```
70
76
 
71
- The back-button and the actions-container are optional. To remove the vertical divider of the "standard" side sheet, assign zero to the following CSS variable:
77
+ The back-button and the actions-container are optional. To remove the vertical divider of the standard side sheet, assign zero to the following CSS variable:
72
78
  ```CSS
73
79
  #mysidesheet {
74
80
  --md-sys-divider-thickness: 0;
75
81
  }
76
82
  ```
77
- To remove the horizontal divider of the actions-container:
78
- ```CSS
79
- #mysidesheet .micl-sidesheet__actions {
80
- --md-sys-divider-thickness: 0;
81
- }
82
- ```
83
-
84
- ### Warning
85
- The **standard** side sheet component adds CSS rules to the `<body>` element to properly resize the main content area when the side sheet is open. Overriding these rules may cause the component to behave unexpectedly. The rules that are applied are:
86
83
 
87
- ```CSS
88
- box-sizing: border-box;
89
- margin: 0;
90
- max-inline-size: ...varies depending on if the side sheet is opened...
91
- transition: ...transition on max-inline-size...
92
- ```
84
+ > [!WARNING]
85
+ > The **standard** side sheet component adds CSS rules to the `<body>` element to properly resize the main content area when the side sheet is open. Overriding these rules may cause the component to behave unexpectedly. The rules that are applied are:
86
+ > ```CSS
87
+ > box-sizing: border-box;
88
+ > margin: 0;
89
+ > max-inline-size: ...varies depending on if the side sheet is opened...
90
+ > transition: ...transition on max-inline-size...
91
+ > ```
93
92
 
94
93
  ## Customizations
95
94
  You can customize the appearance of the Side sheet component by overriding its global CSS variables. These variables are declared on the `:root` pseudo-class and can be changed on any appropriate parent element to affect its child side sheets.
@@ -97,7 +96,7 @@ You can customize the appearance of the Side sheet component by overriding its g
97
96
  | Variable name | Default Value | Description |
98
97
  | ------------- | ------------- | ----------- |
99
98
  | --md-sys-sidesheet-width | 256px | The default (and minimum allowed) width of the side sheet |
100
- | --md-sys-sidesheet-maxwidth | 400px | The largest allowed width of tthe side sheet |
99
+ | --md-sys-sidesheet-maxwidth | 400px | The largest allowed width of the side sheet |
101
100
  | --md-sys-sidesheet-padding-standard | 24px | The amount of space between the vertical edges and the content |
102
101
 
103
102
  **Example: Changing the width of the sidesheet**
@@ -27,14 +27,17 @@
27
27
  :root {
28
28
  --md-sys-sidesheet-width: 256px;
29
29
  --md-sys-sidesheet-maxwidth: 400px;
30
- --md-sys-sidesheet-spring-buffer: 200px;
31
- --md-sys-sidesheet-padding-standard: 24px;
30
+ --md-sys-sidesheet-padding-standard: var(--md-sys-layout-window-margin, 24px);
31
+ }
32
+ body {
32
33
  --md-sys-sidesheet-motion-spatial: #{motion.$md-sys-motion-expressive-slow-spatial};
33
34
  --md-sys-sidesheet-motion-duration: #{motion.$md-sys-motion-expressive-slow-spatial-duration};
34
35
  --md-sys-sidesheet-motion-duration-reverse: #{motion.$md-sys-motion-expressive-default-spatial-duration};
35
36
  }
36
37
 
37
38
  dialog.micl-sidesheet {
39
+ --md-sys-sidesheet-spring-buffer: 40px;
40
+
38
41
  box-sizing: border-box;
39
42
  display: none;
40
43
  flex-direction: column;
@@ -47,7 +50,7 @@ dialog.micl-sidesheet {
47
50
  margin-block: 0;
48
51
  margin-inline-start: auto;
49
52
  margin-inline-end: calc(-1 * (var(--md-sys-sidesheet-maxwidth) + var(--md-sys-sidesheet-spring-buffer)));
50
- padding-block: 14px 0;
53
+ padding-block: var(--md-sys-sidesheet-padding-standard) 0;
51
54
  padding-inline: 0 var(--md-sys-sidesheet-spring-buffer);
52
55
  background-color: var(--md-sys-color-surface);
53
56
  border: none;
@@ -64,7 +67,9 @@ dialog.micl-sidesheet {
64
67
  .micl-sidesheet__headline {
65
68
  display: flex;
66
69
  align-items: center;
70
+ block-size: var(--md-sys-typescale-title-large-line-height);
67
71
  padding-inline: var(--md-sys-sidesheet-padding-standard);
72
+ margin-block-end: 16px;
68
73
  column-gap: 12px;
69
74
  color: var(--md-sys-color-on-surface-variant);
70
75
 
@@ -82,14 +87,12 @@ dialog.micl-sidesheet {
82
87
  margin-inline: -12px;
83
88
  }
84
89
  button:first-child {
85
- margin-inline-start: -20px;
90
+ margin-inline-start: -16px;
86
91
  }
87
92
  }
88
93
  .micl-sidesheet__content {
89
94
  box-sizing: border-box;
90
95
  flex: 1 1 auto;
91
- inline-size: 100%;
92
- max-inline-size: 100%;
93
96
  padding-inline: var(--md-sys-sidesheet-padding-standard);
94
97
  overflow: hidden auto;
95
98
  }
@@ -99,12 +102,10 @@ dialog.micl-sidesheet {
99
102
  flex-shrink: 0;
100
103
  align-items: center;
101
104
  justify-content: start;
102
- inline-size: 100%;
103
- max-inline-size: 100%;
104
- padding-block: 16px 24px;
105
+ padding-block: 16px var(--md-sys-sidesheet-padding-standard);
105
106
  padding-inline: var(--md-sys-sidesheet-padding-standard);
107
+ column-gap: 8px;
106
108
  overflow: hidden;
107
- border-block-start: var(--md-sys-divider-thickness) solid var(--md-sys-divider-color);
108
109
  }
109
110
 
110
111
  &[open] {
@@ -114,9 +115,9 @@ dialog.micl-sidesheet {
114
115
  box-shadow: var(--md-sys-elevation-level1);
115
116
  }
116
117
  &:popover-open {
117
- --md-sys-divider-color: var(--md-sys-color-outline);
118
+ --md-sys-divider-color: var(--md-sys-color-outline, gray);
118
119
 
119
- border-inline-start: var(--md-sys-divider-thickness) solid var(--md-sys-divider-color);
120
+ border-inline-start: var(--md-sys-divider-thickness, 1px) solid var(--md-sys-divider-color);
120
121
  }
121
122
  &:popover-open,
122
123
  &[open] {
@@ -136,13 +137,11 @@ dialog.micl-sidesheet {
136
137
  }
137
138
  &::backdrop {
138
139
  background-color: rgba(0, 0, 0, 0);
139
- transition:
140
- background-color var(--md-sys-sidesheet-motion-duration) linear,
141
- overlay var(--md-sys-sidesheet-motion-duration) linear allow-discrete,
142
- display var(--md-sys-sidesheet-motion-duration) linear allow-discrete;
140
+ transition: background-color var(--md-sys-sidesheet-motion-duration-reverse) linear;
143
141
  }
144
142
  &[open]::backdrop {
145
143
  background-color: rgba(0, 0, 0, 0.2);
144
+ transition: background-color var(--md-sys-sidesheet-motion-duration) linear;
146
145
 
147
146
  @starting-style {
148
147
  background-color: rgba(0, 0, 0, 0);
@@ -1,5 +1,5 @@
1
1
  # Slider
2
- This component implements the the [Material Design 3 Expressive Slider](https://m3.material.io/components/sliders/overview) design.
2
+ This component implements the [Material Design 3 Expressive Slider](https://m3.material.io/components/sliders/overview) design.
3
3
 
4
4
  ## Basic Usage
5
5
 
@@ -17,6 +17,11 @@ Import the slider styles into your project:
17
17
  @use "material-inspired-component-library/dist/slider";
18
18
  ```
19
19
 
20
+ Or import all MICL styles:
21
+ ```CSS
22
+ @use "material-inspired-component-library/styles";
23
+ ```
24
+
20
25
  ### JavaScript
21
26
  This component requires JavaScript for functionality:
22
27
 
@@ -26,8 +31,8 @@ import micl from "material-inspired-component-library/dist/micl";
26
31
 
27
32
  This will initialize any Slider component, including those that will be added to the DOM later on.
28
33
 
29
- ### Demo
30
- A live example of the [Slider component](https://henkpb.github.io/micl/slider.html) is available for you to interact with.
34
+ ### Live Demo
35
+ A live example of the [Slider component](https://henkpb.github.io/micl/slider.html) is available to interact with.
31
36
 
32
37
  ## Variants
33
38
  Sliders come in **five different sizes**: extra small (`xs`), small (`s`), medium (`m`), large (`l`), and extra large (`xl`). To set a specific size, append the appropriate postfix to the `micl-slider` CSS class name:
@@ -19,6 +19,7 @@
19
19
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
20
  // SOFTWARE.
21
21
 
22
+ @use '../../foundations/layout';
22
23
  @use '../../styles/motion';
23
24
  @use '../../styles/shapes';
24
25
  @use '../../styles/statelayer';
@@ -0,0 +1,190 @@
1
+ # Stepper
2
+ This component creates a **Stepper** to manage a linear, step-by-step process for gathering or displaying information, inspired by the design principles of [Material Design 3 Expressive](https://m3.material.io/components).
3
+
4
+ ## Basic Usage
5
+
6
+ ### HTML
7
+ To create a basic stepper, use a `<div>` container with the `micl-stepper` class and the `role="tablist"` attribute. The individual steps are placed within `<div class="micl-stepper__steps">`. Each step content is a `<div>` with the `micl-stepper__step` class and the `role="tabpanel"` attribute. The currently active step must be marked with `aria-current="step"`.
8
+
9
+ ```HTML
10
+ <div class="micl-stepper" role="tablist" aria-label="My Step-by-Step Process">
11
+ <div class="micl-stepper__steps">
12
+ <div class="micl-stepper__step" role="tabpanel" aria-current="step">
13
+ Step 1 Content
14
+ </div>
15
+ <div class="micl-stepper__step" role="tabpanel">
16
+ Step 2 Content
17
+ </div>
18
+ </div>
19
+
20
+ <div class="micl-stepper__actions">
21
+ <div>
22
+ <button type="button" class="micl-button-text-m micl-stepper__action-back">Back</button>
23
+ </div>
24
+ <div>
25
+ <button type="button" class="micl-button-tonal-m micl-stepper__action-next">Next</button>
26
+ </div>
27
+ </div>
28
+ </div>
29
+ ```
30
+
31
+ ### CSS
32
+ Import the stepper styles into your project:
33
+
34
+ ```CSS
35
+ @use "material-inspired-component-library/dist/stepper";
36
+ ```
37
+
38
+ Or import all MICL styles:
39
+ ```CSS
40
+ @use "material-inspired-component-library/styles";
41
+ ```
42
+
43
+ ### JavaScript
44
+ This component requires JavaScript to enable navigation, state management, and form validation. The library will automatically initialize new components as they're added to the DOM.
45
+
46
+ ```JavaScript
47
+ import micl from "material-inspired-component-library/dist/micl";
48
+ ```
49
+
50
+ ### Live Demo
51
+ A live example of the [Stepper component](https://henkpb.github.io/micl/stepper.html) is available to interact with.
52
+
53
+ ## Action and State Management
54
+ The Stepper component automatically manages navigation between steps and controls the visibility of the **Back** and **Next** buttons based on the current step.
55
+
56
+ - **Next Action**: Clicking a button with the `micl-stepper__action-next` class advances the stepper by one step. This button is automatically hidden when the last step is active.
57
+
58
+ - **Back Action**: Clicking a button with the `micl-stepper__action-back` class moves the stepper back one step. This button is automatically hidden when the first step is active.
59
+
60
+ ### Stepper Header
61
+ The optional Stepper Header displays the step titles horizontally, allowing users to navigate directly to steps. The `aria-controls` and `aria-labelledby` attributes are essential for accessibility, linking the header buttons to their corresponding step panels.
62
+
63
+ ```HTML
64
+ <div class="micl-stepper">
65
+ <div class="micl-stepper__header">
66
+ <button type="button" role="tab" id="step1Label class="micl-button-text-xs" aria-controls="step1" aria-selected="true">
67
+ <span class="micl-stepper__progress-dot" aria-hidden="true"></span>
68
+ Step 1
69
+ </button>
70
+ <button type="button" role="tab" id="step2Label class="micl-button-text-xs" aria-controls="step2">
71
+ <span class="micl-stepper__progress-dot" aria-hidden="true"></span>
72
+ Step 2
73
+ </button>
74
+ </div>
75
+ <div class="micl-stepper__steps">
76
+ <div id="step1" role="tabpanel" class="micl-stepper__step" aria-labelledby="step1Label" aria-current="step">
77
+ Step 1 Content
78
+ </div>
79
+ <div id="step2" role="tabpanel" class="micl-stepper__step" aria-labelledby="step2Label">
80
+ Step 2 Content
81
+ </div>
82
+ </div>
83
+ </div>
84
+ ```
85
+
86
+ ### Linear vs. Non-linear Steppers
87
+ - **Linear (Default)**: The user can only click the header buttons of previous steps to revisit them. Navigation to future steps is disabled until they are reached.
88
+
89
+ - **Non-linear**: Apply the `micl-stepper--nonlinear` modifier class to the main stepper container. This allows the user to click any of the header buttons to freely jump between steps.
90
+
91
+ ## Variants
92
+
93
+ ### Progress indicator
94
+ You can include optional elements to display the user's progress.
95
+
96
+ #### Counter
97
+ Use the `micl-stepper__progress-current` and `micl-stepper__progress-total` classes to automatically display the current step number and the total number of steps (e.g., "1 of 3").
98
+
99
+ ```HTML
100
+ <div class="micl-stepper__actions">
101
+ <div>
102
+ <button type="button" class="micl-button-text-m micl-stepper__action-back">Back</button>
103
+ </div>
104
+ <div>
105
+ <span class="micl-stepper__progress-current"></span>
106
+ <span> of </span>
107
+ <span class="micl-stepper__progress-total"></span>
108
+ </div>
109
+ <div>
110
+ <button type="button" class="micl-button-tonal-m micl-stepper__action-next">Next</button>
111
+ </div>
112
+ </div>
113
+ ```
114
+
115
+ #### Dots
116
+ Use the `micl-stepper__progress-dots` class to generate a visual progress bar using colored dots. The dots dynamically change color to indicate the current step.
117
+
118
+ ```HTML
119
+ <div class="micl-stepper__actions">
120
+ <div>
121
+ <button type="button" class="micl-button-text-m micl-stepper__action-back">Back</button>
122
+ </div>
123
+ <div class="micl-stepper__progress-dots"></div>
124
+ <div>
125
+ <button type="button" class="micl-button-tonal-m micl-stepper__action-next">Next</button>
126
+ </div>
127
+ </div>
128
+ ```
129
+
130
+ ### Step validation
131
+ To enable built-in **form validation** for each step, use a `<form>` element as the main stepper container and replace the step `<div>`s with `<fieldset>` elements.
132
+
133
+ #### Validation Flow
134
+ - **Step-by-Step Validation**: When a user clicks **Next**, the browser's built-in validation is triggered only for the input fields within the current step. If any constraints are violated, the stepper will not advance.
135
+
136
+ - **Error Display**: The Stepper component applies the error state to any child MICL component that supports it, displaying the custom error text. Otherwise, the default browser validation message appears.
137
+
138
+ - **Final Submission Validation**: If the final step contains a `type="submit"` button, the component validates the entire form upon submission. The form will only be submitted if all data input fields across all steps are valid.
139
+
140
+ ```HTML
141
+ <form class="micl-stepper" action="/submit-data" method="post" role="tablist" aria-label="My Form">
142
+ <div class="micl-stepper__steps">
143
+ <fieldset class="micl-stepper__step" role="tabpanel" aria-current="step">
144
+ <div class="micl-textfield-filled">
145
+ <label for="mytextfield">Label text</label>
146
+ <input type="text" id="mytextfield" name="mytext" required>
147
+ </div>
148
+ </fieldset>
149
+ <fieldset class="micl-stepper__step" role="tabpanel">
150
+ Step 2 Content
151
+ </fieldset>
152
+ </div>
153
+ <div class="micl-stepper__actions">
154
+ ...
155
+ </div>
156
+ </form>
157
+ ```
158
+
159
+ #### Step-Specific Action Buttons
160
+ Action buttons can be made visible only on a specific step by using the `data-step` attribute, which specifies the step number (starting from 1). This is useful for replacing the default **Next** button with a content-specific action, like a **Submit** button on the final step.
161
+
162
+ In this example for a three-step stepper, the **Next** button is hidden on step 3, and the **Submit** button is shown instead:
163
+
164
+ ```HTML
165
+ <div class="micl-stepper__actions">
166
+ <div>
167
+ <button type="button" class="micl-button-text-m micl-stepper__action-back">Back</button>
168
+ </div>
169
+ <div>
170
+ <button type="submit" class="micl-button-tonal-m" data-step="3">Submit</button>
171
+ <button type="button" class="micl-button-tonal-m micl-stepper__action-next">Next</button>
172
+ </div>
173
+ </div>
174
+ ```
175
+
176
+ ## Customizations
177
+ You can customize the appearance of the Stepper component by overriding its global CSS variables. These variables are declared on the `:root` pseudo-class and can be changed on any appropriate parent element to affect its child steppers.
178
+
179
+ | Variable name | Default Value | Description |
180
+ | ------------- | ----- | ----------- |
181
+ | --md-sys-stepper-counter-style | decimal | The list-style used for the counter number inside the dots in the stepper header |
182
+ | --md-sys-stepper-dot-size | 12px | Controls the size of each progress dot |
183
+
184
+ **Example: Changing the style of the counter inside header dots**
185
+
186
+ ```HTML
187
+ <div class="micl-stepper" style="--md-sys-stepper-counter-style:upper-alpha">
188
+ ...
189
+ </div>
190
+ ```
@@ -19,11 +19,15 @@
19
19
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
20
  // SOFTWARE.
21
21
 
22
- @use '../../layout';
22
+ @use '../../foundations/layout';
23
23
  @use '../../styles/motion';
24
24
 
25
25
  :root {
26
- --md-sys-stepper-thickness: 1px;
26
+ --md-sys-stepper-counter-style: decimal;
27
+ --md-sys-stepper-dot-size: 12px;
28
+ }
29
+ body {
30
+ --md-sys-stepper-dot-done-color: var(--md-sys-color-tertiary-container, blue);
27
31
  }
28
32
 
29
33
  .micl-stepper {
@@ -35,8 +39,38 @@
35
39
  display: flex;
36
40
  flex-direction: column;
37
41
  row-gap: var(--md-sys-layout-padding-xl, 24px);
42
+ margin: 0;
38
43
  background-color: inherit;
39
44
 
45
+ .micl-stepper__header {
46
+ --md-sys-stepper-dot-size: 24px;
47
+
48
+ display: flex;
49
+ justify-content: space-between;
50
+ align-items: flex-start;
51
+ margin-inline: -10px;
52
+ background-color: inherit;
53
+ background-image: linear-gradient(90deg, var(--md-sys-divider-color), var(--md-sys-divider-color));
54
+ background-position: center;
55
+ background-repeat: no-repeat;
56
+ background-size: 100% 1px;
57
+ counter-reset: dotnumber;
58
+
59
+ button {
60
+ background-color: inherit;
61
+ pointer-events: none;
62
+
63
+ &.micl-stepper__progress--done {
64
+ pointer-events: inherit;
65
+ }
66
+ }
67
+ .micl-stepper__progress-dot::before {
68
+ content: counter(dotnumber, var(--md-sys-stepper-counter-style));
69
+ }
70
+ }
71
+ &.micl-stepper--nonlinear .micl-stepper__header button {
72
+ pointer-events: inherit;
73
+ }
40
74
  .micl-stepper__steps {
41
75
  display: grid;
42
76
  grid-template-areas: "stepper-steps";
@@ -48,7 +82,9 @@
48
82
  display: flex;
49
83
  visibility: hidden;
50
84
  flex-direction: column;
51
- justify-content: space-between;
85
+ margin: 0;
86
+ padding: 0;
87
+ border: none;
52
88
  opacity: 0%;
53
89
  background-color: inherit;
54
90
  transform: translateX(100%);
@@ -56,30 +92,73 @@
56
92
  opacity var(--md-sys-stepper-motion-duration) linear,
57
93
  transform var(--md-sys-stepper-motion-duration) var(--md-sys-stepper-motion-spatial);
58
94
 
59
- &:has(~ .micl-stepper__step--current) {
95
+ &:has(~ .micl-stepper__step[aria-current=step]) {
60
96
  transform: translateX(-100%);
61
97
  }
62
- &.micl-stepper__step--tocurrent {
98
+ &.micl-stepper__step--toselected {
63
99
  visibility: visible;
64
100
  }
65
- &.micl-stepper__step--current {
101
+ &[aria-current=step] {
66
102
  visibility: visible;
67
103
  opacity: 100%;
68
104
  transform: translateX(0%);
69
105
  }
70
- &.micl-stepper__step--fromcurrent {
106
+ &.micl-stepper__step--fromselected {
71
107
  visibility: visible;
72
108
  }
73
-
74
- .micl-stepper__content {
75
- box-sizing: border-box;
76
- padding-inline: var(--md-sys-stepper-padding-inline);
77
- background-color: inherit;
78
- }
79
109
  }
80
110
  }
81
111
  .micl-stepper__actions {
82
112
  display: flex;
83
- justify-content: space-between;
113
+ flex-direction: row;
114
+ justify-content: center;
115
+ inline-size: 100%;
116
+ align-items: center;
117
+
118
+ &>:first-child,
119
+ &>:last-child {
120
+ display: flex;
121
+ flex: 1 1 0;
122
+ column-gap: var(--md-sys-layout-padding-xs, 8px)
123
+ }
124
+ &>:last-child {
125
+ justify-content: flex-end;
126
+ }
127
+ }
128
+ .micl-stepper__progress-dots {
129
+ display: flex;
130
+ align-items: center;
131
+ column-gap: 4px;
132
+ }
133
+ .micl-stepper__progress-dot {
134
+ block-size: var(--md-sys-stepper-dot-size);
135
+ inline-size: var(--md-sys-stepper-dot-size);
136
+ min-inline-size: var(--md-sys-stepper-dot-size);
137
+ line-height: var(--md-sys-stepper-dot-size);
138
+ border-radius: calc(var(--md-sys-stepper-dot-size) / 2);
139
+ text-align: center;
140
+ background-color: var(--md-sys-color-on-surface);
141
+ color: var(--md-sys-color-surface);
142
+ opacity: 38%;
143
+ counter-increment: dotnumber 1;
144
+ }
145
+ .micl-stepper__progress--done.micl-stepper__progress-dot,
146
+ .micl-stepper__progress--done .micl-stepper__progress-dot {
147
+ background-color: var(--md-sys-stepper-dot-done-color);
148
+ color: var(--md-sys-color-on-tertiary-container);
149
+ opacity: 100%;
150
+ }
151
+ }
152
+
153
+ [dir=rtl] {
154
+ .micl-stepper .micl-stepper__steps .micl-stepper__step {
155
+ transform: translateX(-100%);
156
+
157
+ &:has(~ .micl-stepper__step[aria-current=step]) {
158
+ transform: translateX(100%);
159
+ }
160
+ &[aria-current=step] {
161
+ transform: translateX(0%);
162
+ }
84
163
  }
85
164
  }