@loidolt/theme-styles 0.4.0 → 0.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loidolt/theme-styles",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Base styles, fonts, accessibility helpers, and utilities for Loidolt applications",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -28,7 +28,7 @@
28
28
  "build": "node -e \"console.log('theme-styles: source CSS is publish-ready')\""
29
29
  },
30
30
  "dependencies": {
31
- "@loidolt/theme-tokens": "^0.4.0"
31
+ "@loidolt/theme-tokens": "^0.6.0"
32
32
  },
33
33
  "publishConfig": {
34
34
  "access": "public",
@@ -20,10 +20,14 @@
20
20
  .ldt-dialog__body,
21
21
  .ldt-drawer__body,
22
22
  .ldt-tabs__list,
23
- .ldt-toggle-group
23
+ .ldt-toggle-group,
24
+ .ldt-listbox,
25
+ .ldt-media-grid
24
26
  )
25
27
  :where(:focus-visible) {
26
28
  outline-offset: -2px;
29
+ /* Follow the control's accessible foreground pairing so inset focus stays visible on fills. */
30
+ outline-color: currentColor;
27
31
  }
28
32
 
29
33
  .ldt-visually-hidden,
@@ -39,6 +43,20 @@
39
43
  border: 0 !important;
40
44
  }
41
45
 
46
+ /* Hidden until it, or something inside it, takes focus — for a "skip" or "back to top" link
47
+ that should not occupy the layout for pointer users. */
48
+ .ldt-sr-only-focusable:not(:focus, :focus-within) {
49
+ position: absolute !important;
50
+ width: 1px !important;
51
+ height: 1px !important;
52
+ padding: 0 !important;
53
+ margin: -1px !important;
54
+ overflow: hidden !important;
55
+ clip: rect(0, 0, 0, 0) !important;
56
+ white-space: nowrap !important;
57
+ border: 0 !important;
58
+ }
59
+
42
60
  .ldt-skip-link {
43
61
  position: fixed;
44
62
  z-index: var(--loidolt-z-skip-link);
@@ -56,6 +74,20 @@
56
74
  min-width: 44px;
57
75
  min-height: 44px;
58
76
  }
77
+ /* Enlarges the hit area without moving anything: a small glyph button in dense UI keeps its
78
+ visual size, and an invisible 44px square centred on it takes the press. */
79
+ .ldt-touch-target-expand {
80
+ position: relative;
81
+ }
82
+ .ldt-touch-target-expand::after {
83
+ content: '';
84
+ position: absolute;
85
+ top: 50%;
86
+ left: 50%;
87
+ width: max(100%, 44px);
88
+ height: max(100%, 44px);
89
+ transform: translate(-50%, -50%);
90
+ }
59
91
 
60
92
  /* Preserve the compact visual density for mouse/keyboard layouts, but give touch-first devices
61
93
  the 44px target size recommended for comfortable coarse-pointer operation. */
@@ -71,17 +103,48 @@
71
103
  .ldt-choice,
72
104
  .ldt-switch,
73
105
  .ldt-number-field__button,
74
- .ldt-menu__item
106
+ .ldt-menu__item,
107
+ .ldt-listbox__item,
108
+ .ldt-combobox,
109
+ .ldt-password-input,
110
+ .ldt-chip,
111
+ .ldt-data-table__edit,
112
+ .ldt-media-controls__button,
113
+ .ldt-media-controls__speed,
114
+ .ldt-media-controls__range,
115
+ .ldt-lightbox__control,
116
+ .ldt-media-carousel__control
75
117
  ) {
76
118
  min-height: 44px;
77
119
  }
