@solid-design-system/mcp 7.0.2 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 7.1.0
4
+
5
+ ## 7.0.3
6
+
3
7
  ## 7.0.2
4
8
 
5
9
  ## 7.0.1
@@ -16,6 +16,7 @@ Use the components tool by passing the args `component` and `example` for any of
16
16
  - component: sd-datepicker, example: disabled
17
17
  - component: sd-datepicker, example: visually-disabled
18
18
  - component: sd-datepicker, example: help-text
19
+ - component: sd-datepicker, example: clearable
19
20
  - component: sd-datepicker, example: required
20
21
  - component: sd-datepicker, example: valid
21
22
  - component: sd-datepicker, example: invalid
@@ -56,6 +57,7 @@ Use the components tool by passing the args `component` and `example` for any of
56
57
  - prop.visuallyDisabled [attr: visually-disabled]: boolean, default=false — Makes the control non-interactive visually (like disabled) without disabling it functionally.
57
58
  - prop.styleOnValid [attr: style-on-valid]: boolean, default=false — When true, applies success styling for valid selections.
58
59
  - prop.readonly: boolean, default=false — Makes the input read-only (non-editable) when true.
60
+ - prop.clearable: boolean, default=false — Adds a clear button when the datepicker is not empty.
59
61
  - prop.placement: 'top'|'bottom', default='bottom' — Preferred placement of the flyout relative to the input (top|bottom).
60
62
  - prop.placeholder: string, default='' — Placeholder text for the input when no date is selected.
61
63
  - prop.name: string, default='' — The name of the datepicker, submitted as a name/value pair with form data.
@@ -79,6 +81,7 @@ Use the components tool by passing the args `component` and `example` for any of
79
81
  - event.sd-blur: Emitted when the datepicker is blurred.
80
82
  - event.sd-month-change: Emitted when the month is changed.
81
83
  - event.sd-month-year: Emitted when the year is changed.
84
+ - event.sd-clear: Emitted when the clear button is activated.
82
85
 
83
86
  ### Slots
84
87
 
@@ -86,6 +89,7 @@ Use the components tool by passing the args `component` and `example` for any of
86
89
  - slot.label: The label for the date input.
87
90
  - slot.help-text: The help text, displayed below the input.
88
91
  - slot.tooltip: The tooltip icon and content.
92
+ - slot.clear-icon: An icon to use in lieu of the default clear icon.
89
93
 
90
94
  ### CSS Parts
91
95
 
@@ -106,6 +110,7 @@ Use the components tool by passing the args `component` and `example` for any of
106
110
  - part.invalid-icon: The icon shown when the input is invalid.
107
111
  - part.valid-icon: The icon shown when the input is valid.
108
112
  - part.form-control-help-text: The help text, displayed below the input.
113
+ - part.clear-button: The clear button.
109
114
 
110
115
  ## Guidelines
111
116
 
@@ -0,0 +1,7 @@
1
+ Use the `clearable` attribute to add a clear button that removes the datepicker value.
2
+
3
+ ```html
4
+ <div class="max-w-[370px] h-[500px]">
5
+ <sd-datepicker label="Label" value="2026.01.01" clearable></sd-datepicker>
6
+ </div>
7
+ ```
@@ -29,16 +29,16 @@
29
29
  "displayNameDe": "Sonne",
30
30
  "tags": ["sonnig", "hell", "schönes Wetter"]
31
31
  },
32
- {
33
- "technicalId": "settings",
34
- "displayNameDe": "Einstellungen",
35
- "tags": ["anpassen", "Bearbeitung", "Zahnrad"]
36
- },
37
32
  {
38
33
  "technicalId": "volume",
39
34
  "displayNameDe": "Lautstärke",
40
35
  "tags": ["Ton", "Pegel", "Geräuschpegel"]
41
36
  },
37
+ {
38
+ "technicalId": "settings",
39
+ "displayNameDe": "Einstellungen",
40
+ "tags": ["anpassen", "Bearbeitung", "Zahnrad"]
41
+ },
42
42
  {
43
43
  "technicalId": "hand",
44
44
  "displayNameDe": "Hand",
@@ -844,16 +844,16 @@
844
844
  "displayNameDe": "Lesezeichen",
845
845
  "tags": ["merken", "Markierung", "markiert", "Favoriten"]
846
846
  },
847
- {
848
- "technicalId": "flash",
849
- "displayNameDe": "Blitz",
850
- "tags": ["Pfeil", "Fehler", "falsch"]
851
- },
852
847
  {
853
848
  "technicalId": "arrow-right",
854
849
  "displayNameDe": "Pfeil rechts",
855
850
  "tags": ["Pfeil", "vorwärts", "weiter"]
856
851
  },
