@teseor/css 2.3.2 → 2.5.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": "@teseor/css",
3
- "version": "2.3.2",
3
+ "version": "2.5.0",
4
4
  "description": "CSS library - reset, primitives, components, utilities",
5
5
  "license": "MIT",
6
6
  "author": "letanure",
@@ -12,6 +12,9 @@
12
12
  "state": {
13
13
  "values": ["error", "success"]
14
14
  },
15
+ "auto-size": {
16
+ "type": "boolean"
17
+ },
15
18
  "block": {
16
19
  "type": "boolean"
17
20
  }
@@ -26,6 +26,11 @@ description: Text input field for user data entry. Heights align to grid rows.
26
26
  <!-- @full_width -->
27
27
  <input class="ui-input ui-input--block" type="text" placeholder="{{ t('full_width_input', 'Full width input') }}"></input>
28
28
 
29
+ <!-- @auto_size | column -->
30
+ <!-- Auto-sizing textarea grows with content. Requires browser support for field-sizing. -->
31
+ <textarea class="ui-input ui-input--auto-size ui-input--block" placeholder="{{ t('auto_size_textarea', 'Type here and watch it grow...') }}"></textarea>
32
+ <input class="ui-input ui-input--auto-size" type="text" placeholder="{{ t('auto_size_input', 'Auto-sizing input') }}"></input>
33
+
29
34
  <!-- @with_prefix_icon -->
30
35
  <div class="ui-input-group ui-input-group--has-prefix">
31
36
  <span class="ui-input-group__addon ui-input-group__addon--start">
@@ -79,6 +79,12 @@
79
79
  // @desc Success border
80
80
  --_border-color-focus: var(--ui-input-success-border, var(--ui-color-success, #{t.$color-success}));
81
81
  }
82
+
83
+ // @modifier boolean auto-size
84
+ .input--auto-size {
85
+ --_height: auto;
86
+ --_min-height: var(--ui-input-height, var(--ui-row-2, #{t.$row-2}));
87
+ }
82
88
  }
83
89
 
84
90
  @layer components.styles {
@@ -129,6 +135,13 @@
129
135
  background: var(--_color-bg-subtle);
130
136
  }
131
137
 
138
+ // Auto-size — textarea/input grows with content
139
+ &--auto-size {
140
+ field-sizing: content;
141
+
142
+ min-block-size: var(--_min-height);
143
+ }
144
+
132
145
  // Full width
133
146
  // @modifier boolean block
134
147
  &--block {
@@ -8,6 +8,9 @@
8
8
  },
9
9
  "vertical": {
10
10
  "type": "boolean"
11
+ },
12
+ "responsive": {
13
+ "type": "boolean"
11
14
  }
12
15
  },
13
16
  "elements": {
@@ -54,6 +54,24 @@ description: Horizontal or vertical navigation links for primary and secondary n
54
54
  </ul>
55
55
  </nav>
56
56
 
57
+ <!-- @responsive -->
58
+ <!-- Auto-collapses to vertical when container is narrow. -->
59
+ <div class="ui-bg-muted ui-p-2" style="inline-size: 250px">
60
+ <nav class="ui-nav ui-nav--responsive">
61
+ <ul class="ui-nav__list">
62
+ <li>
63
+ <a class="ui-nav__item ui-nav__item--active" href="#">{{ t('home', 'Home') }}</a>
64
+ </li>
65
+ <li>
66
+ <a class="ui-nav__item" href="#">{{ t('about', 'About') }}</a>
67
+ </li>
68
+ <li>
69
+ <a class="ui-nav__item" href="#">{{ t('contact', 'Contact') }}</a>
70
+ </li>
71
+ </ul>
72
+ </nav>
73
+ </div>
74
+
57
75
  <!-- @vertical_pills -->
58
76
  <!-- Vertical navigation with pill-style active indicator. -->
59
77
  <nav class="ui-nav ui-nav--vertical ui-nav--pills" style="inline-size: 200px">
@@ -44,6 +44,8 @@
44
44
  }
45
45
 
46
46
  // @modifier boolean vertical
47
+
48
+ // @modifier boolean responsive
47
49
  }