78
- :where(.ldt-icon-button, .ldt-number-field__button) {
120
+ :where(
121
+ .ldt-icon-button,
122
+ .ldt-number-field__button,
123
+ .ldt-combobox__trigger,
124
+ .ldt-password-input__toggle,
125
+ .ldt-chip__remove,
126
+ .ldt-media-controls__button,
127
+ .ldt-lightbox__control,
128
+ .ldt-media-carousel__control
129
+ ) {
79
130
  min-width: 44px;
80
131
  }
132
+ /* The thumb keeps its drawn size; an invisible 44px square around it takes the touch. */
133
+ .ldt-slider__thumb {
134
+ position: relative;
135
+ }
136
+ .ldt-slider__thumb::after {
137
+ content: '';
138
+ position: absolute;
139
+ inset: 50% auto auto 50%;
140
+ width: 44px;
141
+ height: 44px;
142
+ transform: translate(-50%, -50%);
143
+ }
81
144
  :where(.ldt-icon-button) {
82
145
  width: 44px;
83
146
  }
84
- .ldt-number-field {
147
+ .ldt-number-field:not(.ldt-number-field--bare) {
85
148
  grid-template-columns: 44px minmax(0, 1fr) 44px;
86
149
  }
87
150
  }
@@ -1,6 +1,8 @@
1
1
  /* Deep slice: assumes the token custom properties are already loaded.
2
2
  Import '@loidolt/theme-styles/tokens' (or the whole '@loidolt/theme-styles') first. */
3
3
  .ldt-button {
4
+ max-width: 100%;
5
+ min-width: 0;
4
6
  min-height: var(--loidolt-size-control);
5
7
  display: inline-flex;
6
8
  align-items: center;
@@ -13,10 +15,12 @@
13
15
  background: transparent;
14
16
  font: var(--loidolt-font-size-sm) var(--loidolt-font-utility);
15
17
  letter-spacing: 0.08em;
16
- line-height: 1;
18
+ line-height: 1.2;
19
+ overflow-wrap: anywhere;
20
+ text-align: center;
17
21
  text-decoration: none;
18
22
  text-transform: uppercase;
19
- white-space: nowrap;
23
+ white-space: normal;
20
24
  }
21
25
  .ldt-button:hover:not(:disabled, [aria-disabled='true']) {
22
26
  color: var(--loidolt-text-inverse);
@@ -100,6 +104,19 @@
100
104
  border-radius: 50%;
101
105
  animation: ldt-spin 0.7s linear infinite;
102
106
  }
107
+ .ldt-spinner--sm {
108
+ width: 0.875rem;
109
+ height: 0.875rem;
110
+ }
111
+ .ldt-spinner--md {
112
+ width: 1.25rem;
113
+ height: 1.25rem;
114
+ }
115
+ .ldt-spinner--lg {
116
+ width: 2rem;
117
+ height: 2rem;
118
+ border-width: 3px;
119
+ }
103
120
  @keyframes ldt-spin {
104
121
  to {
105
122
  transform: rotate(360deg);
@@ -196,3 +196,114 @@
196
196
  .ldt-record-stepper__count {
197
197
  white-space: nowrap;
198
198
  }
199
+ /* The filters narrowing a list, each removable on its own. Sits under the list's toolbar. */
200
+ .ldt-filter-chips {
201
+ display: flex;
202
+ flex-wrap: wrap;
203
+ align-items: center;
204
+ gap: var(--loidolt-space-2);
205
+ }
206
+ .ldt-filter-chips__list {
207
+ display: flex;
208
+ flex-wrap: wrap;
209
+ gap: var(--loidolt-space-2);
210
+ margin: 0;
211
+ padding: 0;
212
+ list-style: none;
213
+ }
214
+ /* DataTable: selection, editable cells, responsive columns, virtual spacers. */
215
+ .ldt-table :where(th, td).ldt-data-table__select {
216
+ width: 2.75rem;
217
+ padding-inline-end: 0;
218
+ }
219
+ .ldt-data-table__radio {
220
+ width: 1rem;
221
+ height: 1rem;
222
+ accent-color: var(--loidolt-accent);
223
+ }
224
+ .ldt-table tbody tr[data-selected] {
225
+ background: var(--loidolt-surface-alt);
226
+ }
227
+ .ldt-table tbody tr[data-selected] td:first-child {
228
+ box-shadow: inset 3px 0 0 var(--loidolt-accent);
229
+ }
230
+ .ldt-data-table__spacer td {
231
+ padding: 0;
232
+ border: 0;
233
+ }
234
+ /* The resting state of an editable cell: reads as the value, reveals itself on hover or focus. */
235
+ .ldt-data-table__edit {
236
+ min-height: 1.5rem;
237
+ width: 100%;
238
+ border: 0;
239
+ border-bottom: var(--loidolt-border-width) dashed transparent;
240
+ padding: 0;
241
+ color: inherit;
242
+ background: transparent;
243
+ font: inherit;
244
+ text-align: inherit;
245
+ cursor: text;
246
+ }
247
+ .ldt-data-table__edit:hover {
248
+ border-bottom-color: var(--loidolt-border-control);
249
+ }
250
+ .ldt-data-table__edit-input {
251
+ width: 100%;
252
+ min-height: 1.5rem;
253
+ border: 0;
254
+ border-bottom: var(--loidolt-border-width) solid var(--loidolt-accent);
255
+ padding: 0;
256
+ color: inherit;
257
+ background: var(--loidolt-surface-input);
258
+ font: inherit;
259
+ text-align: inherit;
260
+ }
261
+ @media (max-width: 1024px) {
262
+ .ldt-table :where(th, td)[data-hide-below='expanded'] {
263
+ display: none;
264
+ }
265
+ }
266
+ @media (max-width: 760px) {
267
+ .ldt-table :where(th, td)[data-hide-below='compact'] {
268
+ display: none;
269
+ }
270
+ }
271
+
272
+ /* A faceted-filter trigger carries the number of values chosen. */
273
+ .ldt-facet__count {
274
+ display: inline-grid;
275
+ min-width: 1.25rem;
276
+ place-items: center;
277
+ margin-inline-start: 0.4rem;
278
+ padding-inline: 0.3rem;
279
+ color: var(--loidolt-on-accent);
280
+ background: var(--loidolt-accent);
281
+ font-size: var(--loidolt-font-size-xs);
282
+ }
283
+
284
+ /* The footer under a data table: status line, rows-per-page, page trail. */
285
+ .ldt-data-table-pagination {
286
+ display: flex;
287
+ flex-wrap: wrap;
288
+ align-items: center;
289
+ justify-content: space-between;
290
+ gap: var(--loidolt-space-3);
291
+ }
292
+ .ldt-data-table-pagination__summary {
293
+ margin: 0;
294
+ color: var(--loidolt-text-muted);
295
+ font: var(--loidolt-font-size-sm) var(--loidolt-font-utility);
296
+ font-variant-numeric: tabular-nums;
297
+ }
298
+ .ldt-data-table-pagination__size {
299
+ display: flex;
300
+ align-items: center;
301
+ gap: var(--loidolt-space-2);
302
+ color: var(--loidolt-text-muted);
303
+ font: var(--loidolt-font-size-xs) var(--loidolt-font-utility);
304
+ letter-spacing: var(--loidolt-font-tracking-utility);
305
+ text-transform: uppercase;
306
+ }
307
+ .ldt-data-table-pagination__size .ldt-select {
308
+ width: auto;
309
+ }
@@ -45,6 +45,38 @@
45
45
  transform-origin: left center;
46
46
  transition: transform var(--loidolt-motion-normal) var(--loidolt-motion-easing);
47
47
  }
48
+ .ldt-progress--sm {
49
+ height: 0.2rem;
50
+ }
51
+ .ldt-progress--lg {
52
+ height: 0.6rem;
53
+ }
54
+ .ldt-progress--success .ldt-progress__bar {
55
+ background: var(--loidolt-success);
56
+ }
57
+ .ldt-progress--warning .ldt-progress__bar {
58
+ background: var(--loidolt-warning);
59
+ }
60
+ .ldt-progress--error .ldt-progress__bar {
61
+ background: var(--loidolt-danger);
62
+ }
63
+ .ldt-progress--info .ldt-progress__bar {
64
+ background: var(--loidolt-info);
65
+ }
66
+ .ldt-progress-field {
67
+ display: flex;
68
+ align-items: center;
69
+ gap: var(--loidolt-space-3);
70
+ }
71
+ .ldt-progress-field__value {
72
+ flex: none;
73
+ min-width: 4ch;
74
+ white-space: nowrap;
75
+ color: var(--loidolt-text-muted);
76
+ font: var(--loidolt-font-size-sm) var(--loidolt-font-utility);
77
+ font-variant-numeric: tabular-nums;
78
+ text-align: end;
79
+ }
48
80
  .ldt-progress--indeterminate .ldt-progress__bar {
49
81
  width: 40%;
50
82
  transform: none;
@@ -69,6 +101,38 @@
69
101
  background-size: 200% 100%;
70
102
  animation: ldt-shimmer 1.5s linear infinite;
71
103
  }
104
+ /* Shapes take the metrics of what they stand in for, so the layout does not jump on load. */
105
+ .ldt-skeleton--text,
106
+ .ldt-skeleton--title,
107
+ .ldt-skeleton--avatar,
108
+ .ldt-skeleton--button,
109
+ .ldt-skeleton--card {
110
+ display: block;
111
+ }
112
+ .ldt-skeleton--text {
113
+ height: 0.8em;
114
+ min-height: 0;
115
+ margin-block: 0.35em;
116
+ }
117
+ .ldt-skeleton--title {
118
+ width: 60%;
119
+ height: 1.4em;
120
+ }
121
+ .ldt-skeleton--avatar {
122
+ width: var(--loidolt-size-control);
123
+ height: var(--loidolt-size-control);
124
+ }
125
+ .ldt-skeleton--button {
126
+ width: 7rem;
127
+ height: var(--loidolt-size-control);
128
+ }
129
+ .ldt-skeleton--card {
130
+ width: 100%;
131
+ height: 10rem;
132
+ }
133
+ .ldt-skeleton-lines {
134
+ display: block;
135
+ }
72
136
  @keyframes ldt-shimmer {
73
137
  to {
74
138
  background-position: -200% 0;
@@ -120,6 +184,35 @@
120
184
  grid-area: 1 / 2 / span 2 / auto;
121
185
  align-self: start;
122
186
  }
187
+ .ldt-toast__actions {
188
+ grid-column: 1;
189
+ display: flex;
190
+ flex-wrap: wrap;
191
+ gap: 0.4rem;
192
+ margin-top: 0.2rem;
193
+ }
194
+ /* Logical insets, so `start`/`end` follow the writing direction. */
195
+ .ldt-toast-viewport--bottom-start {
196
+ right: auto;
197
+ left: 1rem;
198
+ inset-inline: 1rem auto;
199
+ }
200
+ .ldt-toast-viewport--bottom-center,
201
+ .ldt-toast-viewport--top-center {
202
+ right: auto;
203
+ left: 50%;
204
+ transform: translateX(-50%);
205
+ }
206
+ .ldt-toast-viewport--top-end,
207
+ .ldt-toast-viewport--top-start,
208
+ .ldt-toast-viewport--top-center {
209
+ top: 1rem;
210
+ bottom: auto;
211
+ }
212
+ .ldt-toast-viewport--top-start {
213
+ right: auto;
214
+ inset-inline: 1rem auto;
215
+ }
123
216
  /* A colored dot that reports state where a Badge would be too loud. */
124
217
  .ldt-status-dot {
125
218
  display: inline-block;