852
+ {
853
+ "technicalId": "flash",
854
+ "displayNameDe": "Blitz",
855
+ "tags": ["Pfeil", "Fehler", "falsch"]
856
+ },
857
857
  {
858
858
  "technicalId": "arrow-top",
859
859
  "displayNameDe": "Pfeil oben",
@@ -0,0 +1,266 @@
1
+ ---
2
+ name: file-selector
3
+ title: File Selector
4
+ components:
5
+ - sd-button
6
+ - sd-divider
7
+ - sd-file-selector
8
+ - sd-headline
9
+ - sd-headline--size-3xl
10
+ - sd-headline--size-4xl
11
+ - sd-icon
12
+ - sd-input
13
+ - sd-interactive
14
+ - sd-interactive--reset
15
+ - sd-meta
16
+ - sd-meta--light
17
+ - sd-meta--size-sm
18
+ - sd-option
19
+ - sd-paragraph
20
+ - sd-progress-bar
21
+ - sd-select
22
+ - sd-tooltip
23
+ version: 1.0.0
24
+ ---
25
+
26
+ ## Template: File Selector with Default variant
27
+
28
+ ```html
29
+ <section>
30
+ <form id="identity-form" class="flex flex-col gap-6">
31
+ <div class="flex flex-col gap-2">
32
+ <h3 class="sd-headline sd-headline--size-4xl">Confirm your identity</h3>
33
+ <p class="sd-paragraph">
34
+ To safeguard your account, we need to verify who you are. Choose a document type below and upload a clear scan.
35
+ </p>
36
+ </div>
37
+ <div class="flex flex-col gap-6">
38
+ <span class="sd-meta sd-meta--size-sm sd-meta--light">Fields marked with * are required.</span>
39
+ <sd-select name="documentType" label="Document type" placeholder="Please select" required>
40
+ <sd-option value="passport">Passport</sd-option>
41
+ <sd-option value="id-card">ID card</sd-option>
42
+ </sd-select>
43
+ <sd-file-selector name="identityDocument" label="Upload document" show-label required></sd-file-selector>
44
+ </div>
45
+ </form>
46
+ </section>
47
+ ```
48
+
49
+ ## Template: File Selector with Drop Area variant
50
+
51
+ ```html
52
+ <section>
53
+ <form id="droparea-documents-form" class="flex flex-col gap-6">
54
+ <h3 class="sd-headline sd-headline--size-3xl">Tax Documents &amp; Depot Statements</h3>
55
+ <p class="sd-paragraph">
56
+ Please share your tax and depot records for the current year. Digital documents help us provide you with accurate
57
+ tax reporting services.
58
+ </p>
59
+ <div class="flex flex-col">
60
+ <span class="sd-meta sd-meta--size-sm sd-meta--light">Fields marked with * are required.</span>
61
+ <sd-file-selector
62
+ id="droparea-file-selector"
63
+ name="droparea-file-selector"
64
+ label="Upload documents"
65
+ show-label
66
+ drop-area
67
+ multiple
68
+ required
69
+ accept=".pdf,.jpg,.jpeg,.png"
70
+ help-text="Maximum file size 3 MB. Supported: PDF, JPG, PNG."
71
+ class="mt-6"
72
+ ></sd-file-selector>
73
+ <ul id="droparea-file-list" class="file-list flex flex-col gap-2 mt-2" aria-live="polite"></ul>
74
+ </div>
75
+ <div class="flex flex-col gap-4 md:flex-row md:justify-end">
76
+ <sd-button variant="secondary" onclick="alert('Cancelled process')">Cancel</sd-button>
77
+ <sd-tooltip id="droparea-submit-tooltip" trigger="hover focus" content="Please select one or more files.">
78
+ <sd-button id="droparea-submit-button" type="submit" visually-disabled>Submit documents</sd-button>
79
+ </sd-tooltip>
80
+ </div>
81
+ </form>
82
+ </section>
83
+ <script type="module">
84
+ await Promise.all([
85
+ customElements.whenDefined('sd-file-selector'),
86
+ customElements.whenDefined('sd-progress-bar'),
87
+ customElements.whenDefined('sd-button'),
88
+ customElements.whenDefined('sd-icon'),
89
+ customElements.whenDefined('sd-divider'),
90
+ customElements.whenDefined('sd-tooltip')
91
+ ]);
92
+
93
+ const MAX_FILE_SIZE = 3 * 1024 * 1024;
94
+ const ALLOWED_FILE_TYPES = ['application/pdf', 'image/jpeg', 'image/png'];
95
+ const NO_FILES_MESSAGE = 'Please select one or more files.';
96
+ const INVALID_FILES_MESSAGE = 'One or more files have errors. Please remove them and try again.';
97
+ const fileSelector = document.getElementById('droparea-file-selector');
98
+ const fileList = document.getElementById('droparea-file-list');
99
+ const submitButton = document.getElementById('droparea-submit-button');
100
+ const submitTooltip = document.getElementById('droparea-submit-tooltip');
101
+ let files = [];
102
+
103
+ // preview-ignore:start
104
+ const delay = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));
105
+ const simulateUpload = async (file, progressBar, fileName) => {
106
+ for (let progress = 0; progress <= 100; progress += 1) {
107
+ progressBar.value = progress;
108
+ progressBar.label = 'Uploading ' + file.name + ': ' + progress + '%';
109
+
110
+ await delay(50);
111
+ }
112
+
113
+ progressBar.label = file.name + ' uploaded successfully';
114
+ await delay(300);
115
+
116
+ progressBar.remove();
117
+ fileName.classList.remove('shrink-0', 'text-neutral-700');
118
+ fileName.classList.add('flex-1', 'text-black');
119
+ };
120
+ // preview-ignore:end
121
+
122
+ const updateSubmitButtonState = () => {
123
+ const hasFiles = files.length > 0;
124
+ const hasInvalidFiles = fileList?.querySelector('li.invalid') !== null;
125
+ const isDisabled = !hasFiles || hasInvalidFiles;
126
+
127
+ submitButton.visuallyDisabled = isDisabled;
128
+ submitTooltip.disabled = !isDisabled;
129
+ submitTooltip.content = hasInvalidFiles ? INVALID_FILES_MESSAGE : NO_FILES_MESSAGE;
130
+ };
131
+
132
+ fileSelector.addEventListener('sd-input', event => {
133
+ fileList?.replaceChildren();
134
+
135
+ files = Array.from(event.currentTarget.files ?? []);
136
+ fileList?.classList.toggle('hidden', files.length === 0);
137
+
138
+ files.forEach((file, index) => {
139
+ const listItem = document.createElement('li');
140
+ const listRow = document.createElement('div');
141
+ const fileName = document.createElement('span');
142
+ const removeButton = document.createElement('button');
143
+
144
+ listItem.classList.add('flex', 'flex-col', 'text-sm', 'gap-2', 'text-left');
145
+ listRow.classList.add('flex', 'items-center', 'gap-2', 'w-full');
146
+ fileName.classList.add('shrink-0', 'truncate', 'text-neutral-700');
147
+ fileName.textContent = file.name;
148
+
149
+ removeButton.type = 'button';
150
+ removeButton.classList.add('sd-interactive', 'sd-interactive--reset', 'shrink-0', 'flex', 'items-center');
151
+ removeButton.title = 'Remove ' + file.name;
152
+ removeButton.setAttribute('aria-label', 'Remove ' + file.name);
153
+
154
+ const trashIcon = document.createElement('sd-icon');
155
+ trashIcon.setAttribute('name', 'system/trash');
156
+ trashIcon.setAttribute('color', 'currentColor');
157
+ trashIcon.setAttribute('aria-hidden', 'true');
158
+ trashIcon.classList.add('w-4', 'h-4');
159
+
160
+ removeButton.append(trashIcon);
161
+ listRow.append(fileName);
162
+
163
+ /**
164
+ * Client-side validation example.
165
+ * Files must also be validated by the server.
166
+ */
167
+ const errors = [];
168
+
169
+ if (!ALLOWED_FILE_TYPES.includes(file.type)) errors.push('Unsupported file type');
170
+ if (file.size > MAX_FILE_SIZE) errors.push('The file is too large. Maximum allowed size is 3 MB.');
171
+
172
+ if (errors.length === 0) {
173
+ const progressBar = document.createElement('sd-progress-bar');
174
+
175
+ progressBar.classList.add('flex-1');
176
+ progressBar.max = 100;
177
+ progressBar.value = 0;
178
+ progressBar.label = 'Uploading ' + file.name + ': 0%';
179
+
180
+ listRow.append(progressBar);
181
+
182
+ /**
183
+ * Connect the progress bar to your application's
184
+ * upload progress here.
185
+ */
186
+
187
+ // preview-ignore:start
188
+ simulateUpload(file, progressBar, fileName);
189
+ // preview-ignore:end
190
+ } else {
191
+ fileName.classList.add('flex-1');
192
+ }
193
+ listRow.append(removeButton);
194
+ listItem.append(listRow);
195
+
196
+ errors.forEach(message => {
197
+ const errorMessage = document.createElement('div');
198
+
199
+ errorMessage.classList.add('flex', 'items-center', 'gap-2', 'text-error', 'text-left', 'text-sm');
200
+ fileName.classList.remove('text-neutral-700');
201
+ fileName.classList.add('text-black');
202
+ errorMessage.setAttribute('role', 'alert');
203
+
204
+ const errorIcon = document.createElement('sd-icon');
205
+ errorIcon.setAttribute('name', 'system/warning');
206
+ errorIcon.setAttribute('color', 'currentColor');
207
+ errorIcon.setAttribute('aria-hidden', 'true');
208
+
209
+ const errorText = document.createElement('span');
210
+ errorText.textContent = message;
211
+
212
+ errorMessage.append(errorIcon, errorText);
213
+ listItem.append(errorMessage);
214
+ });
215
+
216
+ removeButton.addEventListener('click', () => {
217
+ files = files.filter(remainingFile => remainingFile !== file);
218
+
219
+ const dataTransfer = new DataTransfer();
220
+
221
+ files.forEach(remainingFile => {
222
+ dataTransfer.items.add(remainingFile);
223
+ });
224
+
225
+ fileSelector.files = dataTransfer.files;
226
+ listItem.remove();
227
+
228
+ const lastListItem = fileList?.querySelector('li:last-child');
229
+ const lastDivider = lastListItem?.querySelector(':scope > sd-divider');
230
+
231
+ lastDivider?.remove();
232
+ fileList?.classList.toggle('hidden', files.length === 0);
233
+ updateSubmitButtonState();
234
+ });
235
+
236
+ if (errors.length > 0) listItem.classList.add('invalid');
237
+
238
+ if (index < files.length - 1) {
239
+ const divider = document.createElement('sd-divider');
240
+ divider.setAttribute('aria-hidden', 'true');
241
+ listItem.append(divider);
242
+ }
243
+
244
+ fileList?.append(listItem);
245
+ });
246
+
247
+ updateSubmitButtonState();
248
+ });
249
+
250
+ const form = document.getElementById('droparea-documents-form');
251
+ form.onsubmit = event => {
252
+ event.preventDefault();
253
+
254
+ if (submitButton.visuallyDisabled) {
255
+ return;
256
+ }
257
+
258
+ if (form.checkValidity()) {
259
+ alert('Drop area form submitted');
260
+ return;
261
+ }
262
+
263
+ form.reportValidity();
264
+ };
265
+ </script>
266
+ ```
@@ -2,12 +2,18 @@
2
2
  name: footnotes
3
3
  title: Footnotes
4
4
  components:
5
+ - sd-container
6
+ - sd-container--variant-primary
5
7
  - sd-footnotes
8
+ - sd-footnotes--inverted
6
9
  - sd-footnotes--marker
7
10
  - sd-headline
8
- - sd-headline--3xl
11
+ - sd-headline--inverted
12
+ - sd-headline--size-3xl
9
13
  - sd-paragraph
14
+ - sd-paragraph--inverted
10
15
  - sd-prose
16
+ - sd-prose--inverted
11
17
  version: 1.0.0
12
18
  ---
13
19
 
@@ -15,10 +21,7 @@ version: 1.0.0
15
21
 
16
22
  ```html
17
23
  <div class="sd-prose">
18
- <!-- Dev-note: The <a> elements have been wrapped in <span> elements due to an issue in safari
19
- where using the mouse to navigate between footnotes would trigger the focus-outline. -->
20
-
21
- <h2 class="sd-headline sd-headline--3xl">The Power of a Solid Design System</h2>
24
+ <h2 class="sd-headline sd-headline--size-3xl">The Power of a Solid Design System</h2>
22
25
  <p class="sd-paragraph">
23
26
  A solid design system is the backbone of a cohesive product, offering a single source of truth that promotes
24
27
  consistency across all platforms and teams
@@ -47,7 +50,7 @@ version: 1.0.0
47
50
  increasingly complex. A well-defined design system mitigates these challenges by acting as a blueprint for future
48
51
  iterations, preventing visual drift and maintaining brand integrity across diverse touchpoints. Teams can
49
52
  confidently experiment and innovate within the system’s boundaries, knowing that their work aligns with established
50
- guidelines <span id="ref_4" class="sd-footnotes--marker"><a href="#note_4">3</a></span> .
53
+ guidelines <span id="ref_4" class="sd-footnotes--marker"><a href="#note_4">4</a></span> .
51
54
  </p>
52
55
  <p>
53
56
  By continuously evolving with feedback and technological advancements, a design system remains a living entity
@@ -60,21 +63,54 @@ version: 1.0.0
60
63
  <ol class="sd-footnotes mt-12">
61
64
  <li id="note_1">
62
65
  <a href="#ref_1" class="sd-footnotes--marker"></a>
63
- Design systems act as a "single source of truth," promoting consistency across all products.
66
+ A design system centralizes guidelines, ensuring consistency across teams and products.
64
67
  </li>
65
68
  <li id="note_2">
66
69
  <a href="#ref_2a" class="sd-footnotes--marker"></a>
67
70
  <a href="#ref_2b" class="sd-footnotes--marker"></a>
68
71
  <a href="#ref_2c" class="sd-footnotes--marker"></a>
69
- Component libraries in design systems streamline workflows, boosting efficiency and scalability.
72
+ A consistent UI fosters familiarity, trust, and better accessibility for diverse users.
70
73
  </li>
71
74
  <li id="note_3">
72
75
  <a href="#ref_3" class="sd-footnotes--marker"></a>
73
- A design system’s consistency helps reinforce brand identity and user trust.
76
+ Regular updates keep the design system adaptable to new trends and technologies.
74
77
  </li>
75
78
  <li id="note_4">
76
79
  <a href="#ref_4" class="sd-footnotes--marker"></a>
77
- Effective design systems evolve, remaining adaptable to product and user needs over time.
80
+ Standardized components and documentation reduce development time and design inconsistencies.
78
81
  </li>
79
82
  </ol>
80
83
  ```
84
+
85
+ ## Template: Linked Footnotes in Container
86
+
87
+ ```html
88
+ <div class="sd-container sd-container--variant-primary flex flex-col gap-8 max-w-xl">
89
+ <div class="sd-prose sd-prose--inverted">
90
+ <h2 class="sd-headline sd-headline--inverted sd-headline--size-3xl">Financing that fits your life</h2>
91
+ <p class="sd-paragraph sd-paragraph--inverted">
92
+ A clear loan structure helps customers understand exactly what they're signing up for, before they commit to
93
+ anything
94
+ <span id="ref_c_1" class="sd-footnotes--marker sd-footnotes--inverted"><a href="#note_c_1">1</a></span> .
95
+ Transparent rates, honest fees, and flexible repayment options work together to reduce surprises, helping build
96
+ long-term trust between the bank and the people it serves.
97
+ </p>
98
+ <p class="sd-paragraph sd-paragraph--inverted">
99
+ Every application is reviewed individually, factoring in income, credit history, and personal financial goals
100
+ <span id="ref_c_2" class="sd-footnotes--marker sd-footnotes--inverted"><a href="#note_c_2">2</a></span> . This
101
+ tailored approach means financing decisions reflect each customer's real situation, rather than applying a
102
+ one-size-fits-all model that ignores individual circumstances.
103
+ </p>
104
+ </div>
105
+ <ol class="sd-footnotes sd-footnotes--inverted flex flex-col gap-2">
106
+ <li id="note_c_1">
107
+ <a href="#ref_c_1" class="sd-footnotes--marker"></a>
108
+ Rates shown are indicative and subject to credit approval.
109
+ </li>
110
+ <li id="note_c_2">
111
+ <a href="#ref_c_2" class="sd-footnotes--marker"></a>
112
+ Terms may vary based on income and repayment history.
113
+ </li>
114
+ </ol>
115
+ </div>
116
+ ```
package/package.json CHANGED
@@ -20,9 +20,9 @@
20
20
  "prettier": "^3.9.5",
21
21
  "tsx": "^4.23.1",
22
22
  "typescript": "^5.9.3",
23
- "@solid-design-system/components": "7.0.2",
24
- "@solid-design-system/styles": "7.0.2",
25
- "@solid-design-system/tokens": "7.0.2"
23
+ "@solid-design-system/components": "7.1.0",
24
+ "@solid-design-system/styles": "7.1.0",
25
+ "@solid-design-system/tokens": "7.1.0"
26
26
  },
27
27
  "exports": {
28
28
  ".": {
@@ -59,7 +59,7 @@
59
59
  "directory": "packages/mcp"
60
60
  },
61
61
  "type": "module",
62
- "version": "7.0.2",
62
+ "version": "7.1.0",
63
63
  "scripts": {
64
64
  "build": "pnpm run build:components && pnpm run build:tokens && pnpm run build:ts && pnpm run build:metadata && cd ../.. && pnpm exec prettier --write --log-level warn packages/mcp/metadata",
65
65
  "build:components": "cd ../components && pnpm exec node scripts/make-metadata.js --outdir dist",