48
50
 
49
51
  @layer components.styles {
@@ -148,6 +150,30 @@
148
150
  }
149
151
  }
150
152
 
153
+ // Responsive — auto-collapses to vertical in narrow containers
154
+ .nav--responsive {
155
+ container-type: inline-size;
156
+
157
+ @container (max-width: #{t.$container-threshold-sm}) {
158
+ .nav__list {
159
+ flex-direction: column;
160
+ align-items: stretch;
161
+
162
+ block-size: auto;
163
+
164
+ box-shadow: inset calc(var(--_border-width-sm) * -1) 0 0 var(--_border-color);
165
+ }
166
+
167
+ .nav__item {
168
+ box-shadow: inset calc(var(--_border-width-md) * -1) 0 0 transparent;
169
+
170
+ &--active {
171
+ box-shadow: inset calc(var(--_border-width-md) * -1) 0 0 var(--_item-color-active);
172
+ }
173
+ }
174
+ }
175
+ }
176
+
151
177
  // Vertical + pills
152
178
  .nav--vertical.nav--pills {
153
179
  .nav__list {
@@ -63,6 +63,11 @@
63
63
  "default": "var(--ui-color-bg)",
64
64
  "description": "Tab bg active"
65
65
  },
66
+ {
67
+ "name": "--ui-tabs-tab-line-height",
68
+ "default": "var(--ui-line-height-none)",
69
+ "description": "Tab line height"
70
+ },
66
71
  {
67
72
  "name": "--ui-tabs-panel-padding",
68
73
  "default": "var(--ui-space-3)",
@@ -30,6 +30,8 @@
30
30
  --_tab-bg: var(--ui-tabs-tab-bg, transparent);
31
31
  // @desc Tab bg active
32
32
  --_tab-bg-active: var(--ui-tabs-tab-bg-active, var(--ui-color-bg, #{t.$color-bg}));
33
+ // @desc Tab line height
34
+ --_tab-line-height: var(--ui-tabs-tab-line-height, var(--ui-line-height-none, #{t.$line-height-none}));
33
35
  // @desc Panel padding on all sides
34
36
  --_panel-padding: var(--ui-tabs-panel-padding, var(--ui-space-3, #{t.$space-3}));
35
37
  }
@@ -80,7 +82,7 @@
80
82
  font-family: var(--_font-sans);
81
83
  font-size: var(--_tab-font-size);
82
84
  font-weight: var(--_weight-medium);
83
- line-height: 1;
85
+ line-height: var(--_tab-line-height);
84
86
  color: var(--_color-text-muted);
85
87
 
86
88
  background: var(--_tab-bg);
@@ -103,8 +103,8 @@ $sizes: (
103
103
  // ==========================================================================
104
104
 
105
105
  // Font families (system stack, consumers override via CSS tokens)
106
- $font-sans: system-ui, -apple-system, blinkmacsystemfont, "Segoe UI", roboto, "Helvetica Neue", arial, sans-serif;
107
- $font-mono: ui-monospace, sfmono-regular, "SF Mono", menlo, consolas, "Liberation Mono", monospace;
106
+ $font-sans: system-ui, -apple-system, blinkmacsystemfont, "Segoe UI", roboto, oxygen, ubuntu, cantarell, "Helvetica Neue", arial, sans-serif;
107
+ $font-mono: ui-monospace, "SFMono-Regular", "SF Mono", menlo, consolas, "Liberation Mono", "Courier New", monospace;
108
108
 
109
109
  // Font sizes (derived from base, 1.2 modular scale)
110
110
  $font-size-base: 1rem; // 16px — core knob
@@ -117,6 +117,9 @@ $font-size-2xl: 1.75rem; // 28px
117
117
  $font-size-3xl: 2rem; // 32px
118
118
  $font-size-4xl: 2.5rem; // 40px
119
119
 
120
+ // Unitless line height (no extra leading)
121
+ $line-height-none: 1;
122
+
120
123
  // Tight line heights (compact UI elements)
121
124
  $line-height-tight-xs: $row;
122
125
  $line-height-tight-sm: $row;
@@ -8,26 +8,26 @@
8
8
  --ui-unit: calc(8px * var(--ui-scale));
9
9
 
10
10
  // Base colors — shades auto-generated via color-mix in tokens.scale
11
- --ui-color-primary: oklch(55% 0.22 250);
11
+ --ui-color-primary: oklch(54% 0.20 260);
12
12
  --ui-color-success: oklch(60% 0.18 145);
13
13
  --ui-color-warning: oklch(75% 0.18 70);
14
14
  --ui-color-danger: oklch(60% 0.22 25);
15
- --ui-color-neutral: oklch(50% 0.02 250);
15
+ --ui-color-neutral: oklch(45% 0.015 260);
16
16
 
17
17
  // Font families — system stacks, override for brand fonts
18
- --ui-font-sans: system-ui, -apple-system, blinkmacsystemfont, "Segoe UI", roboto, "Helvetica Neue", arial, sans-serif;
19
- --ui-font-mono: ui-monospace, sfmono-regular, "SF Mono", menlo, consolas, "Liberation Mono", monospace;
18
+ --ui-font-sans: system-ui, -apple-system, blinkmacsystemfont, "Segoe UI", roboto, oxygen, ubuntu, cantarell, "Helvetica Neue", arial, sans-serif;
19
+ --ui-font-mono: ui-monospace, "SFMono-Regular", "SF Mono", menlo, consolas, "Liberation Mono", "Courier New", monospace;
20
20
 
21
21
  // Base font size — all font-size-* tokens derive from this via calc()
22
22
  --ui-font-size-base: calc(1rem * var(--ui-scale));
23
23
 
24
24
  // Base radius — sm/md/lg derive from this
25
- --ui-radius-base: var(--ui-unit);
25
+ --ui-radius-base: 6px;
26
26
 
27
27
  // Base border width — sm/md/lg derive from this
28
28
  --ui-border-width-base: calc(var(--ui-unit) * 0.125);
29
29
 
30
30
  // Shadow strength — controls opacity of all shadow levels
31
- --ui-shadow-strength: 20%;
31
+ --ui-shadow-strength: 12%;
32
32
  }
33
33
  }
@@ -17,6 +17,9 @@
17
17
  // Two modes: normal (for body text) and tight (for UI/forms)
18
18
  // ==========================================================================
19
19
 
20
+ // Unitless line height (no extra leading)
21
+ --ui-line-height-none: 1;
22
+
20
23
  // Tight line-heights for compact UI elements
21
24
  --ui-line-height-tight-xs: var(--ui-row-1);
22
25
  --ui-line-height-tight-sm: var(--ui-row-1);
@@ -76,9 +76,19 @@
76
76
  },
77
77
  {
78
78
  "name": "--ui-sidebar-nav-group-label-weight",
79
- "default": "var(--ui-font-weight-bold)",
79
+ "default": "var(--ui-font-weight-semibold)",
80
80
  "description": "Group label weight"
81
81
  },
82
+ {
83
+ "name": "--ui-sidebar-nav-group-label-transform",
84
+ "default": "none",
85
+ "description": "Group label text-transform"
86
+ },
87
+ {
88
+ "name": "--ui-sidebar-nav-group-label-letter-spacing",
89
+ "default": "normal",
90
+ "description": "Group label letter-spacing"
91
+ },
82
92
  {
83
93
  "name": "--ui-sidebar-nav-item-height",
84
94
  "default": "var(--ui-row-2)",
@@ -116,17 +126,17 @@
116
126
  },
117
127
  {
118
128
  "name": "--ui-sidebar-nav-item-active-bg",
119
- "default": "var(--ui-color-primary-subtle)",
129
+ "default": "var(--ui-color-bg-muted)",
120
130
  "description": "Item active bg"
121
131
  },
122
132
  {
123
133
  "name": "--ui-sidebar-nav-item-active-color",
124
- "default": "var(--ui-color-primary-hover)",
134
+ "default": "var(--ui-color-primary)",
125
135
  "description": "Item active color"
126
136
  },
127
137
  {
128
138
  "name": "--ui-sidebar-nav-item-active-weight",
129
- "default": "var(--ui-font-weight-medium)",
139
+ "default": "normal",
130
140
  "description": "Item active weight"
131
141
  },
132
142
  {
@@ -83,7 +83,11 @@
83
83
  // @desc Group label color
84
84
  --_color: var(--ui-sidebar-nav-group-label-color, var(--ui-color-text-muted));
85
85
  // @desc Group label weight
86
- --_weight: var(--ui-sidebar-nav-group-label-weight, var(--ui-font-weight-bold));
86
+ --_weight: var(--ui-sidebar-nav-group-label-weight, var(--ui-font-weight-semibold));
87
+ // @desc Group label text-transform
88
+ --_transform: var(--ui-sidebar-nav-group-label-transform, none);
89
+ // @desc Group label letter-spacing
90
+ --_letter-spacing: var(--ui-sidebar-nav-group-label-letter-spacing, normal);
87
91
 
88
92
  display: block;
89
93
 
@@ -92,8 +96,8 @@
92
96
 
93
97
  font-size: var(--_font-size);
94
98
  font-weight: var(--_weight);
95
- letter-spacing: #{t.$letter-spacing-wide};
96
- text-transform: uppercase;
99
+ letter-spacing: var(--_letter-spacing);
100
+ text-transform: var(--_transform);
97
101
  color: var(--_color);
98
102
  }
99
103
 
@@ -156,12 +160,14 @@
156
160
  min-block-size: var(--_height);
157
161
  padding-inline: var(--_padding-inline);
158
162
 
163
+ font-family: inherit;
159
164
  font-size: var(--_font-size);
160
165
  font-weight: var(--_weight, normal);
161
166
  text-decoration: none;
162
167
  color: var(--_color);
163
168
 
164
169
  background: var(--_bg);
170
+ border: none;
165
171
  border-radius: var(--_radius);
166
172
  cursor: pointer;
167
173
 
@@ -187,11 +193,11 @@
187
193
  // Active state
188
194
  .sidebar-nav__item--active {
189
195
  // @desc Item active bg
190
- --_bg: var(--ui-sidebar-nav-item-active-bg, var(--ui-color-primary-subtle));
196
+ --_bg: var(--ui-sidebar-nav-item-active-bg, var(--ui-color-bg-muted));
191
197
  // @desc Item active color
192
- --_color: var(--ui-sidebar-nav-item-active-color, var(--ui-color-primary-hover));
198
+ --_color: var(--ui-sidebar-nav-item-active-color, var(--ui-color-primary));
193
199
  // @desc Item active weight
194
- --_weight: var(--ui-sidebar-nav-item-active-weight, var(--ui-font-weight-medium));
200
+ --_weight: var(--ui-sidebar-nav-item-active-weight, normal);
195
201
  }
196
202
 
197
203
  // Nested item indent
@@ -1,6 +1,14 @@
1
1
  {
2
2
  "name": "display",
3
3
  "type": "utility",
4
- "utilities": ["flex", "justify-between", "items-center", "gap-2", "p-2"],
4
+ "utilities": [
5
+ "flex",
6
+ "justify-between",
7
+ "items-center",
8
+ "gap-2",
9
+ "p-2",
10
+ "container-inline",
11
+ "container-normal"
12
+ ],
5
13
  "cssVars": []
6
14
  }
@@ -174,6 +174,15 @@
174
174
  visibility: hidden;
175
175
  }
176
176
 
177
+ // Container query types
178
+ .container-inline {
179
+ container-type: inline-size;
180
+ }
181
+
182
+ .container-normal {
183
+ container-type: normal;
184
+ }
185
+
177
186
  // Screen reader only - visually hidden but accessible
178
187
  .sr-only {
179
188
  position: absolute;
@@ -22,6 +22,15 @@ description: Flexbox and display utilities.
22
22
  <span>{{ t('row_3', 'Row 3') }}</span>
23
23
  </div>
24
24
 
25
+ <!-- @container_queries | row -->
26
+ <!-- Make an element a container query context. -->
27
+ <div class="ui-container-inline ui-bg-muted ui-p-2">
28
+ <span class="ui-text-sm">{{ t('container_inline_desc', 'container-inline: enables inline-size container queries on children') }}</span>
29
+ </div>
30
+ <div class="ui-container-normal ui-bg-muted ui-p-2">
31
+ <span class="ui-text-sm">{{ t('container_normal_desc', 'container-normal: named container without size containment') }}</span>
32
+ </div>
33
+
25
34
  <!-- @visibility | row -->
26
35
  <span class="ui-visible ui-p-1 ui-bg-muted">{{ t('visible', 'Visible') }}</span>
27
36
  <span class="ui-invisible ui-p-1 ui-bg-muted">{{ t('invisible_hidden_but_occupies_space', 'Invisible (hidden but occupies space)') }}</span>
@@ -1,6 +1,25 @@
1
1
  {
2
2
  "name": "position",
3
3
  "type": "utility",
4
- "utilities": ["relative", "absolute", "overflow-hidden", "inset-0"],
4
+ "utilities": [
5
+ "relative",
6
+ "absolute",
7
+ "fixed",
8
+ "sticky",
9
+ "inset-0",
10
+ "top-0",
11
+ "bottom-0",
12
+ "start-0",
13
+ "end-0",
14
+ "top-2",
15
+ "bottom-2",
16
+ "start-2",
17
+ "end-2",
18
+ "z-10",
19
+ "z-20",
20
+ "z-50",
21
+ "overflow-hidden",
22
+ "overflow-auto"
23
+ ],
5
24
  "cssVars": []
6
25
  }
@@ -9,6 +9,13 @@ description: Position, overflow, and inset utilities for controlling element pla
9
9
  <div class="ui-absolute ui-top-0 ui-end-0 ui-bg-subtle ui-p-1">{{ t('absolute_top_end', 'Absolute top-end') }}</div>
10
10
  <div class="ui-absolute ui-bottom-0 ui-start-0 ui-bg-subtle ui-p-1">{{ t('absolute_bottom_start', 'Absolute bottom-start') }}</div>
11
11
  </div>
12
+ <div class="ui-sticky ui-top-0 ui-bg-muted ui-p-2">
13
+ <span class="ui-text-sm">{{ t('sticky_element', 'Sticky element (sticks to top on scroll)') }}</span>
14
+ </div>
15
+ <div class="ui-relative ui-overflow-hidden ui-bg-muted" style="block-size: var(--ui-row-4); transform: translate(0)">
16
+ <div class="ui-fixed ui-top-0 ui-start-0 ui-bg-subtle ui-p-1">{{ t('fixed_in_container', 'Fixed (contained by transform parent)') }}</div>
17
+ </div>
18
+ <p class="ui-text-sm ui-text-muted">{{ t('position_classes', 'Also available: ui-static') }}</p>
12
19
 
13
20
  <!-- @inset | row -->
14
21
  <!-- Pin element to all edges or specific sides. -->
@@ -19,6 +26,24 @@ description: Position, overflow, and inset utilities for controlling element pla
19
26
  <div class="ui-absolute ui-inset-block-0 ui-start-0 ui-bg-subtle ui-p-2">{{ t('inset_block_0_start_0', 'inset-block-0 + start-0') }}</div>
20
27
  </div>
21
28
 
29
+ <!-- @inset-scale | row -->
30
+ <!-- Offset from edges using space tokens (1-4). -->
31
+ <div class="ui-relative ui-bg-muted" style="block-size: var(--ui-row-4)">
32
+ <div class="ui-absolute ui-top-1 ui-end-1 ui-bg-subtle ui-p-1">{{ t('top_1_end_1', 'top-1 end-1') }}</div>
33
+ <div class="ui-absolute ui-bottom-2 ui-start-2 ui-bg-subtle ui-p-1">{{ t('bottom_2_start_2', 'bottom-2 start-2') }}</div>
34
+ </div>
35
+ <div class="ui-relative ui-bg-muted" style="block-size: var(--ui-row-4)">
36
+ <div class="ui-absolute ui-top-0 ui-end-2 ui-bg-subtle ui-p-1">{{ t('top_0_end_2', 'top-0 end-2') }}</div>
37
+ </div>
38
+
39
+ <!-- @z-index | row -->
40
+ <!-- Control stacking order. Scale: 0, 10, 20, 30, 40, 50. -->
41
+ <div class="ui-relative ui-bg-muted" style="block-size: var(--ui-row-4)">
42
+ <div class="ui-absolute ui-top-1 ui-start-1 ui-z-10 ui-bg-subtle ui-p-1">{{ t('z_10', 'z-10') }}</div>
43
+ <div class="ui-absolute ui-top-2 ui-start-2 ui-z-20 ui-bg ui-p-1 ui-rounded">{{ t('z_20_on_top', 'z-20 on top') }}</div>
44
+ <div class="ui-absolute ui-top-3 ui-start-3 ui-z-50 ui-bg-subtle ui-p-1 ui-rounded">{{ t('z_50_highest', 'z-50 highest') }}</div>
45
+ </div>
46
+
22
47
  <!-- @overflow | row -->
23
48
  <!-- Control overflow behavior. -->
24
49
  <div class="ui-overflow-hidden ui-bg-muted ui-p-2" style="block-size: var(--ui-row-3)">
@@ -35,20 +35,51 @@
35
35
  inset-inline: 0;
36
36
  }
37
37
 
38
- .top-0 {
39
- inset-block-start: 0;
38
+ @each $n in (0, 1, 2, 3, 4) {
39
+ .top-#{$n} {
40
+ inset-block-start: if($n == 0, 0, var(--ui-space-#{$n}));
41
+ }
42
+
43
+ .bottom-#{$n} {
44
+ inset-block-end: if($n == 0, 0, var(--ui-space-#{$n}));
45
+ }
46
+
47
+ .start-#{$n} {
48
+ inset-inline-start: if($n == 0, 0, var(--ui-space-#{$n}));
49
+ }
50
+
51
+ .end-#{$n} {
52
+ inset-inline-end: if($n == 0, 0, var(--ui-space-#{$n}));
53
+ }
54
+ }
55
+
56
+ // Z-index
57
+ .z-0 {
58
+ z-index: 0;
59
+ }
60
+
61
+ .z-10 {
62
+ z-index: 10;
63
+ }
64
+
65
+ .z-20 {
66
+ z-index: 20;
67
+ }
68
+
69
+ .z-30 {
70
+ z-index: 30;
40
71
  }
41
72
 
42
- .bottom-0 {
43
- inset-block-end: 0;
73
+ .z-40 {
74
+ z-index: 40;
44
75
  }
45
76
 
46
- .start-0 {
47
- inset-inline-start: 0;
77
+ .z-50 {
78
+ z-index: 50;
48
79
  }
49
80
 
50
- .end-0 {
51
- inset-inline-end: 0;
81
+ .z-auto {
82
+ z-index: auto;
52
83
  }
53
84
 
54
85
  // Overflow