@mt-gloss/styles 0.0.3

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,163 @@
1
+ // ============================================
2
+ // COMPONENT: LINKS
3
+ // ============================================
4
+
5
+ @use '../tokens' as *;
6
+ @use '../mixins' as *;
7
+
8
+ .gloss-link {
9
+ display: inline-flex;
10
+ align-items: center;
11
+ gap: $space-1;
12
+ color: $alias-text-link;
13
+ font-family: $font-body;
14
+ font-size: $text-base;
15
+ font-weight: 500;
16
+ text-decoration: none;
17
+ cursor: pointer;
18
+ transition: color 0.2s ease, opacity 0.2s ease;
19
+ position: relative;
20
+
21
+ // Text span for underline effect
22
+ &__text {
23
+ position: relative;
24
+ }
25
+
26
+ // Icon slots
27
+ &__icon {
28
+ display: inline-flex;
29
+ flex-shrink: 0;
30
+ transition: transform 0.2s ease;
31
+
32
+ &--left {
33
+ margin-right: $space-1;
34
+ }
35
+
36
+ &--right {
37
+ margin-left: $space-1;
38
+ }
39
+ }
40
+
41
+ // Hover state
42
+ &:hover:not(.gloss-link--disabled) {
43
+ color: $color-blue-700;
44
+
45
+ .gloss-link__icon--right {
46
+ transform: translateX(2px);
47
+ }
48
+ }
49
+
50
+ // Active state
51
+ &:active:not(.gloss-link--disabled) {
52
+ color: $color-blue-800;
53
+ }
54
+
55
+ // Focus state
56
+ &:focus-visible {
57
+ outline: none;
58
+ border-radius: $radius-xs;
59
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.4);
60
+ }
61
+
62
+ // --- UNDERLINE VARIANTS ---
63
+ &--underline-always {
64
+ .gloss-link__text {
65
+ text-decoration: underline;
66
+ text-underline-offset: 2px;
67
+ text-decoration-thickness: 1px;
68
+ }
69
+ }
70
+
71
+ &--underline-hover {
72
+ .gloss-link__text {
73
+ background-image: linear-gradient(currentColor, currentColor);
74
+ background-position: 0% 100%;
75
+ background-repeat: no-repeat;
76
+ background-size: 0% 1px;
77
+ transition: background-size 0.2s ease;
78
+ }
79
+
80
+ &:hover:not(.gloss-link--disabled) .gloss-link__text {
81
+ background-size: 100% 1px;
82
+ }
83
+ }
84
+
85
+ &--underline-none {
86
+ .gloss-link__text {
87
+ text-decoration: none;
88
+ }
89
+ }
90
+
91
+ // --- SIZE VARIANTS ---
92
+ &--sm {
93
+ font-size: $text-sm;
94
+ gap: 2px;
95
+
96
+ .gloss-link__icon--left {
97
+ margin-right: 2px;
98
+ }
99
+
100
+ .gloss-link__icon--right {
101
+ margin-left: 2px;
102
+ }
103
+ }
104
+
105
+ &--lg {
106
+ font-size: $text-lg;
107
+ gap: $space-2;
108
+
109
+ .gloss-link__icon--left {
110
+ margin-right: $space-2;
111
+ }
112
+
113
+ .gloss-link__icon--right {
114
+ margin-left: $space-2;
115
+ }
116
+ }
117
+
118
+ // --- VARIANT: MUTED ---
119
+ &--muted {
120
+ color: $alias-text-secondary;
121
+
122
+ &:hover:not(.gloss-link--disabled) {
123
+ color: $alias-text-primary;
124
+ }
125
+
126
+ &:active:not(.gloss-link--disabled) {
127
+ color: $color-gray-800;
128
+ }
129
+ }
130
+
131
+ // --- VARIANT: DANGER ---
132
+ &--danger {
133
+ color: $color-red-500;
134
+
135
+ &:hover:not(.gloss-link--disabled) {
136
+ color: $color-red-600;
137
+ }
138
+
139
+ &:active:not(.gloss-link--disabled) {
140
+ color: $color-red-700;
141
+ }
142
+
143
+ &:focus-visible {
144
+ box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.4);
145
+ }
146
+ }
147
+
148
+ // --- DISABLED STATE ---
149
+ &--disabled {
150
+ color: $alias-text-tertiary;
151
+ cursor: not-allowed;
152
+ opacity: 0.6;
153
+
154
+ .gloss-link__text {
155
+ text-decoration: none;
156
+ background-size: 0% 1px !important;
157
+ }
158
+ }
159
+ }
160
+
161
+ // --- LINK IN BUTTON-LIKE CONTEXT ---
162
+ // When you want a link styled as a button, use Button component with as="a"
163
+ // This is specifically for inline text links
@@ -0,0 +1,339 @@
1
+ // ============================================
2
+ // COMPONENT: MENU
3
+ // Navigation menu with collapsible groups
4
+ // ============================================
5
+
6
+ @use '../tokens' as *;
7
+
8
+ // Animation variables
9
+ $menu-duration: 200ms;
10
+ $menu-easing: cubic-bezier(0.175, 0.885, 0.32, 1.275); // Spring easing
11
+ $menu-easing-out: cubic-bezier(0, 0, 0.2, 1);
12
+
13
+ // --- MENU CONTAINER ---
14
+ .gloss-menu {
15
+ display: flex;
16
+ flex-direction: column;
17
+ gap: $space-1;
18
+ }
19
+
20
+ // --- MENU GROUP ---
21
+ .gloss-menu-group {
22
+ display: flex;
23
+ flex-direction: column;
24
+
25
+ &--disabled {
26
+ opacity: 0.5;
27
+ pointer-events: none;
28
+ }
29
+
30
+ &--empty {
31
+ .gloss-menu-group__header {
32
+ cursor: default;
33
+
34
+ &:hover {
35
+ background-color: transparent;
36
+ }
37
+ }
38
+ }
39
+
40
+ // --- LEVEL-SPECIFIC STYLING ---
41
+ // Level 0: Top-level groups (UPPERCASE, secondary color)
42
+ &--level-0 {
43
+ > .gloss-menu-group__header {
44
+ .gloss-menu-group__label {
45
+ font-size: $text-xs;
46
+ font-weight: 700;
47
+ text-transform: uppercase;
48
+ letter-spacing: 0.05em;
49
+ color: $alias-text-secondary;
50
+ }
51
+ }
52
+ }
53
+
54
+ // Level 1: Second-level groups (Capitalized, smaller)
55
+ &--level-1 {
56
+ > .gloss-menu-group__header {
57
+ padding-left: $space-4;
58
+
59
+ .gloss-menu-group__label {
60
+ font-size: $text-sm;
61
+ font-weight: 600;
62
+ text-transform: none;
63
+ letter-spacing: normal;
64
+ color: $alias-text-secondary;
65
+ }
66
+ }
67
+ }
68
+
69
+ // Level 2: Third-level groups
70
+ &--level-2 {
71
+ > .gloss-menu-group__header {
72
+ padding-left: $space-4;
73
+
74
+ .gloss-menu-group__label {
75
+ font-size: $text-sm;
76
+ font-weight: 500;
77
+ text-transform: none;
78
+ color: $alias-text-tertiary;
79
+ }
80
+ }
81
+ }
82
+ }
83
+
84
+ // --- MENU GROUP HEADER ---
85
+ .gloss-menu-group__header {
86
+ display: flex;
87
+ align-items: center;
88
+ width: 100%;
89
+ padding: $space-3 $space-4;
90
+ background: transparent;
91
+ border: none;
92
+ border-radius: $radius-sm;
93
+ cursor: pointer;
94
+ font-family: $font-body;
95
+ text-align: left;
96
+ transition:
97
+ background-color 150ms $menu-easing-out,
98
+ transform 100ms $menu-easing;
99
+
100
+ &:hover:not(:disabled) {
101
+ background-color: $color-gray-50;
102
+ }
103
+
104
+ &:focus-visible {
105
+ outline: 2px solid $alias-border-focus;
106
+ outline-offset: 2px;
107
+ }
108
+
109
+ &:active:not(:disabled) {
110
+ transform: scale(0.98);
111
+ }
112
+
113
+ &:disabled {
114
+ cursor: not-allowed;
115
+ opacity: 0.5;
116
+ }
117
+ }
118
+
119
+ // Icon slot (left)
120
+ .gloss-menu-group__icon {
121
+ display: flex;
122
+ align-items: center;
123
+ justify-content: center;
124
+ margin-right: $space-3;
125
+ color: $alias-text-secondary;
126
+ flex-shrink: 0;
127
+
128
+ svg {
129
+ width: 18px;
130
+ height: 18px;
131
+ }
132
+ }
133
+
134
+ // Label
135
+ .gloss-menu-group__label {
136
+ flex: 1;
137
+ min-width: 0;
138
+ overflow: hidden;
139
+ text-overflow: ellipsis;
140
+ white-space: nowrap;
141
+ }
142
+
143
+ // Right-aligned container (count or chevron)
144
+ .gloss-menu-group__end {
145
+ display: flex;
146
+ align-items: center;
147
+ justify-content: center;
148
+ margin-left: auto;
149
+ flex-shrink: 0;
150
+ }
151
+
152
+ // Count badge
153
+ .gloss-menu-group__count {
154
+ display: inline-flex;
155
+ align-items: center;
156
+ justify-content: center;
157
+ min-width: 20px;
158
+ height: 20px;
159
+ padding: 0 $space-2;
160
+ background: $color-gray-800;
161
+ color: $color-white;
162
+ font-size: $text-xs;
163
+ font-weight: 600;
164
+ border-radius: $radius-full;
165
+ animation: menu-count-in 150ms $menu-easing-out forwards;
166
+ }
167
+
168
+ // Chevron icon
169
+ .gloss-menu-group__chevron {
170
+ display: flex;
171
+ align-items: center;
172
+ justify-content: center;
173
+ color: $alias-text-secondary;
174
+ transition: transform $menu-duration $menu-easing-out;
175
+
176
+ svg {
177
+ width: 16px;
178
+ height: 16px;
179
+ }
180
+ }
181
+
182
+ // --- MENU GROUP CONTENT ---
183
+ .gloss-menu-group__content {
184
+ display: grid;
185
+ grid-template-rows: 0fr;
186
+ opacity: 0;
187
+ transition:
188
+ grid-template-rows $menu-duration $menu-easing,
189
+ opacity 150ms $menu-easing-out;
190
+
191
+ &--expanded {
192
+ grid-template-rows: 1fr;
193
+ opacity: 1;
194
+ }
195
+ }
196
+
197
+ .gloss-menu-group__inner {
198
+ overflow: hidden;
199
+ display: flex;
200
+ flex-direction: column;
201
+ gap: $space-1;
202
+ padding-top: $space-1;
203
+ }
204
+
205
+ // --- OPEN STATE ---
206
+ .gloss-menu-group--open {
207
+ > .gloss-menu-group__header .gloss-menu-group__chevron {
208
+ transform: rotate(0deg);
209
+ }
210
+ }
211
+
212
+ // --- MENU ITEM ---
213
+ .gloss-menu-item {
214
+ display: flex;
215
+ align-items: center;
216
+ width: 100%;
217
+ padding: $space-2 $space-4;
218
+ background: transparent;
219
+ border: none;
220
+ border-radius: $radius-sm;
221
+ cursor: pointer;
222
+ font-family: $font-body;
223
+ font-size: $text-sm;
224
+ font-weight: 500;
225
+ color: $alias-text-primary;
226
+ text-align: left;
227
+ text-decoration: none;
228
+ transition:
229
+ background-color 150ms $menu-easing-out,
230
+ color 150ms $menu-easing-out,
231
+ transform 100ms $menu-easing;
232
+
233
+ &:hover:not(:disabled):not(.gloss-menu-item--disabled) {
234
+ background-color: $color-gray-50;
235
+ }
236
+
237
+ &:focus-visible {
238
+ outline: 2px solid $alias-border-focus;
239
+ outline-offset: 2px;
240
+ }
241
+
242
+ &:active:not(:disabled):not(.gloss-menu-item--disabled) {
243
+ transform: scale(0.98);
244
+ }
245
+
246
+ // Active state
247
+ &--active {
248
+ background-color: $color-blue-50;
249
+ color: $alias-primary;
250
+ font-weight: 600;
251
+
252
+ .gloss-menu-item__icon {
253
+ color: $alias-primary;
254
+ }
255
+
256
+ &:hover {
257
+ background-color: $color-blue-100;
258
+ }
259
+ }
260
+
261
+ // Disabled state
262
+ &--disabled {
263
+ cursor: not-allowed;
264
+ opacity: 0.5;
265
+ pointer-events: none;
266
+ }
267
+
268
+ // Level-specific styling (all items are flush left, differentiate by color/weight)
269
+ &--level-0 {
270
+ font-weight: 500;
271
+ color: $alias-text-primary;
272
+ }
273
+
274
+ &--level-1 {
275
+ padding-left: $space-4;
276
+ font-weight: 500;
277
+ color: $alias-text-primary;
278
+ }
279
+
280
+ &--level-2 {
281
+ padding-left: $space-4;
282
+ font-weight: 400;
283
+ color: $alias-text-secondary;
284
+ }
285
+ }
286
+
287
+ // Item icon
288
+ .gloss-menu-item__icon {
289
+ display: flex;
290
+ align-items: center;
291
+ justify-content: center;
292
+ margin-right: $space-3;
293
+ color: $alias-text-secondary;
294
+ flex-shrink: 0;
295
+
296
+ svg {
297
+ width: 18px;
298
+ height: 18px;
299
+ }
300
+ }
301
+
302
+ // Item label
303
+ .gloss-menu-item__label {
304
+ flex: 1;
305
+ min-width: 0;
306
+ overflow: hidden;
307
+ text-overflow: ellipsis;
308
+ white-space: nowrap;
309
+ }
310
+
311
+ // --- MENU DIVIDER ---
312
+ .gloss-menu-divider {
313
+ height: 1px;
314
+ margin: $space-2 $space-4;
315
+ background: $alias-border-default;
316
+ border: none;
317
+ }
318
+
319
+ // --- ANIMATION KEYFRAMES ---
320
+ @keyframes menu-count-in {
321
+ from {
322
+ opacity: 0;
323
+ transform: scale(0.8);
324
+ }
325
+ to {
326
+ opacity: 1;
327
+ transform: scale(1);
328
+ }
329
+ }
330
+
331
+ // --- REDUCED MOTION ---
332
+ @media (prefers-reduced-motion: reduce) {
333
+ .gloss-menu-group__header,
334
+ .gloss-menu-group__chevron,
335
+ .gloss-menu-group__content,
336
+ .gloss-menu-item {
337
+ transition-duration: 0.01ms !important;
338
+ }
339
+ }
@@ -0,0 +1,188 @@
1
+ // ============================================
2
+ // COMPONENT: SEGMENTED CONTROL
3
+ // ============================================
4
+
5
+ @use '../tokens' as *;
6
+ @use '../mixins' as *;
7
+
8
+ .gloss-segmented-control-wrapper {
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: $space-2;
12
+
13
+ &--disabled {
14
+ opacity: 0.6;
15
+ }
16
+ }
17
+
18
+ .gloss-segmented-control {
19
+ display: inline-flex;
20
+ align-items: center;
21
+ padding: 4px;
22
+ background: $color-gray-100;
23
+ border-radius: $radius-lg;
24
+ position: relative;
25
+ gap: 2px;
26
+
27
+ // --- SLIDING INDICATOR ---
28
+ &__indicator {
29
+ position: absolute;
30
+ top: 4px;
31
+ left: 0;
32
+ height: calc(100% - 8px);
33
+ background: $color-white;
34
+ border-radius: $radius-md;
35
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.04);
36
+ transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), width 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
37
+ z-index: 0;
38
+ }
39
+
40
+ // --- OPTION BUTTON ---
41
+ &__option {
42
+ position: relative;
43
+ z-index: 1;
44
+ display: inline-flex;
45
+ align-items: center;
46
+ justify-content: center;
47
+ gap: $space-2;
48
+ padding: $space-2 $space-4;
49
+ min-height: 36px;
50
+ background: transparent;
51
+ border: none;
52
+ border-radius: $radius-md;
53
+ font-family: $font-body;
54
+ font-size: $text-sm;
55
+ font-weight: 500;
56
+ color: $alias-text-secondary;
57
+ cursor: pointer;
58
+ white-space: nowrap;
59
+ transition: color 0.2s ease;
60
+
61
+ &:hover:not(:disabled):not(.gloss-segmented-control__option--selected) {
62
+ color: $alias-text-primary;
63
+ }
64
+
65
+ &:focus-visible {
66
+ outline: none;
67
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.4);
68
+ }
69
+
70
+ &--selected {
71
+ color: $alias-text-primary;
72
+ }
73
+
74
+ &--disabled {
75
+ color: $alias-text-tertiary;
76
+ cursor: not-allowed;
77
+ }
78
+ }
79
+
80
+ &__icon {
81
+ display: inline-flex;
82
+ flex-shrink: 0;
83
+ }
84
+
85
+ &__text {
86
+ display: inline-flex;
87
+ }
88
+
89
+ // --- LABEL ---
90
+ &__label {
91
+ font-size: $text-sm;
92
+ font-weight: 500;
93
+ color: $alias-text-primary;
94
+ }
95
+
96
+ // --- HELPER TEXT ---
97
+ &__helper {
98
+ display: flex;
99
+ align-items: center;
100
+ gap: $space-1;
101
+ font-size: $text-sm;
102
+ color: $alias-text-secondary;
103
+
104
+ &--error {
105
+ color: $alias-text-error;
106
+
107
+ svg {
108
+ color: $color-red-500;
109
+ }
110
+ }
111
+ }
112
+
113
+ // --- SIZE VARIANTS ---
114
+ &--sm {
115
+ padding: 3px;
116
+ border-radius: $radius-md;
117
+
118
+ .gloss-segmented-control__indicator {
119
+ top: 3px;
120
+ height: calc(100% - 6px);
121
+ border-radius: $radius-sm;
122
+ }
123
+
124
+ .gloss-segmented-control__option {
125
+ padding: $space-1 $space-3;
126
+ min-height: 28px;
127
+ font-size: $text-xs;
128
+ border-radius: $radius-sm;
129
+ }
130
+ }
131
+
132
+ &--lg {
133
+ padding: 5px;
134
+ border-radius: $radius-xl;
135
+
136
+ .gloss-segmented-control__indicator {
137
+ top: 5px;
138
+ height: calc(100% - 10px);
139
+ border-radius: $radius-lg;
140
+ }
141
+
142
+ .gloss-segmented-control__option {
143
+ padding: $space-3 $space-6;
144
+ min-height: 44px;
145
+ font-size: $text-base;
146
+ border-radius: $radius-lg;
147
+ gap: $space-3;
148
+ }
149
+ }
150
+
151
+ // --- FULL WIDTH ---
152
+ &--full-width {
153
+ display: flex;
154
+ width: 100%;
155
+
156
+ .gloss-segmented-control__option {
157
+ flex: 1;
158
+ }
159
+ }
160
+
161
+ // --- STATUS VARIANTS ---
162
+ &--success {
163
+ .gloss-segmented-control__indicator {
164
+ box-shadow: 0 1px 2px rgba(34, 197, 94, 0.1), 0 2px 4px rgba(34, 197, 94, 0.08), 0 0 0 1px rgba(34, 197, 94, 0.2);
165
+ }
166
+ }
167
+
168
+ &--error {
169
+ background: $alias-bg-error;
170
+
171
+ .gloss-segmented-control__indicator {
172
+ box-shadow: 0 1px 2px rgba(239, 68, 68, 0.1), 0 2px 4px rgba(239, 68, 68, 0.08), 0 0 0 1px rgba(239, 68, 68, 0.2);
173
+ }
174
+ }
175
+
176
+ // --- DISABLED STATE ---
177
+ &--disabled {
178
+ cursor: not-allowed;
179
+
180
+ .gloss-segmented-control__option {
181
+ cursor: not-allowed;
182
+ }
183
+
184
+ .gloss-segmented-control__indicator {
185
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
186
+ }
187
+ }
188
+ }