@elsapiens/styles 0.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.
@@ -0,0 +1,1072 @@
1
+ /* @elsapiens/sdk Semantic Component Classes */
2
+ /* Requires @elsapiens/styles/variables to be imported first */
3
+
4
+ /* ============================================
5
+ Form Element Semantic Classes
6
+ ============================================ */
7
+
8
+ /* Field Container - wrapper for form fields */
9
+ .el-field-container {
10
+ width: 100%;
11
+ }
12
+
13
+ /* Base Input Styles */
14
+ .el-input {
15
+ width: 100%;
16
+ border-radius: var(--radius-md);
17
+ border: 1px solid hsl(var(--input));
18
+ background-color: hsl(var(--background));
19
+ color: hsl(var(--foreground));
20
+ line-height: var(--el-line-height);
21
+ transition-property: border-color, box-shadow;
22
+ transition-duration: var(--transition-fast);
23
+ }
24
+
25
+ .el-input:focus {
26
+ outline: none;
27
+ border-color: hsl(var(--primary));
28
+ box-shadow: 0 0 0 1px hsl(var(--primary));
29
+ }
30
+
31
+ .el-input:disabled {
32
+ opacity: 0.5;
33
+ cursor: not-allowed;
34
+ }
35
+
36
+ .el-input::placeholder {
37
+ color: hsl(var(--muted-foreground));
38
+ }
39
+
40
+ /* Input Size Variants - margin/width handled by cascaded styles from el-p-* containers */
41
+ .el-input-sm {
42
+ padding: var(--el-spacing-py-sm) var(--el-spacing-px-sm);
43
+ font-size: var(--el-font-size-sm);
44
+ min-height: var(--el-input-height-sm);
45
+ }
46
+
47
+ .el-input-md {
48
+ padding: var(--el-spacing-py-md) var(--el-spacing-px-md);
49
+ font-size: var(--el-font-size-md);
50
+ min-height: var(--el-input-height-md);
51
+ }
52
+
53
+ .el-input-lg {
54
+ padding: var(--el-spacing-py-lg) var(--el-spacing-px-lg);
55
+ font-size: var(--el-font-size-lg);
56
+ min-height: var(--el-input-height-lg);
57
+ }
58
+
59
+ /* Validation States */
60
+ .el-input-valid {
61
+ border-color: hsl(var(--success));
62
+ }
63
+
64
+ .el-input-valid:focus {
65
+ border-color: hsl(var(--success));
66
+ box-shadow: 0 0 0 1px hsl(var(--success));
67
+ }
68
+
69
+ .el-input-invalid {
70
+ border-color: hsl(var(--destructive));
71
+ }
72
+
73
+ .el-input-invalid:focus {
74
+ border-color: hsl(var(--destructive));
75
+ box-shadow: 0 0 0 1px hsl(var(--destructive));
76
+ }
77
+
78
+ /* Textarea */
79
+ .el-textarea {
80
+ resize: none;
81
+ }
82
+
83
+ .el-textarea-sm {
84
+ min-height: var(--el-textarea-min-height-sm);
85
+ }
86
+
87
+ .el-textarea-md {
88
+ min-height: var(--el-textarea-min-height-md);
89
+ }
90
+
91
+ .el-textarea-lg {
92
+ min-height: var(--el-textarea-min-height-lg);
93
+ }
94
+
95
+ .el-textarea-auto-resize {
96
+ min-height: 0;
97
+ }
98
+
99
+ /* Select */
100
+ .el-select {
101
+ appearance: none;
102
+ padding-inline-end: 2.5rem;
103
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
104
+ background-position: right 0.75rem center;
105
+ background-repeat: no-repeat;
106
+ background-size: 1rem 1rem;
107
+ }
108
+
109
+ /* Select size overrides - use line-height for vertical centering */
110
+ .el-select.el-input-sm {
111
+ padding-block: 0;
112
+ height: var(--el-input-height-sm);
113
+ line-height: calc(var(--el-input-height-sm) - 2px);
114
+ }
115
+
116
+ .el-select.el-input-md {
117
+ padding-block: 0;
118
+ height: var(--el-input-height-md);
119
+ line-height: calc(var(--el-input-height-md) - 2px);
120
+ }
121
+
122
+ .el-select.el-input-lg {
123
+ padding-block: 0;
124
+ height: var(--el-input-height-lg);
125
+ line-height: calc(var(--el-input-height-lg) - 2px);
126
+ }
127
+
128
+ /* RTL: Flip select arrow position */
129
+ [dir="rtl"] .el-select {
130
+ background-position: left 0.75rem center;
131
+ padding-inline-start: 2.5rem;
132
+ padding-inline-end: var(--el-spacing-px-md);
133
+ }
134
+
135
+ /* Searchable Select / MultiSelect Button */
136
+ .el-select-button {
137
+ display: flex;
138
+ align-items: center;
139
+ justify-content: space-between;
140
+ gap: var(--el-gap-md);
141
+ text-align: start;
142
+ min-height: var(--el-input-height-md);
143
+ }
144
+
145
+ /* Checkbox & Radio Container */
146
+ .el-check-container {
147
+ display: flex;
148
+ align-items: center;
149
+ gap: var(--el-gap-lg);
150
+ cursor: pointer;
151
+ border-radius: var(--radius-md);
152
+ transition-property: background-color;
153
+ transition-duration: var(--transition-fast);
154
+ }
155
+
156
+ .el-check-container:has(input:disabled) {
157
+ cursor: not-allowed;
158
+ opacity: 0.5;
159
+ }
160
+
161
+ .el-check-container-sm {
162
+ min-height: var(--el-input-height-sm);
163
+ padding: var(--el-spacing-py-sm) 0;
164
+ }
165
+
166
+ .el-check-container-md {
167
+ min-height: var(--el-input-height-md);
168
+ padding: var(--el-spacing-py-md) 0;
169
+ }
170
+
171
+ .el-check-container-lg {
172
+ min-height: var(--el-input-height-lg);
173
+ padding: var(--el-spacing-py-lg) 0;
174
+ }
175
+
176
+ /* Checkbox */
177
+ .el-checkbox {
178
+ flex-shrink: 0;
179
+ border: 2px solid hsl(var(--input));
180
+ border-radius: var(--radius-sm);
181
+ display: flex;
182
+ align-items: center;
183
+ justify-content: center;
184
+ background-color: hsl(var(--background));
185
+ transition-property: border-color, background-color;
186
+ transition-duration: var(--transition-fast);
187
+ }
188
+
189
+ .el-checkbox-sm {
190
+ width: var(--el-checkbox-size-sm);
191
+ height: var(--el-checkbox-size-sm);
192
+ }
193
+
194
+ .el-checkbox-md {
195
+ width: var(--el-checkbox-size-md);
196
+ height: var(--el-checkbox-size-md);
197
+ }
198
+
199
+ .el-checkbox-lg {
200
+ width: var(--el-checkbox-size-lg);
201
+ height: var(--el-checkbox-size-lg);
202
+ }
203
+
204
+ /* Radio */
205
+ .el-radio {
206
+ flex-shrink: 0;
207
+ border: 2px solid hsl(var(--input));
208
+ border-radius: var(--radius-full);
209
+ display: flex;
210
+ align-items: center;
211
+ justify-content: center;
212
+ background-color: hsl(var(--background));
213
+ transition-property: border-color, background-color;
214
+ transition-duration: var(--transition-fast);
215
+ }
216
+
217
+ .el-radio-sm {
218
+ width: var(--el-checkbox-size-sm);
219
+ height: var(--el-checkbox-size-sm);
220
+ }
221
+
222
+ .el-radio-md {
223
+ width: var(--el-checkbox-size-md);
224
+ height: var(--el-checkbox-size-md);
225
+ }
226
+
227
+ .el-radio-lg {
228
+ width: var(--el-checkbox-size-lg);
229
+ height: var(--el-checkbox-size-lg);
230
+ }
231
+
232
+ /* Check/Radio label text */
233
+ .el-check-label-sm {
234
+ font-size: var(--el-font-size-sm);
235
+ }
236
+
237
+ .el-check-label-md {
238
+ font-size: var(--el-font-size-md);
239
+ }
240
+
241
+ .el-check-label-lg {
242
+ font-size: var(--el-font-size-lg);
243
+ }
244
+
245
+ /* Button Base */
246
+ .el-btn {
247
+ display: inline-flex;
248
+ align-items: center;
249
+ justify-content: center;
250
+ gap: var(--el-gap-md);
251
+ border-radius: var(--radius-md);
252
+ font-weight: var(--el-font-weight-medium);
253
+ transition-property: background-color, border-color, color, box-shadow;
254
+ transition-duration: var(--transition-fast);
255
+ cursor: pointer;
256
+ white-space: nowrap;
257
+ }
258
+
259
+ .el-btn:focus-visible {
260
+ outline: none;
261
+ box-shadow: 0 0 0 2px hsl(var(--background)), 0 0 0 4px hsl(var(--ring));
262
+ }
263
+
264
+ .el-btn:disabled {
265
+ opacity: 0.5;
266
+ cursor: not-allowed;
267
+ }
268
+
269
+ /* Button Sizes - vertical padding and height only (horizontal padding/margin handled by .el-btn) */
270
+ .el-btn-sm {
271
+ padding-block: var(--el-btn-py-sm);
272
+ font-size: var(--el-font-size-sm);
273
+ height: var(--el-input-height-sm);
274
+ }
275
+
276
+ .el-btn-md {
277
+ padding-block: var(--el-btn-py-md);
278
+ font-size: var(--el-font-size-md);
279
+ height: var(--el-input-height-md);
280
+ }
281
+
282
+ .el-btn-lg {
283
+ padding-block: var(--el-btn-py-lg);
284
+ font-size: var(--el-font-size-lg);
285
+ height: var(--el-input-height-lg);
286
+ }
287
+
288
+ /* Button Variants */
289
+ .el-btn-primary {
290
+ background-color: hsl(var(--primary));
291
+ color: hsl(var(--primary-foreground));
292
+ border: 1px solid hsl(var(--primary));
293
+ }
294
+
295
+ .el-btn-primary:hover:not(:disabled) {
296
+ background-color: hsl(var(--primary-700));
297
+ border-color: hsl(var(--primary-700));
298
+ }
299
+
300
+ .el-btn-secondary {
301
+ background-color: hsl(var(--secondary));
302
+ color: hsl(var(--secondary-foreground));
303
+ border: 1px solid hsl(var(--border));
304
+ }
305
+
306
+ .el-btn-secondary:hover:not(:disabled) {
307
+ background-color: hsl(var(--muted));
308
+ }
309
+
310
+ .el-btn-outline {
311
+ background-color: transparent;
312
+ color: hsl(var(--foreground));
313
+ border: 1px solid hsl(var(--border));
314
+ }
315
+
316
+ .el-btn-outline:hover:not(:disabled) {
317
+ background-color: hsl(var(--secondary));
318
+ }
319
+
320
+ .el-btn-ghost {
321
+ background-color: transparent;
322
+ color: hsl(var(--foreground));
323
+ border: 1px solid transparent;
324
+ }
325
+
326
+ .el-btn-ghost:hover:not(:disabled) {
327
+ background-color: hsl(var(--secondary));
328
+ }
329
+
330
+ .el-btn-destructive {
331
+ background-color: hsl(var(--destructive));
332
+ color: hsl(var(--destructive-foreground));
333
+ border: 1px solid hsl(var(--destructive));
334
+ }
335
+
336
+ .el-btn-destructive:hover:not(:disabled) {
337
+ opacity: 0.9;
338
+ }
339
+
340
+ /* Form Message Area */
341
+ .el-field-message {
342
+ min-height: var(--el-message-min-height);
343
+ margin-top: var(--el-gap-sm);
344
+ font-size: var(--el-message-font-size);
345
+ white-space: nowrap;
346
+ overflow: hidden;
347
+ text-overflow: ellipsis;
348
+ }
349
+
350
+ .el-field-error {
351
+ color: hsl(var(--destructive));
352
+ white-space: nowrap;
353
+ overflow: hidden;
354
+ text-overflow: ellipsis;
355
+ }
356
+
357
+ .el-field-helper {
358
+ color: hsl(var(--muted-foreground));
359
+ white-space: nowrap;
360
+ overflow: hidden;
361
+ text-overflow: ellipsis;
362
+ }
363
+
364
+ /* Form Field Label */
365
+ .el-field-label {
366
+ display: block;
367
+ font-size: var(--el-font-size-sm);
368
+ font-weight: var(--el-font-weight-medium);
369
+ color: hsl(var(--foreground));
370
+ margin-bottom: var(--el-gap-sm);
371
+ }
372
+
373
+ .el-field-label-required::after {
374
+ content: " *";
375
+ color: hsl(var(--destructive));
376
+ }
377
+
378
+ /* Numeric Input */
379
+ .el-numeric-input {
380
+ text-align: end;
381
+ font-family: ui-monospace, monospace;
382
+ }
383
+
384
+ /* Input with Prefix/Suffix Icons - using logical properties for RTL support */
385
+ .el-input-prefix-icon {
386
+ position: absolute;
387
+ inset-block: 0;
388
+ inset-inline-start: 0;
389
+ inset-inline-end: auto;
390
+ display: flex;
391
+ align-items: center;
392
+ padding-inline-start: 0;
393
+ pointer-events: none;
394
+ color: hsl(var(--muted-foreground));
395
+ }
396
+
397
+ .el-input-suffix-icon {
398
+ position: absolute;
399
+ inset-block: 0;
400
+ inset-inline-start: auto;
401
+ inset-inline-end: 0;
402
+ display: flex;
403
+ align-items: center;
404
+ padding-inline-end: var(--el-spacing-px-md);
405
+ }
406
+
407
+ /* Size variants for prefix/suffix */
408
+ .el-input-prefix-icon-sm {
409
+ padding-inline-start: 0;
410
+ }
411
+
412
+ .el-input-prefix-icon-lg {
413
+ padding-inline-start: 0;
414
+ }
415
+
416
+ .el-input-suffix-icon-sm {
417
+ padding-inline-end: var(--el-spacing-px-sm);
418
+ }
419
+
420
+ .el-input-suffix-icon-lg {
421
+ padding-inline-end: var(--el-spacing-px-lg);
422
+ }
423
+
424
+ /* Picker suffix icon - positioned at the extended edge of inputs with negative margins */
425
+ .el-picker-suffix-icon {
426
+ position: absolute;
427
+ inset-block: 0;
428
+ inset-inline-start: auto;
429
+ inset-inline-end: calc(var(--el-spacing-px-md) * -1);
430
+ display: flex;
431
+ align-items: center;
432
+ padding-inline-end: var(--el-spacing-px-md);
433
+ }
434
+
435
+ .el-picker-suffix-icon-sm {
436
+ inset-inline-end: calc(var(--el-spacing-px-sm) * -1);
437
+ padding-inline-end: var(--el-spacing-px-sm);
438
+ }
439
+
440
+ .el-picker-suffix-icon-lg {
441
+ inset-inline-end: calc(var(--el-spacing-px-lg) * -1);
442
+ padding-inline-end: var(--el-spacing-px-lg);
443
+ }
444
+
445
+ /* Input padding adjustments when using prefix/suffix icons */
446
+ .el-input-has-prefix {
447
+ padding-inline-start: calc(var(--el-spacing-px-md) + 1.5rem);
448
+ }
449
+
450
+ .el-input-has-prefix-sm {
451
+ padding-inline-start: calc(var(--el-spacing-px-sm) + 1.25rem);
452
+ }
453
+
454
+ .el-input-has-prefix-lg {
455
+ padding-inline-start: calc(var(--el-spacing-px-lg) + 1.75rem);
456
+ }
457
+
458
+ .el-input-has-prefix-narrow {
459
+ padding-inline-start: calc(var(--el-spacing-px-md) + 1rem);
460
+ }
461
+
462
+ .el-input-has-suffix {
463
+ padding-inline-end: calc(var(--el-spacing-px-md) + 1.25rem);
464
+ }
465
+
466
+ .el-input-has-suffix-sm {
467
+ padding-inline-end: calc(var(--el-spacing-px-sm) + 1rem);
468
+ }
469
+
470
+ .el-input-has-suffix-lg {
471
+ padding-inline-end: calc(var(--el-spacing-px-lg) + 1.5rem);
472
+ }
473
+
474
+ /* ============================================
475
+ Table Alignment Styles
476
+ ============================================ */
477
+
478
+ /* Table spacer width variable */
479
+ /* Table spacer width - set by container (el-p-* or Card) */
480
+ /* Default is 0 when not inside a padded container */
481
+
482
+ /* Aligned table wrapper */
483
+ .el-table-aligned {
484
+ /* Container styles if needed */
485
+ }
486
+
487
+ /* Base table styles */
488
+ .el-table {
489
+ border-collapse: collapse;
490
+ font-size: var(--el-font-size-md);
491
+ }
492
+
493
+ /* Spacer columns - invisible columns on both sides */
494
+ .el-table-spacer {
495
+ width: 0;
496
+ min-width: var(--el-table-spacer-width);
497
+ max-width: var(--el-table-spacer-width);
498
+ padding: 0 !important;
499
+ margin: 0;
500
+ border: none;
501
+ box-sizing: border-box;
502
+ }
503
+
504
+ /* First real column (after start spacer) */
505
+ .el-table-header-first,
506
+ .el-table-cell-first {
507
+ padding-inline-start: 0;
508
+ }
509
+
510
+ /* Last real column (before end spacer) */
511
+ .el-table-header-last,
512
+ .el-table-cell-last {
513
+ padding-inline-end: 0;
514
+ }
515
+
516
+ /* Hover state for spacer columns */
517
+ .el-table-aligned tbody tr:hover .el-table-spacer {
518
+ background-color: hsl(var(--muted) / 0.5);
519
+ }
520
+
521
+ /* ============================================
522
+ Table in Card - Negative Margin
523
+ ============================================ */
524
+
525
+ /*
526
+ * Card padding now uses adaptive layout gap variables:
527
+ * - sm: el-p-md = var(--el-layout-gap-md)
528
+ * - md: el-p-lg = var(--el-layout-gap-lg) (default)
529
+ * - lg: el-p-xl = var(--el-layout-gap-xl)
530
+ *
531
+ * The --el-card-padding variable defaults to the layout gap lg value,
532
+ * and is overridden by the padding size variant classes below.
533
+ */
534
+
535
+ /* Base table in card - horizontal margins only */
536
+ .el-table-in-card {
537
+ margin-left: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
538
+ margin-right: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
539
+ width: calc(100% + var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * 2);
540
+ }
541
+
542
+ /* Table as first element in card - add negative top margin */
543
+ .el-table-in-card-first {
544
+ margin-left: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
545
+ margin-right: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
546
+ margin-top: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
547
+ width: calc(100% + var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * 2);
548
+ }
549
+
550
+ /* Table as last element in card - add negative bottom margin */
551
+ .el-table-in-card-last {
552
+ margin-left: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
553
+ margin-right: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
554
+ margin-bottom: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
555
+ width: calc(100% + var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * 2);
556
+ }
557
+
558
+ /* Table as only element or spanning full card - all margins */
559
+ .el-table-in-card-full {
560
+ margin: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
561
+ width: calc(100% + var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * 2);
562
+ }
563
+
564
+ /* Card padding size variants - use adaptive layout gap variables */
565
+ .el-table-in-card-padding-sm {
566
+ --el-card-padding: var(--el-layout-gap-md, 0.75rem);
567
+ }
568
+
569
+ .el-table-in-card-padding-lg {
570
+ --el-card-padding: var(--el-layout-gap-xl, 1.5rem);
571
+ }
572
+
573
+ /* ============================================
574
+ Layout Gap Utilities
575
+ These adapt to the spacing mode (compact/normal/spacious)
576
+ ============================================ */
577
+
578
+ /* Gap utilities - for flex/grid containers */
579
+ .el-gap-0 { gap: 0; }
580
+ .el-gap-px { gap: 1px; }
581
+ .el-gap-xs { gap: var(--el-layout-gap-xs); }
582
+ .el-gap-sm { gap: var(--el-layout-gap-sm); }
583
+ .el-gap-md { gap: var(--el-layout-gap-md); }
584
+ .el-gap-lg { gap: var(--el-layout-gap-lg); }
585
+ .el-gap-xl { gap: var(--el-layout-gap-xl); }
586
+ .el-gap-2xl { gap: var(--el-layout-gap-2xl); }
587
+
588
+ /* Semantic gap utilities */
589
+ .el-gap-section { gap: var(--el-section-gap); }
590
+ .el-gap-content { gap: var(--el-content-gap); }
591
+ .el-gap-inline { gap: var(--el-inline-gap); }
592
+
593
+ /* Row gap (vertical) utilities */
594
+ .el-gap-y-0 { row-gap: 0; }
595
+ .el-gap-y-xs { row-gap: var(--el-layout-gap-xs); }
596
+ .el-gap-y-sm { row-gap: var(--el-layout-gap-sm); }
597
+ .el-gap-y-md { row-gap: var(--el-layout-gap-md); }
598
+ .el-gap-y-lg { row-gap: var(--el-layout-gap-lg); }
599
+ .el-gap-y-xl { row-gap: var(--el-layout-gap-xl); }
600
+
601
+ /* Column gap (horizontal) utilities */
602
+ .el-gap-x-0 { column-gap: 0; }
603
+ .el-gap-x-xs { column-gap: var(--el-layout-gap-xs); }
604
+ .el-gap-x-sm { column-gap: var(--el-layout-gap-sm); }
605
+ .el-gap-x-md { column-gap: var(--el-layout-gap-md); }
606
+ .el-gap-x-lg { column-gap: var(--el-layout-gap-lg); }
607
+ .el-gap-x-xl { column-gap: var(--el-layout-gap-xl); }
608
+
609
+ /* ============================================
610
+ Control Gap Utilities
611
+ For button groups, form field rows, inline controls
612
+ ============================================ */
613
+ .el-gap-control-xs { gap: var(--el-control-gap-xs); }
614
+ .el-gap-control-sm { gap: var(--el-control-gap-sm); }
615
+ .el-gap-control-md { gap: var(--el-control-gap-md); }
616
+ .el-gap-control-lg { gap: var(--el-control-gap-lg); }
617
+ .el-gap-control-xl { gap: var(--el-control-gap-xl); }
618
+
619
+ /* Padding utilities - defined below in the Spacing Utilities section */
620
+
621
+ /* Field grid gap - uses 1.5x container padding */
622
+ .el-gap-field { gap: calc(var(--el-container-px, var(--el-spacing-px-md)) * 1.5); }
623
+
624
+ /* Buttons and inputs inside el-gap-field inside padding containers - extend to visual edge */
625
+ [class*="el-p-"] .el-gap-field .el-btn,
626
+ [class*="el-p-"] .el-gap-field .el-input,
627
+ [class*="el-px-"] .el-gap-field .el-btn,
628
+ [class*="el-px-"] .el-gap-field .el-input {
629
+ padding-inline: calc(var(--el-container-px) * 0.5);
630
+ margin-inline: calc(var(--el-container-px) * -0.5);
631
+ }
632
+
633
+ /* Only inputs need width adjustment to override 100% from .el-input */
634
+ [class*="el-p-"] .el-gap-field .el-input,
635
+ [class*="el-px-"] .el-gap-field .el-input {
636
+ width: calc(100% + var(--el-container-px));
637
+ }
638
+
639
+ /* ============================================
640
+ Dropdown Menu - Portal-based container
641
+ Sets --el-container-px for cascaded button/input styles
642
+ ============================================ */
643
+ .el-dropdown-menu {
644
+ padding: var(--el-layout-gap-xs);
645
+ --el-container-px: var(--el-layout-gap-xs);
646
+ }
647
+
648
+ /* Buttons inside dropdown menu get cascaded styles */
649
+ .el-dropdown-menu .el-btn {
650
+ padding-inline: calc(var(--el-container-px) * 0.5);
651
+ margin-inline: calc(var(--el-container-px) * -0.5);
652
+ }
653
+
654
+ /* ============================================
655
+ Full-width Components - Cascaded Styles
656
+ These components extend edge-to-edge within padding containers
657
+ ============================================ */
658
+
659
+ /* Full-width components inside padding containers - extend to visual edge */
660
+ [class*="el-p-"] .el-multibutton-switch,
661
+ [class*="el-p-"] .el-tags-input,
662
+ [class*="el-p-"] .el-alert,
663
+ [class*="el-p-"] .el-tabs-list,
664
+ [class*="el-p-"] .el-filter-bar,
665
+ [class*="el-p-"] .el-info,
666
+ [class*="el-px-"] .el-multibutton-switch,
667
+ [class*="el-px-"] .el-tags-input,
668
+ [class*="el-px-"] .el-alert,
669
+ [class*="el-px-"] .el-tabs-list,
670
+ [class*="el-px-"] .el-filter-bar,
671
+ [class*="el-px-"] .el-info {
672
+ margin-inline: calc(var(--el-container-px) * -0.5);
673
+ padding-inline: calc(var(--el-container-px) * 0.5);
674
+ width: calc(100% + var(--el-container-px));
675
+ }
676
+
677
+ /* Components with visible borders - extend edge-to-edge, inner elements handle padding */
678
+ /* Note: .el-card is excluded here - nested cards are handled separately below */
679
+ [class*="el-p-"] .el-accordion,
680
+ [class*="el-p-"] .el-collapsible,
681
+ [class*="el-p-"] .el-list,
682
+ [class*="el-p-"] .el-file-upload,
683
+ [class*="el-p-"] .el-image-upload,
684
+ [class*="el-p-"] .el-skeleton-card,
685
+ [class*="el-p-"] .el-markdown-editor,
686
+ [class*="el-p-"] .el-richtext-editor,
687
+ [class*="el-px-"] .el-accordion,
688
+ [class*="el-px-"] .el-collapsible,
689
+ [class*="el-px-"] .el-list,
690
+ [class*="el-px-"] .el-file-upload,
691
+ [class*="el-px-"] .el-image-upload,
692
+ [class*="el-px-"] .el-skeleton-card,
693
+ [class*="el-px-"] .el-markdown-editor,
694
+ [class*="el-px-"] .el-richtext-editor {
695
+ margin-inline: calc(var(--el-container-px) * -0.5);
696
+ width: calc(100% + var(--el-container-px));
697
+ }
698
+
699
+ /* Nested cards only - cards inside other cards with padding extend edge-to-edge */
700
+ .el-card [class*="el-p-"] .el-card,
701
+ .el-card [class*="el-px-"] .el-card {
702
+ margin-inline: calc(var(--el-container-px) * -0.5);
703
+ width: calc(100% + var(--el-container-px));
704
+ }
705
+
706
+ /* Editor inner elements - default padding when not inside padding containers */
707
+ .el-editor-toolbar {
708
+ padding-inline: var(--el-spacing-px-md);
709
+ padding-block: var(--el-spacing-py-sm);
710
+ }
711
+
712
+ .el-editor-content {
713
+ padding-inline: var(--el-spacing-px-md);
714
+ padding-block: var(--el-spacing-py-md);
715
+ }
716
+
717
+ /* Editor inner elements - cascaded padding when inside padding containers */
718
+ [class*="el-p-"] .el-markdown-editor .el-editor-toolbar,
719
+ [class*="el-p-"] .el-markdown-editor .el-editor-content,
720
+ [class*="el-p-"] .el-richtext-editor .el-editor-toolbar,
721
+ [class*="el-p-"] .el-richtext-editor .el-editor-content,
722
+ [class*="el-px-"] .el-markdown-editor .el-editor-toolbar,
723
+ [class*="el-px-"] .el-markdown-editor .el-editor-content,
724
+ [class*="el-px-"] .el-richtext-editor .el-editor-toolbar,
725
+ [class*="el-px-"] .el-richtext-editor .el-editor-content {
726
+ padding-inline: calc(var(--el-container-px) * 0.5);
727
+ }
728
+
729
+ /* Accordion inner elements - default padding when not inside padding containers */
730
+ .el-accordion-trigger {
731
+ padding-inline: var(--el-spacing-px-md);
732
+ padding-block: var(--el-layout-gap-md);
733
+ }
734
+
735
+ .el-accordion-content {
736
+ padding-inline: var(--el-spacing-px-md);
737
+ padding-block: 0 var(--el-layout-gap-md);
738
+ }
739
+
740
+ /* Accordion inner elements - cascaded padding when inside padding containers */
741
+ [class*="el-p-"] .el-accordion .el-accordion-trigger,
742
+ [class*="el-p-"] .el-accordion .el-accordion-content,
743
+ [class*="el-px-"] .el-accordion .el-accordion-trigger,
744
+ [class*="el-px-"] .el-accordion .el-accordion-content {
745
+ padding-inline: calc(var(--el-container-px) * 0.5);
746
+ }
747
+
748
+ /* Collapsible inner elements - default padding when not inside padding containers */
749
+ .el-collapsible-trigger {
750
+ display: flex;
751
+ width: 100%;
752
+ align-items: center;
753
+ justify-content: space-between;
754
+ text-align: start;
755
+ padding-inline: var(--el-spacing-px-md);
756
+ }
757
+
758
+ .el-collapsible-content {
759
+ display: block;
760
+ width: 100%;
761
+ padding-inline: var(--el-spacing-px-md);
762
+ }
763
+
764
+ /* Collapsible inner elements - cascaded padding when inside padding containers */
765
+ [class*="el-p-"] .el-collapsible .el-collapsible-trigger,
766
+ [class*="el-p-"] .el-collapsible .el-collapsible-content,
767
+ [class*="el-px-"] .el-collapsible .el-collapsible-trigger,
768
+ [class*="el-px-"] .el-collapsible .el-collapsible-content {
769
+ padding-inline: calc(var(--el-container-px) * 0.5);
770
+ }
771
+
772
+ /* List inner elements - default padding when not inside padding containers */
773
+ .el-list-item {
774
+ padding-inline: var(--el-spacing-px-md);
775
+ }
776
+
777
+ .el-list-subheader {
778
+ padding-inline: var(--el-spacing-px-md);
779
+ }
780
+
781
+ /* List inner elements - cascaded padding when inside padding containers */
782
+ [class*="el-p-"] .el-list .el-list-item,
783
+ [class*="el-p-"] .el-list .el-list-subheader,
784
+ [class*="el-px-"] .el-list .el-list-item,
785
+ [class*="el-px-"] .el-list .el-list-subheader {
786
+ padding-inline: calc(var(--el-container-px) * 0.5);
787
+ }
788
+
789
+ /* FileUpload inner elements - default padding when not inside padding containers */
790
+ .el-file-upload-zone {
791
+ padding: var(--el-layout-gap-xl);
792
+ gap: var(--el-layout-gap-sm);
793
+ }
794
+
795
+ .el-file-upload-item {
796
+ padding: var(--el-layout-gap-sm) var(--el-spacing-px-md);
797
+ gap: var(--el-layout-gap-md);
798
+ }
799
+
800
+ /* FileUpload inner elements - cascaded padding when inside padding containers */
801
+ [class*="el-p-"] .el-file-upload .el-file-upload-zone,
802
+ [class*="el-p-"] .el-file-upload .el-file-upload-item,
803
+ [class*="el-px-"] .el-file-upload .el-file-upload-zone,
804
+ [class*="el-px-"] .el-file-upload .el-file-upload-item {
805
+ padding-inline: calc(var(--el-container-px) * 0.5);
806
+ }
807
+
808
+ /* ImageUpload inner elements - default padding when not inside padding containers */
809
+ .el-image-upload-zone {
810
+ padding: var(--el-layout-gap-md);
811
+ }
812
+
813
+ /* ImageUpload inner elements - cascaded padding when inside padding containers */
814
+ [class*="el-p-"] .el-image-upload .el-image-upload-zone,
815
+ [class*="el-px-"] .el-image-upload .el-image-upload-zone {
816
+ padding-inline: calc(var(--el-container-px) * 0.5);
817
+ }
818
+
819
+ /* SkeletonCard - default padding when not inside padding containers */
820
+ .el-skeleton-card {
821
+ padding: var(--el-spacing-px-md);
822
+ }
823
+
824
+ /* SkeletonCard - cascaded padding when inside padding containers */
825
+ [class*="el-p-"] .el-skeleton-card,
826
+ [class*="el-px-"] .el-skeleton-card {
827
+ padding-inline: calc(var(--el-container-px) * 0.5);
828
+ }
829
+
830
+ /* Summary - default margin when not inside padding containers */
831
+ .el-summary {
832
+ margin-inline: calc(var(--el-spacing-px-md) * -1);
833
+ width: calc(100% + var(--el-spacing-px-md) * 2);
834
+ }
835
+
836
+ /* Summary inner elements - default padding when not inside padding containers */
837
+ .el-summary-item {
838
+ padding-inline: var(--el-spacing-px-md);
839
+ }
840
+
841
+ /* Summary inner elements - cascaded padding when inside padding containers */
842
+ [class*="el-p-"] .el-summary .el-summary-item,
843
+ [class*="el-px-"] .el-summary .el-summary-item {
844
+ padding-inline: calc(var(--el-container-px) * 0.5);
845
+ }
846
+
847
+ /* Textarea - cascaded styles when inside padding containers */
848
+ [class*="el-p-"] .el-textarea,
849
+ [class*="el-px-"] .el-textarea {
850
+ padding-inline: calc(var(--el-container-px) * 0.5);
851
+ margin-inline: calc(var(--el-container-px) * -0.5);
852
+ width: calc(100% + var(--el-container-px));
853
+ }
854
+
855
+ /* ============================================
856
+ Spacing Utilities (padding/margin)
857
+ These adapt to the spacing mode
858
+ ============================================ */
859
+
860
+ /* Defaults (when not inside a padded container) */
861
+ :root {
862
+ --el-table-spacer-width: 0px;
863
+ }
864
+
865
+ /* Padding utilities - set table spacer width and container-px for cascaded styles */
866
+ .el-p-xs {
867
+ padding: var(--el-layout-gap-xs);
868
+ --el-table-spacer-width: var(--el-layout-gap-xs);
869
+ --el-container-px: var(--el-layout-gap-xs);
870
+ }
871
+ .el-p-sm {
872
+ padding: var(--el-layout-gap-sm);
873
+ --el-table-spacer-width: var(--el-layout-gap-sm);
874
+ --el-container-px: var(--el-layout-gap-sm);
875
+ }
876
+ .el-p-md {
877
+ padding: var(--el-layout-gap-md);
878
+ --el-table-spacer-width: var(--el-layout-gap-md);
879
+ --el-container-px: var(--el-layout-gap-md);
880
+ }
881
+ .el-p-lg {
882
+ padding: var(--el-layout-gap-lg);
883
+ --el-table-spacer-width: var(--el-layout-gap-lg);
884
+ --el-container-px: var(--el-layout-gap-lg);
885
+ }
886
+ .el-p-xl {
887
+ padding: var(--el-layout-gap-xl);
888
+ --el-table-spacer-width: var(--el-layout-gap-xl);
889
+ --el-container-px: var(--el-layout-gap-xl);
890
+ }
891
+ .el-p-2xl {
892
+ padding: var(--el-layout-gap-2xl);
893
+ --el-table-spacer-width: var(--el-layout-gap-2xl);
894
+ --el-container-px: var(--el-layout-gap-2xl);
895
+ }
896
+ .el-p-section {
897
+ padding: var(--el-section-gap);
898
+ --el-table-spacer-width: var(--el-section-gap);
899
+ --el-container-px: var(--el-section-gap);
900
+ }
901
+ .el-p-content {
902
+ padding: var(--el-content-gap);
903
+ --el-table-spacer-width: var(--el-content-gap);
904
+ --el-container-px: var(--el-content-gap);
905
+ }
906
+
907
+ /* Padding X (horizontal) - also set --el-container-px for cascaded styles */
908
+ .el-px-xs { padding-left: var(--el-layout-gap-xs); padding-right: var(--el-layout-gap-xs); --el-container-px: var(--el-layout-gap-xs); }
909
+ .el-px-sm { padding-left: var(--el-layout-gap-sm); padding-right: var(--el-layout-gap-sm); --el-container-px: var(--el-layout-gap-sm); }
910
+ .el-px-md { padding-left: var(--el-layout-gap-md); padding-right: var(--el-layout-gap-md); --el-container-px: var(--el-layout-gap-md); }
911
+ .el-px-lg { padding-left: var(--el-layout-gap-lg); padding-right: var(--el-layout-gap-lg); --el-container-px: var(--el-layout-gap-lg); }
912
+ .el-px-xl { padding-left: var(--el-layout-gap-xl); padding-right: var(--el-layout-gap-xl); --el-container-px: var(--el-layout-gap-xl); }
913
+ .el-px-2xl { padding-left: var(--el-layout-gap-2xl); padding-right: var(--el-layout-gap-2xl); --el-container-px: var(--el-layout-gap-2xl); }
914
+
915
+ /* Padding Y (vertical) */
916
+ .el-py-xs { padding-top: var(--el-layout-gap-xs); padding-bottom: var(--el-layout-gap-xs); }
917
+ .el-py-sm { padding-top: var(--el-layout-gap-sm); padding-bottom: var(--el-layout-gap-sm); }
918
+ .el-py-md { padding-top: var(--el-layout-gap-md); padding-bottom: var(--el-layout-gap-md); }
919
+ .el-py-lg { padding-top: var(--el-layout-gap-lg); padding-bottom: var(--el-layout-gap-lg); }
920
+ .el-py-xl { padding-top: var(--el-layout-gap-xl); padding-bottom: var(--el-layout-gap-xl); }
921
+ .el-py-2xl { padding-top: var(--el-layout-gap-2xl); padding-bottom: var(--el-layout-gap-2xl); }
922
+
923
+ /* Padding Top */
924
+ .el-pt-0 { padding-top: 0; }
925
+ .el-pt-xs { padding-top: var(--el-layout-gap-xs); }
926
+ .el-pt-sm { padding-top: var(--el-layout-gap-sm); }
927
+ .el-pt-md { padding-top: var(--el-layout-gap-md); }
928
+ .el-pt-lg { padding-top: var(--el-layout-gap-lg); }
929
+ .el-pt-xl { padding-top: var(--el-layout-gap-xl); }
930
+ .el-pt-2xl { padding-top: var(--el-layout-gap-2xl); }
931
+
932
+ /* Padding Bottom */
933
+ .el-pb-xs { padding-bottom: var(--el-layout-gap-xs); }
934
+ .el-pb-sm { padding-bottom: var(--el-layout-gap-sm); }
935
+ .el-pb-md { padding-bottom: var(--el-layout-gap-md); }
936
+ .el-pb-lg { padding-bottom: var(--el-layout-gap-lg); }
937
+ .el-pb-xl { padding-bottom: var(--el-layout-gap-xl); }
938
+
939
+ /* Padding Left */
940
+ .el-pl-xs { padding-left: var(--el-layout-gap-xs); }
941
+ .el-pl-sm { padding-left: var(--el-layout-gap-sm); }
942
+ .el-pl-md { padding-left: var(--el-layout-gap-md); }
943
+ .el-pl-lg { padding-left: var(--el-layout-gap-lg); }
944
+ .el-pl-xl { padding-left: var(--el-layout-gap-xl); }
945
+ .el-pl-2xl { padding-left: var(--el-layout-gap-2xl); }
946
+
947
+ /* Padding Right */
948
+ .el-pr-xs { padding-right: var(--el-layout-gap-xs); }
949
+ .el-pr-sm { padding-right: var(--el-layout-gap-sm); }
950
+ .el-pr-md { padding-right: var(--el-layout-gap-md); }
951
+ .el-pr-lg { padding-right: var(--el-layout-gap-lg); }
952
+ .el-pr-xl { padding-right: var(--el-layout-gap-xl); }
953
+ .el-pr-2xl { padding-right: var(--el-layout-gap-2xl); }
954
+
955
+ /* Margin utilities */
956
+ .el-m-xs { margin: var(--el-layout-gap-xs); }
957
+ .el-m-sm { margin: var(--el-layout-gap-sm); }
958
+ .el-m-md { margin: var(--el-layout-gap-md); }
959
+ .el-m-lg { margin: var(--el-layout-gap-lg); }
960
+ .el-m-xl { margin: var(--el-layout-gap-xl); }
961
+ .el-m-2xl { margin: var(--el-layout-gap-2xl); }
962
+
963
+ /* Margin X (horizontal) */
964
+ .el-mx-xs { margin-left: var(--el-layout-gap-xs); margin-right: var(--el-layout-gap-xs); }
965
+ .el-mx-sm { margin-left: var(--el-layout-gap-sm); margin-right: var(--el-layout-gap-sm); }
966
+ .el-mx-md { margin-left: var(--el-layout-gap-md); margin-right: var(--el-layout-gap-md); }
967
+ .el-mx-lg { margin-left: var(--el-layout-gap-lg); margin-right: var(--el-layout-gap-lg); }
968
+
969
+ /* Margin Y (vertical) */
970
+ .el-my-xs { margin-top: var(--el-layout-gap-xs); margin-bottom: var(--el-layout-gap-xs); }
971
+ .el-my-sm { margin-top: var(--el-layout-gap-sm); margin-bottom: var(--el-layout-gap-sm); }
972
+ .el-my-md { margin-top: var(--el-layout-gap-md); margin-bottom: var(--el-layout-gap-md); }
973
+ .el-my-lg { margin-top: var(--el-layout-gap-lg); margin-bottom: var(--el-layout-gap-lg); }
974
+
975
+ /* Margin bottom utilities (common for stacking) */
976
+ .el-mb-xs { margin-bottom: var(--el-layout-gap-xs); }
977
+ .el-mb-sm { margin-bottom: var(--el-layout-gap-sm); }
978
+ .el-mb-md { margin-bottom: var(--el-layout-gap-md); }
979
+ .el-mb-lg { margin-bottom: var(--el-layout-gap-lg); }
980
+ .el-mb-xl { margin-bottom: var(--el-layout-gap-xl); }
981
+ .el-mb-2xl { margin-bottom: var(--el-layout-gap-2xl); }
982
+
983
+ /* Margin top utilities */
984
+ .el-mt-xs { margin-top: var(--el-layout-gap-xs); }
985
+ .el-mt-sm { margin-top: var(--el-layout-gap-sm); }
986
+ .el-mt-md { margin-top: var(--el-layout-gap-md); }
987
+ .el-mt-lg { margin-top: var(--el-layout-gap-lg); }
988
+ .el-mt-xl { margin-top: var(--el-layout-gap-xl); }
989
+ .el-mt-2xl { margin-top: var(--el-layout-gap-2xl); }
990
+
991
+ /* Margin left utilities */
992
+ .el-ml-0 { margin-left: 0; }
993
+ .el-ml-xs { margin-left: var(--el-layout-gap-xs); }
994
+ .el-ml-sm { margin-left: var(--el-layout-gap-sm); }
995
+ .el-ml-md { margin-left: var(--el-layout-gap-md); }
996
+ .el-ml-lg { margin-left: var(--el-layout-gap-lg); }
997
+ .el-ml-xl { margin-left: var(--el-layout-gap-xl); }
998
+ .el-ml-2xl { margin-left: var(--el-layout-gap-2xl); }
999
+
1000
+ /* Margin right utilities */
1001
+ .el-mr-0 { margin-right: 0; }
1002
+ .el-mr-xs { margin-right: var(--el-layout-gap-xs); }
1003
+ .el-mr-sm { margin-right: var(--el-layout-gap-sm); }
1004
+ .el-mr-md { margin-right: var(--el-layout-gap-md); }
1005
+ .el-mr-lg { margin-right: var(--el-layout-gap-lg); }
1006
+ .el-mr-xl { margin-right: var(--el-layout-gap-xl); }
1007
+ .el-mr-2xl { margin-right: var(--el-layout-gap-2xl); }
1008
+
1009
+ /* ============================================
1010
+ Space Utilities (vertical/horizontal stacking)
1011
+ These add margin between child elements
1012
+ ============================================ */
1013
+
1014
+ /* Space Y (vertical) - margin-top on all but first child */
1015
+ .el-space-y-xs > * + * { margin-top: var(--el-layout-gap-xs); }
1016
+ .el-space-y-sm > * + * { margin-top: var(--el-layout-gap-sm); }
1017
+ .el-space-y-md > * + * { margin-top: var(--el-layout-gap-md); }
1018
+ .el-space-y-lg > * + * { margin-top: var(--el-layout-gap-lg); }
1019
+ .el-space-y-xl > * + * { margin-top: var(--el-layout-gap-xl); }
1020
+ .el-space-y-2xl > * + * { margin-top: var(--el-layout-gap-2xl); }
1021
+ .el-space-y-section > * + * { margin-top: var(--el-section-gap); }
1022
+ .el-space-y-content > * + * { margin-top: var(--el-content-gap); }
1023
+
1024
+ /* Space X (horizontal) - margin-left on all but first child */
1025
+ .el-space-x-xs > * + * { margin-left: var(--el-layout-gap-xs); }
1026
+ .el-space-x-sm > * + * { margin-left: var(--el-layout-gap-sm); }
1027
+ .el-space-x-md > * + * { margin-left: var(--el-layout-gap-md); }
1028
+ .el-space-x-lg > * + * { margin-left: var(--el-layout-gap-lg); }
1029
+ .el-space-x-xl > * + * { margin-left: var(--el-layout-gap-xl); }
1030
+
1031
+ /* ============================================
1032
+ Component in Container - Negative Margin
1033
+ For edge-to-edge appearance (List, Accordion, Alert, Collapsible)
1034
+ ============================================ */
1035
+
1036
+ /* Base in container - horizontal margins only */
1037
+ .el-in-container {
1038
+ margin-left: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
1039
+ margin-right: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
1040
+ width: calc(100% + var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * 2);
1041
+ }
1042
+
1043
+ /* As first element in container - add negative top margin */
1044
+ .el-in-container-first {
1045
+ margin-left: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
1046
+ margin-right: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
1047
+ margin-top: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
1048
+ width: calc(100% + var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * 2);
1049
+ }
1050
+
1051
+ /* As last element in container - add negative bottom margin */
1052
+ .el-in-container-last {
1053
+ margin-left: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
1054
+ margin-right: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
1055
+ margin-bottom: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
1056
+ width: calc(100% + var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * 2);
1057
+ }
1058
+
1059
+ /* As only element or spanning full container - all margins */
1060
+ .el-in-container-full {
1061
+ margin: calc(var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * -1);
1062
+ width: calc(100% + var(--el-card-padding, var(--el-layout-gap-lg, 1rem)) * 2);
1063
+ }
1064
+
1065
+ /* Container padding size variants */
1066
+ .el-in-container-padding-sm {
1067
+ --el-card-padding: var(--el-layout-gap-md, 0.75rem);
1068
+ }
1069
+
1070
+ .el-in-container-padding-lg {
1071
+ --el-card-padding: var(--el-layout-gap-xl, 1.5rem);
1072
+ }