@scania/tegel-lite 0.0.2 → 0.0.3-rules-beta.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.
@@ -0,0 +1,395 @@
1
+ ---
2
+ description: 02-components-forms
3
+ alwaysApply: true
4
+ ---
5
+ # Form Components
6
+
7
+ ## Button
8
+
9
+ **Classes**: `tl-button`, `tl-button--primary`, `tl-button--secondary`, `tl-button--ghost`, `tl-button--danger`
10
+ **Sizes**: `tl-button--xs` (24px), `tl-button--sm` (40px), `tl-button--md` (48px), `tl-button--lg` (56px)
11
+ **Modifiers**: `tl-button--full-width`, `tl-button--icon`, `tl-button--only-icon`
12
+
13
+ ```html
14
+ <!-- Primary button (default) -->
15
+ <button class="tl-button tl-button--primary tl-button--md">
16
+ Primary Action
17
+ </button>
18
+
19
+ <!-- Secondary button -->
20
+ <button class="tl-button tl-button--secondary tl-button--md">Secondary</button>
21
+
22
+ <!-- Ghost button -->
23
+ <button class="tl-button tl-button--ghost tl-button--sm">Ghost</button>
24
+
25
+ <!-- Danger button -->
26
+ <button class="tl-button tl-button--danger tl-button--md">Delete</button>
27
+
28
+ <!-- Button with icon (text BEFORE icon) -->
29
+ <button class="tl-button tl-button--primary tl-button--icon tl-button--md">
30
+ Save
31
+ <span class="tl-icon tl-icon--save" aria-hidden="true"></span>
32
+ </button>
33
+
34
+ <!-- Icon-only button -->
35
+ <button
36
+ class="tl-button tl-button--only-icon tl-button--md"
37
+ aria-label="Settings"
38
+ >
39
+ <span class="tl-icon tl-icon--settings"></span>
40
+ </button>
41
+
42
+ <!-- Full width -->
43
+ <button
44
+ class="tl-button tl-button--primary tl-button--md tl-button--full-width"
45
+ >
46
+ Full Width
47
+ </button>
48
+
49
+ <!-- Disabled -->
50
+ <button class="tl-button tl-button--primary tl-button--md" disabled>
51
+ Disabled
52
+ </button>
53
+ ```
54
+
55
+ **Structure Rules**:
56
+
57
+ - **Button with icon**: Text comes FIRST, then icon. Add `tl-button--icon` modifier. Icon should have `aria-hidden="true"`.
58
+ - **Icon-only button**: Add `tl-button--only-icon` modifier and `aria-label` for accessibility.
59
+ - **Size**: Always include a size modifier (--xs, --sm, --md, --lg).
60
+ - **Variant**: Primary, secondary, ghost, or danger (optional, defaults to primary).
61
+
62
+ **Do's**:
63
+
64
+ - Always put text before icon in buttons with icons
65
+ - Always add `aria-hidden="true"` to decorative icons in buttons with text
66
+ - Always use `aria-label` for icon-only buttons
67
+
68
+ **Don'ts**:
69
+
70
+ - Never use `<div>` as a button
71
+ - Never style buttons with custom colors
72
+ - Never put icon before text in buttons with text
73
+
74
+ ---
75
+
76
+ ## Text Field (Input)
77
+
78
+ **Classes**: `tl-text-field`, `tl-text-field--lg` (56px, default), `tl-text-field--md` (48px), `tl-text-field--sm` (40px)
79
+ **Variants**: `tl-text-field--primary`, `tl-text-field--secondary`, `tl-text-field--label-inside`
80
+ **States**: `tl-text-field--error`, `tl-text-field--success`
81
+
82
+ ```html
83
+ <!-- Basic text field with external label -->
84
+ <div class="tl-text-field tl-text-field--lg">
85
+ <label class="tl-text-field__label" for="name">Name</label>
86
+ <input
87
+ class="tl-text-field__input"
88
+ id="name"
89
+ type="text"
90
+ placeholder="Enter your name"
91
+ />
92
+ </div>
93
+
94
+ <!-- Label inside -->
95
+ <div class="tl-text-field tl-text-field--lg tl-text-field--label-inside">
96
+ <label class="tl-text-field__label" for="email">Email</label>
97
+ <input class="tl-text-field__input" id="email" type="email" placeholder=" " />
98
+ </div>
99
+
100
+ <!-- With helper text -->
101
+ <div class="tl-text-field tl-text-field--lg">
102
+ <label class="tl-text-field__label" for="phone">Phone</label>
103
+ <input
104
+ class="tl-text-field__input"
105
+ id="phone"
106
+ type="tel"
107
+ placeholder="+46..."
108
+ />
109
+ <div class="tl-text-field__bottom">
110
+ <span class="tl-text-field__helper">Include country code</span>
111
+ </div>
112
+ </div>
113
+
114
+ <!-- Error state -->
115
+ <div class="tl-text-field tl-text-field--lg tl-text-field--error">
116
+ <label class="tl-text-field__label" for="req">Required field</label>
117
+ <input class="tl-text-field__input" id="req" type="text" placeholder=" " />
118
+ <div class="tl-text-field__bottom">
119
+ <span class="tl-text-field__helper">This field is required</span>
120
+ </div>
121
+ </div>
122
+
123
+ <!-- With prefix/suffix icons -->
124
+ <div class="tl-text-field tl-text-field--lg">
125
+ <label class="tl-text-field__label" for="search">Search</label>
126
+ <span class="tl-text-field__prefix--icon tl-icon tl-icon--search"></span>
127
+ <input
128
+ class="tl-text-field__input"
129
+ id="search"
130
+ type="text"
131
+ placeholder="Search..."
132
+ />
133
+ </div>
134
+
135
+ <!-- With character counter -->
136
+ <div class="tl-text-field tl-text-field--lg">
137
+ <label class="tl-text-field__label" for="bio">Bio</label>
138
+ <input
139
+ class="tl-text-field__input"
140
+ id="bio"
141
+ type="text"
142
+ placeholder=" "
143
+ maxlength="100"
144
+ />
145
+ <div class="tl-text-field__bottom">
146
+ <span class="tl-text-field__helper">Short description</span>
147
+ <span class="tl-text-field__charcounter">
148
+ 0<span class="tl-text-field__charcounter-divider">/</span>100
149
+ </span>
150
+ </div>
151
+ </div>
152
+
153
+ <!-- Disabled -->
154
+ <div class="tl-text-field tl-text-field--lg">
155
+ <label class="tl-text-field__label" for="dis">Disabled</label>
156
+ <input
157
+ class="tl-text-field__input"
158
+ id="dis"
159
+ type="text"
160
+ disabled
161
+ placeholder="Cannot edit"
162
+ />
163
+ </div>
164
+ ```
165
+
166
+ **IMPORTANT for label-inside**: The `placeholder` attribute MUST be set (even to `" "` a space) for the floating label animation to work.
167
+
168
+ ---
169
+
170
+ ## Textarea
171
+
172
+ **Classes**: `tl-textarea`
173
+ **Variants**: `tl-textarea--primary`, `tl-textarea--secondary`, `tl-textarea--label-inside`
174
+ **States**: `tl-textarea--error`, `tl-textarea--success`
175
+
176
+ ```html
177
+ <div class="tl-textarea">
178
+ <label class="tl-textarea__label" for="msg">Message</label>
179
+ <textarea
180
+ class="tl-textarea__input"
181
+ id="msg"
182
+ rows="4"
183
+ placeholder="Type here..."
184
+ ></textarea>
185
+ <div class="tl-textarea__bottom">
186
+ <span class="tl-textarea__helper">Max 500 characters</span>
187
+ <span class="tl-textarea__charcounter">
188
+ 0<span class="tl-textarea__charcounter-divider">/</span>500
189
+ </span>
190
+ </div>
191
+ </div>
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Checkbox
197
+
198
+ **Classes**: `tl-checkbox`
199
+
200
+ ```html
201
+ <label class="tl-checkbox">
202
+ <input class="tl-checkbox__input" type="checkbox" />
203
+ <span class="tl-checkbox__label">Accept terms</span>
204
+ </label>
205
+
206
+ <!-- Checked -->
207
+ <label class="tl-checkbox">
208
+ <input class="tl-checkbox__input" type="checkbox" checked />
209
+ <span class="tl-checkbox__label">Selected</span>
210
+ </label>
211
+
212
+ <!-- Disabled -->
213
+ <label class="tl-checkbox">
214
+ <input class="tl-checkbox__input" type="checkbox" disabled />
215
+ <span class="tl-checkbox__label">Disabled</span>
216
+ </label>
217
+
218
+ <!-- Indeterminate (add class manually) -->
219
+ <label class="tl-checkbox">
220
+ <input
221
+ class="tl-checkbox__input tl-checkbox__input--indeterminate"
222
+ type="checkbox"
223
+ />
224
+ <span class="tl-checkbox__label">Indeterminate</span>
225
+ </label>
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Radio Button
231
+
232
+ **Classes**: `tl-radio-button`
233
+
234
+ ```html
235
+ <label class="tl-radio-button">
236
+ <input class="tl-radio-button__input" type="radio" name="group1" value="a" />
237
+ <span class="tl-radio-button__label">Option A</span>
238
+ </label>
239
+
240
+ <label class="tl-radio-button">
241
+ <input class="tl-radio-button__input" type="radio" name="group1" value="b" />
242
+ <span class="tl-radio-button__label">Option B</span>
243
+ </label>
244
+
245
+ <label class="tl-radio-button">
246
+ <input
247
+ class="tl-radio-button__input"
248
+ type="radio"
249
+ name="group1"
250
+ value="c"
251
+ disabled
252
+ />
253
+ <span class="tl-radio-button__label">Disabled</span>
254
+ </label>
255
+ ```
256
+
257
+ ---
258
+
259
+ ## Toggle / Switch
260
+
261
+ **Classes**: `tl-toggle`
262
+ **Sizes**: default (44×24px), `tl-toggle__input--sm` (28×16px)
263
+
264
+ ```html
265
+ <div class="tl-toggle">
266
+ <span class="tl-toggle__headline">Dark mode</span>
267
+ <label>
268
+ <input class="tl-toggle__input" type="checkbox" />
269
+ <span class="tl-toggle__label">Enable</span>
270
+ </label>
271
+ </div>
272
+
273
+ <!-- Small toggle -->
274
+ <div class="tl-toggle">
275
+ <label>
276
+ <input
277
+ class="tl-toggle__input tl-toggle__input--sm"
278
+ type="checkbox"
279
+ checked
280
+ />
281
+ <span class="tl-toggle__label">On</span>
282
+ </label>
283
+ </div>
284
+ ```
285
+
286
+ ---
287
+
288
+ ## Dropdown / Select
289
+
290
+ **Classes**: `tl-dropdown`
291
+ **Sizes**: default (56px), `tl-dropdown--md` (48px), `tl-dropdown--sm` (40px)
292
+ **Variants**: `tl-dropdown--primary`, `tl-dropdown--secondary`, `tl-dropdown--label-inside`
293
+ **States**: `tl-dropdown--error`
294
+
295
+ ### Native Select
296
+
297
+ ```html
298
+ <div class="tl-dropdown tl-dropdown--lg">
299
+ <label class="tl-dropdown__label" for="country">Country</label>
300
+ <select class="tl-dropdown__select" id="country">
301
+ <option value="">Select a country</option>
302
+ <option value="se">Sweden</option>
303
+ <option value="no">Norway</option>
304
+ <option value="dk">Denmark</option>
305
+ </select>
306
+ </div>
307
+ ```
308
+
309
+ ### Custom Dropdown (requires JS for open/close)
310
+
311
+ ```html
312
+ <div class="tl-dropdown tl-dropdown--lg">
313
+ <label class="tl-dropdown__label">Status</label>
314
+ <button
315
+ class="tl-dropdown__button"
316
+ aria-expanded="false"
317
+ aria-haspopup="listbox"
318
+ >
319
+ <span class="tl-dropdown__text" data-placeholder="Select status"></span>
320
+ </button>
321
+ <ul class="tl-dropdown__list" role="listbox">
322
+ <li class="tl-dropdown__option" role="option" tabindex="0">Active</li>
323
+ <li class="tl-dropdown__option" role="option" tabindex="0">Inactive</li>
324
+ <li class="tl-dropdown__option tl-dropdown__option--disabled" role="option">
325
+ Archived
326
+ </li>
327
+ </ul>
328
+ </div>
329
+ ```
330
+
331
+ ### Filterable Dropdown
332
+
333
+ ```html
334
+ <div class="tl-dropdown tl-dropdown--lg">
335
+ <label class="tl-dropdown__label">Search items</label>
336
+ <div class="tl-dropdown__input-wrapper">
337
+ <input
338
+ class="tl-dropdown__input"
339
+ type="text"
340
+ placeholder="Type to filter..."
341
+ aria-expanded="false"
342
+ role="combobox"
343
+ autocomplete="off"
344
+ />
345
+ <button class="tl-dropdown__input-clear" aria-label="Clear">×</button>
346
+ </div>
347
+ <ul class="tl-dropdown__list" role="listbox">
348
+ <li class="tl-dropdown__option" role="option" tabindex="0">Item 1</li>
349
+ <li class="tl-dropdown__option" role="option" tabindex="0">Item 2</li>
350
+ </ul>
351
+ </div>
352
+ ```
353
+
354
+ ---
355
+
356
+ ## Datetime / Date Picker
357
+
358
+ **Classes**: `tl-datetime`
359
+ **Sizes**: default lg (56px), `tl-datetime--md` (48px), `tl-datetime--sm` (40px)
360
+ **Variants**: `tl-datetime--primary`, `tl-datetime--secondary`, `tl-datetime--label-inside`
361
+ **States**: `tl-datetime--error`
362
+
363
+ ```html
364
+ <div class="tl-datetime tl-datetime--label-inside">
365
+ <div class="tl-datetime__wrapper">
366
+ <span class="tl-datetime__label-inside">Date</span>
367
+ <input class="tl-datetime__input" type="date" />
368
+ </div>
369
+ </div>
370
+
371
+ <!-- With external label -->
372
+ <div class="tl-datetime">
373
+ <label class="tl-datetime__label" for="start">Start date</label>
374
+ <div class="tl-datetime__wrapper">
375
+ <input class="tl-datetime__input" id="start" type="date" />
376
+ </div>
377
+ </div>
378
+
379
+ <!-- Time picker -->
380
+ <div class="tl-datetime">
381
+ <label class="tl-datetime__label" for="time">Time</label>
382
+ <div class="tl-datetime__wrapper">
383
+ <input class="tl-datetime__input" id="time" type="time" />
384
+ </div>
385
+ </div>
386
+
387
+ <!-- Error state -->
388
+ <div class="tl-datetime tl-datetime--error">
389
+ <label class="tl-datetime__label" for="due">Due date</label>
390
+ <div class="tl-datetime__wrapper">
391
+ <input class="tl-datetime__input" id="due" type="date" />
392
+ </div>
393
+ <span class="tl-datetime__helper">Date cannot be in the past</span>
394
+ </div>
395
+ ```