@fluixi-ui/tokens 0.4.0-alpha.8 → 0.4.0-alpha.9

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.
@@ -1,20 +1,24 @@
1
1
  @layer flx.components {
2
- /* Image (from @fluixi-ui/image). A sized box that layers the <img>, a loading
3
- placeholder, and an error fallback; give it a width/height or aspect ratio. */
2
+ /* Image (from @fluixi-ui/image). A box that reserves the image's space and layers
3
+ a loading placeholder / blur-up and an error fallback over the <img>. Size it via
4
+ a width/height, an aspect-ratio, or a sized parent — the <img> fills it. */
4
5
  :where([data-image]) {
5
6
  position: relative;
6
7
  display: inline-block;
7
8
  overflow: hidden;
8
- background: var(--flx-ui-color-bg-subtle);
9
9
  line-height: 0;
10
+ vertical-align: middle;
11
+ background: var(--flx-ui-color-bg-subtle);
12
+ color: var(--flx-ui-color-fg-subtle);
13
+ --flx-ui-image-fallback-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M21 3H3a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2Zm0 16H3V5h18v14ZM8.5 13.5l2 2.41L13.5 12l4 5.5H6.5l2-4Z'/%3E%3C/svg%3E");
10
14
  }
11
- :where([data-image] > *) {
12
- position: absolute;
13
- inset: 0;
15
+
16
+ /* The image stays in normal flow so the box reserves its footprint (and keeps its
17
+ height when the source errors); object-fit crops it to a sized box. */
18
+ :where([data-image-img]) {
19
+ display: block;
14
20
  width: 100%;
15
21
  height: 100%;
16
- }
17
- :where([data-image-img]) {
18
22
  object-fit: cover;
19
23
  opacity: 0;
20
24
  transition: opacity var(--flx-ui-duration-normal) var(--flx-ui-ease-standard);
@@ -23,13 +27,41 @@
23
27
  opacity: 1;
24
28
  }
25
29
  :where([data-image][data-status='error'] [data-image-img]) {
26
- display: none;
30
+ opacity: 0;
31
+ }
32
+
33
+ /* Overlays — blur-up, custom placeholder, and the error fallback — fill the box. */
34
+ :where([data-image-blur], [data-image-placeholder], [data-image-fallback]) {
35
+ position: absolute;
36
+ inset: 0;
37
+ width: 100%;
38
+ height: 100%;
27
39
  }
28
- /* Blur-up (LQIP): a scaled, blurred version shown until the image loads. */
29
40
  :where([data-image-blur]) {
30
41
  background-size: cover;
31
42
  background-position: center;
32
43
  filter: blur(12px);
33
44
  transform: scale(1.1);
34
45
  }
46
+
47
+ /* Default error fallback: a centered picture glyph on the subtle surface. Passing a
48
+ custom `fallback` element replaces it entirely. */
49
+ :where([data-image-fallback]) {
50
+ display: flex;
51
+ align-items: center;
52
+ justify-content: center;
53
+ background: var(--flx-ui-color-bg-subtle);
54
+ color: var(--flx-ui-color-fg-subtle);
55
+ }
56
+ :where([data-image-fallback])::before {
57
+ content: "";
58
+ width: 45%;
59
+ height: 45%;
60
+ max-width: 28px;
61
+ max-height: 28px;
62
+ background: currentColor;
63
+ opacity: 0.55;
64
+ -webkit-mask: center / contain no-repeat var(--flx-ui-image-fallback-glyph);
65
+ mask: center / contain no-repeat var(--flx-ui-image-fallback-glyph);
66
+ }
35
67
  }
@@ -0,0 +1,10 @@
1
+ @layer flx.components {
2
+ /* ----------------------------------------------------------------------------
3
+ * Layout primitives (Stack / Grid / Container) — the geometry is set inline per
4
+ * instance; this only guarantees a predictable box model.
5
+ * ------------------------------------------------------------------------- */
6
+ :where([data-stack], [data-grid], [data-container]) {
7
+ box-sizing: border-box;
8
+ min-width: 0;
9
+ }
10
+ }
@@ -89,10 +89,15 @@
89
89
  border-color: var(--flx-ui-color-primary);
90
90
  }
91
91
  :where([data-mode='multiple'] [role='option'][data-selected] > [data-select-item-indicator])::after {
92
- content: '✓';
93
- color: var(--flx-ui-color-primary-fg);
94
- font-size: 0.7rem;
95
- line-height: 1;
92
+ content: '';
93
+ box-sizing: content-box;
94
+ flex: none;
95
+ width: 4px;
96
+ height: 8px;
97
+ margin-top: -2px;
98
+ border: solid var(--flx-ui-color-primary-fg);
99
+ border-width: 0 2px 2px 0;
100
+ transform: rotate(45deg);
96
101
  }
97
102
  :where([data-mode='multiple'] [role='option'][data-selected])::after {
98
103
  content: none;
@@ -0,0 +1,40 @@
1
+ @layer flx.components {
2
+ /* ----------------------------------------------------------------------------
3
+ * PIN / OTP input — a row of single-character cells
4
+ * ------------------------------------------------------------------------- */
5
+ :where([data-pin-input]) {
6
+ display: inline-flex;
7
+ align-items: center;
8
+ gap: var(--flx-ui-pin-gap, var(--flx-ui-space-2));
9
+ }
10
+ :where([data-pin-input-field]) {
11
+ box-sizing: border-box;
12
+ width: var(--flx-ui-pin-size, 2.75rem);
13
+ height: var(--flx-ui-pin-size, 2.75rem);
14
+ padding: 0;
15
+ text-align: center;
16
+ font: inherit;
17
+ font-size: var(--flx-ui-font-size-lg);
18
+ font-weight: var(--flx-ui-font-weight-medium);
19
+ font-variant-numeric: tabular-nums;
20
+ color: var(--flx-ui-color-fg);
21
+ background: var(--flx-ui-color-bg);
22
+ border: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border-strong);
23
+ border-radius: var(--flx-ui-radius-md);
24
+ transition:
25
+ border-color var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
26
+ box-shadow var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
27
+ }
28
+ :where([data-pin-input-field]::placeholder) {
29
+ color: var(--flx-ui-color-fg-muted);
30
+ }
31
+ :where([data-pin-input-field]:focus-visible) {
32
+ outline: none;
33
+ border-color: var(--flx-ui-color-focus-ring);
34
+ box-shadow: var(--flx-ui-ctl-ring);
35
+ }
36
+ :where([data-pin-input-field]:disabled) {
37
+ opacity: var(--flx-ui-opacity-disabled, 0.5);
38
+ cursor: not-allowed;
39
+ }
40
+ }
@@ -37,4 +37,60 @@
37
37
  0% { transform: translateX(-100%); }
38
38
  100% { transform: translateX(250%); }
39
39
  }
40
+
41
+ /* ----------------------------------------------------------------------------
42
+ * Circular progress
43
+ * ------------------------------------------------------------------------- */
44
+ :where([data-circular]) {
45
+ position: relative;
46
+ /* Stack the ring and any centred label in a single grid cell. */
47
+ display: inline-grid;
48
+ place-items: center;
49
+ vertical-align: middle;
50
+ /* Undo the linear bar's box styling that keys off [role='progressbar']
51
+ (fixed 6px height / 240px width / clipped overflow / filled track). */
52
+ width: auto;
53
+ height: auto;
54
+ overflow: visible;
55
+ background: none;
56
+ border-radius: 0;
57
+ }
58
+ :where([data-circular]) > * {
59
+ grid-area: 1 / 1;
60
+ }
61
+ :where([data-circular] [data-progress-svg]) {
62
+ display: block;
63
+ /* Start the arc at 12 o'clock rather than 3 o'clock. */
64
+ transform: rotate(-90deg);
65
+ }
66
+ :where([data-progress-track]) {
67
+ fill: none;
68
+ stroke: var(--flx-ui-color-bg-muted);
69
+ }
70
+ :where([data-progress-indicator]) {
71
+ fill: none;
72
+ stroke: var(--flx-ui-color-primary);
73
+ stroke-linecap: round;
74
+ transition: stroke-dashoffset var(--flx-ui-duration-normal) var(--flx-ui-ease-standard);
75
+ }
76
+ /* Indeterminate: a short arc that sweeps around the ring. */
77
+ :where([data-circular][data-state='indeterminate'] [data-progress-svg]) {
78
+ animation: flx-ui-circular-spin 0.9s linear infinite;
79
+ }
80
+ :where([data-circular][data-state='indeterminate'] [data-progress-indicator]) {
81
+ stroke-dasharray: 25 200;
82
+ transition: none;
83
+ }
84
+ @media (prefers-reduced-motion: reduce) {
85
+ :where([data-circular][data-state='indeterminate'] [data-progress-svg]) {
86
+ animation: none;
87
+ }
88
+ :where([data-circular][data-state='indeterminate'] [data-progress-indicator]) {
89
+ stroke-dasharray: none;
90
+ opacity: 0.5;
91
+ }
92
+ }
93
+ @keyframes flx-ui-circular-spin {
94
+ to { transform: rotate(270deg); }
95
+ }
40
96
  }
@@ -0,0 +1,59 @@
1
+ @layer flx.components {
2
+ /* ----------------------------------------------------------------------------
3
+ * Rating
4
+ *
5
+ * Each item is a star silhouette (mask) painted in the "empty" colour; a
6
+ * ::before overlay paints the "filled" colour, revealed left-to-right via
7
+ * clip-path by the item's data-state (empty / half / full).
8
+ * ------------------------------------------------------------------------- */
9
+ :where([data-rating]) {
10
+ --flx-ui-star: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.2l2.9 6.5 7 .6-5.3 4.6 1.6 6.9L12 17.7 5.8 21.4l1.6-6.9L2 9.9l7-.6z'/%3E%3C/svg%3E");
11
+ display: inline-flex;
12
+ align-items: center;
13
+ gap: var(--flx-ui-rating-gap, 2px);
14
+ outline: none;
15
+ }
16
+ :where([data-rating]:not([data-disabled]):not([data-readonly])) {
17
+ cursor: pointer;
18
+ }
19
+ :where([data-rating]:focus-visible) {
20
+ border-radius: var(--flx-ui-radius-sm);
21
+ box-shadow: var(--flx-ui-ctl-ring);
22
+ }
23
+ :where([data-rating][data-disabled]) {
24
+ opacity: var(--flx-ui-opacity-disabled, 0.5);
25
+ cursor: not-allowed;
26
+ }
27
+
28
+ :where([data-rating-item]) {
29
+ position: relative;
30
+ display: inline-block;
31
+ width: var(--flx-ui-rating-size, 20px);
32
+ height: var(--flx-ui-rating-size, 20px);
33
+ flex: none;
34
+ background: var(--flx-ui-color-border-strong);
35
+ -webkit-mask: var(--flx-ui-star) center / contain no-repeat;
36
+ mask: var(--flx-ui-star) center / contain no-repeat;
37
+ }
38
+ :where([data-rating-item])::before {
39
+ content: '';
40
+ position: absolute;
41
+ inset: 0;
42
+ background: var(--flx-ui-rating-color, var(--flx-ui-color-primary));
43
+ -webkit-mask: var(--flx-ui-star) center / contain no-repeat;
44
+ mask: var(--flx-ui-star) center / contain no-repeat;
45
+ clip-path: inset(0 100% 0 0);
46
+ transition: clip-path var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
47
+ }
48
+ :where([data-rating-item][data-state='full'])::before {
49
+ clip-path: inset(0 0 0 0);
50
+ }
51
+ :where([data-rating-item][data-state='half'])::before {
52
+ clip-path: inset(0 50% 0 0);
53
+ }
54
+ @media (prefers-reduced-motion: reduce) {
55
+ :where([data-rating-item])::before {
56
+ transition: none;
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,44 @@
1
+ @layer flx.components {
2
+ /* ----------------------------------------------------------------------------
3
+ * Scroll area — a scroll container with slim, theme-aware scrollbars styled over
4
+ * the native scrollbar (Firefox `scrollbar-*` + WebKit `::-webkit-scrollbar`).
5
+ * ------------------------------------------------------------------------- */
6
+ :where([data-scroll-area]) {
7
+ position: relative;
8
+ scrollbar-width: thin;
9
+ scrollbar-color: var(--flx-ui-color-border-strong) transparent;
10
+ overscroll-behavior: contain;
11
+ }
12
+ :where([data-scroll-area][data-orientation='vertical']) {
13
+ overflow-y: auto;
14
+ overflow-x: hidden;
15
+ }
16
+ :where([data-scroll-area][data-orientation='horizontal']) {
17
+ overflow-x: auto;
18
+ overflow-y: hidden;
19
+ }
20
+ :where([data-scroll-area][data-orientation='both']) {
21
+ overflow: auto;
22
+ }
23
+ :where([data-scroll-area])::-webkit-scrollbar {
24
+ width: 10px;
25
+ height: 10px;
26
+ }
27
+ :where([data-scroll-area])::-webkit-scrollbar-track {
28
+ background: transparent;
29
+ }
30
+ :where([data-scroll-area])::-webkit-scrollbar-thumb {
31
+ background: var(--flx-ui-color-border-strong);
32
+ border-radius: var(--flx-ui-radius-full);
33
+ /* Inset the thumb with a transparent border so it reads as a slim pill. */
34
+ border: 2px solid transparent;
35
+ background-clip: content-box;
36
+ }
37
+ :where([data-scroll-area])::-webkit-scrollbar-thumb:hover {
38
+ background: var(--flx-ui-color-fg-muted);
39
+ background-clip: content-box;
40
+ }
41
+ :where([data-scroll-area])::-webkit-scrollbar-corner {
42
+ background: transparent;
43
+ }
44
+ }
@@ -42,7 +42,7 @@
42
42
  left: 0;
43
43
  width: 100%;
44
44
  }
45
- :where([role='slider']) {
45
+ :where([data-slider] [role='slider']) {
46
46
  position: absolute;
47
47
  width: 16px;
48
48
  height: 16px;
@@ -52,15 +52,15 @@
52
52
  box-shadow: var(--flx-ui-shadow-sm);
53
53
  cursor: grab;
54
54
  }
55
- :where([role='slider'][data-orientation='horizontal']) {
55
+ :where([data-slider] [role='slider'][data-orientation='horizontal']) {
56
56
  top: 50%;
57
57
  transform: translate(-50%, -50%);
58
58
  }
59
- :where([role='slider'][data-orientation='vertical']) {
59
+ :where([data-slider] [role='slider'][data-orientation='vertical']) {
60
60
  left: 50%;
61
61
  transform: translate(-50%, 50%);
62
62
  }
63
- :where([role='slider']:focus-visible) {
63
+ :where([data-slider] [role='slider']:focus-visible) {
64
64
  outline: none;
65
65
  box-shadow: var(--flx-ui-ctl-ring);
66
66
  }
@@ -0,0 +1,85 @@
1
+ @layer flx.components {
2
+ /* ----------------------------------------------------------------------------
3
+ * Speed dial — a FAB trigger with actions that fan out in a direction.
4
+ * ------------------------------------------------------------------------- */
5
+ :where([data-speed-dial]) {
6
+ position: relative;
7
+ display: inline-flex;
8
+ width: max-content;
9
+ }
10
+ :where([data-speed-dial-actions]) {
11
+ position: absolute;
12
+ display: flex;
13
+ gap: var(--flx-ui-space-3);
14
+ align-items: center;
15
+ opacity: 1;
16
+ transition: opacity var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
17
+ }
18
+ /* Off by default — the actions float bare. `filled` opts into a surface. */
19
+ :where([data-speed-dial-actions][data-filled]) {
20
+ gap: var(--flx-ui-space-2);
21
+ padding: var(--flx-ui-space-2);
22
+ background: var(--flx-ui-color-bg);
23
+ border: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
24
+ border-radius: var(--flx-ui-radius-lg);
25
+ box-shadow: var(--flx-ui-shadow-lg);
26
+ }
27
+ /* Hidden (and unfocusable) until the dial opens. */
28
+ :where([data-speed-dial][data-state='closed']) [data-speed-dial-actions] {
29
+ visibility: hidden;
30
+ opacity: 0;
31
+ pointer-events: none;
32
+ }
33
+
34
+ /* Fan-out direction, anchored to the trigger. */
35
+ :where([data-speed-dial][data-direction='up']) [data-speed-dial-actions] {
36
+ flex-direction: column-reverse;
37
+ bottom: 100%;
38
+ left: 50%;
39
+ transform: translateX(-50%);
40
+ margin-bottom: var(--flx-ui-space-3);
41
+ }
42
+ :where([data-speed-dial][data-direction='down']) [data-speed-dial-actions] {
43
+ flex-direction: column;
44
+ top: 100%;
45
+ left: 50%;
46
+ transform: translateX(-50%);
47
+ margin-top: var(--flx-ui-space-3);
48
+ }
49
+ :where([data-speed-dial][data-direction='left']) [data-speed-dial-actions] {
50
+ flex-direction: row-reverse;
51
+ right: 100%;
52
+ top: 50%;
53
+ transform: translateY(-50%);
54
+ margin-right: var(--flx-ui-space-3);
55
+ }
56
+ :where([data-speed-dial][data-direction='right']) [data-speed-dial-actions] {
57
+ flex-direction: row;
58
+ left: 100%;
59
+ top: 50%;
60
+ transform: translateY(-50%);
61
+ margin-left: var(--flx-ui-space-3);
62
+ }
63
+
64
+ /* An action + its optional label. */
65
+ :where([data-speed-dial-action-wrap]) {
66
+ display: inline-flex;
67
+ align-items: center;
68
+ gap: var(--flx-ui-space-2);
69
+ }
70
+ /* For vertical directions the label reads to the left of the button. */
71
+ :where([data-speed-dial][data-direction='down']) [data-speed-dial-action-wrap],
72
+ :where([data-speed-dial][data-direction='up']) [data-speed-dial-action-wrap] {
73
+ flex-direction: row-reverse;
74
+ }
75
+ :where([data-speed-dial-action-label]) {
76
+ padding: 2px var(--flx-ui-space-2);
77
+ border-radius: var(--flx-ui-radius-sm);
78
+ background: var(--flx-ui-color-fg);
79
+ color: var(--flx-ui-color-bg);
80
+ font-size: var(--flx-ui-font-size-xs);
81
+ font-weight: var(--flx-ui-font-weight-medium);
82
+ white-space: nowrap;
83
+ box-shadow: var(--flx-ui-shadow-sm);
84
+ }
85
+ }
@@ -0,0 +1,34 @@
1
+ @layer flx.components {
2
+ /* Statistic (from @fluixi-ui/statistic). A KPI: caption, big value, and an
3
+ optional delta line coloured by the container's data-trend. */
4
+ :where([data-statistic]) {
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: var(--flx-ui-space-1);
8
+ min-width: 0;
9
+ }
10
+ :where([data-statistic-label]) {
11
+ font-size: var(--flx-ui-font-size-xs);
12
+ font-weight: var(--flx-ui-font-weight-medium);
13
+ color: var(--flx-ui-color-fg-subtle);
14
+ letter-spacing: var(--flx-ui-letter-spacing-wide);
15
+ text-transform: uppercase;
16
+ }
17
+ :where([data-statistic-value]) {
18
+ font-size: var(--flx-ui-font-size-2xl);
19
+ font-weight: var(--flx-ui-font-weight-bold);
20
+ color: var(--flx-ui-color-fg);
21
+ line-height: 1.1;
22
+ font-variant-numeric: tabular-nums;
23
+ }
24
+ :where([data-statistic-delta]) {
25
+ display: inline-flex;
26
+ align-items: center;
27
+ gap: var(--flx-ui-space-1);
28
+ font-size: var(--flx-ui-font-size-xs);
29
+ font-weight: var(--flx-ui-font-weight-semibold);
30
+ color: var(--flx-ui-color-fg-subtle);
31
+ }
32
+ :where([data-statistic][data-trend='up'] [data-statistic-delta]) { color: var(--flx-ui-color-success); }
33
+ :where([data-statistic][data-trend='down'] [data-statistic-delta]) { color: var(--flx-ui-color-danger); }
34
+ }
@@ -0,0 +1,59 @@
1
+ @layer flx.components {
2
+ /* Timeline (from @fluixi-ui/timeline). A vertical feed: each item is an indicator
3
+ column (dot) beside its content; a connector line threads between the dots. */
4
+ :where([data-timeline]) {
5
+ display: flex;
6
+ flex-direction: column;
7
+ }
8
+ :where([data-timeline-item]) {
9
+ display: grid;
10
+ grid-template-columns: auto 1fr;
11
+ column-gap: var(--flx-ui-space-3);
12
+ --flx-timeline-dot: var(--flx-ui-color-border-strong);
13
+ }
14
+ :where([data-timeline-item][data-tone='primary']),
15
+ :where([data-timeline-item][data-tone='info']) { --flx-timeline-dot: var(--flx-ui-color-primary); }
16
+ :where([data-timeline-item][data-tone='success']) { --flx-timeline-dot: var(--flx-ui-color-success); }
17
+ :where([data-timeline-item][data-tone='warning']) { --flx-timeline-dot: var(--flx-ui-color-warning); }
18
+ :where([data-timeline-item][data-tone='danger']) { --flx-timeline-dot: var(--flx-ui-color-danger); }
19
+
20
+ /* Indicator column: the dot, with the connector line drawn below it. */
21
+ :where([data-timeline-indicator]) {
22
+ position: relative;
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: center;
26
+ width: 18px;
27
+ padding-top: 2px;
28
+ color: var(--flx-timeline-dot);
29
+ }
30
+ /* Default dot (when no custom `dot` content). */
31
+ :where([data-timeline-indicator]:empty)::before {
32
+ content: "";
33
+ width: 9px;
34
+ height: 9px;
35
+ border-radius: var(--flx-ui-radius-full);
36
+ background: var(--flx-timeline-dot);
37
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--flx-timeline-dot) 18%, transparent);
38
+ }
39
+ /* Connector line — hidden on the last item. */
40
+ :where([data-timeline-item]:not(:last-child) [data-timeline-indicator])::after {
41
+ content: "";
42
+ position: absolute;
43
+ top: 16px;
44
+ bottom: -6px;
45
+ left: 50%;
46
+ width: var(--flx-ui-border-width-thin);
47
+ transform: translateX(-50%);
48
+ background: var(--flx-ui-color-border);
49
+ }
50
+ :where([data-timeline-content]) {
51
+ min-width: 0;
52
+ padding-bottom: var(--flx-ui-space-4);
53
+ font-size: var(--flx-ui-font-size-sm);
54
+ color: var(--flx-ui-color-fg);
55
+ }
56
+ :where([data-timeline-item]:last-child [data-timeline-content]) {
57
+ padding-bottom: 0;
58
+ }
59
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../../src/lib/reference/colors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,eAAe,CAAC;AAE3D,4FAA4F;AAC5F,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAC9D,eAAO,MAAM,cAAc,EAAE,UAAmB,CAAC;AAEjD,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAsGpC,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQjE,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAwBjD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAUhF,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,KAAK,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,YAAY,CAc3E,CAAC"}
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../../src/lib/reference/colors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,eAAe,CAAC;AAE3D,4FAA4F;AAC5F,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAC9D,eAAO,MAAM,cAAc,EAAE,UAAmB,CAAC;AAEjD,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AA+GpC,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQjE,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA6BjD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAUhF,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,KAAK,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,YAAY,CAc3E,CAAC"}
@@ -66,23 +66,32 @@ const statusLight = {
66
66
  'danger-solid': '#e5484d',
67
67
  'danger-subtle': '#feebec',
68
68
  'danger-fg': '#ffffff',
69
+ // `-text`: a darker, saturated shade that stays legible ON the `-subtle`
70
+ // background (the solid shade is too light for text — notably amber).
71
+ 'danger-text': '#cd2b31',
69
72
  'success-solid': '#30a46c',
70
73
  'success-subtle': '#e6f6ec',
71
74
  'success-fg': '#ffffff',
75
+ 'success-text': '#18794e',
72
76
  'warning-solid': '#ffb224',
73
77
  'warning-subtle': '#fff4d5',
74
78
  'warning-fg': '#1c2024',
79
+ 'warning-text': '#ad5700',
75
80
  };
76
81
  const statusDark = {
77
82
  'danger-solid': '#ff6369',
78
83
  'danger-subtle': '#3b1219',
79
84
  'danger-fg': '#ffffff',
85
+ // On dark, `-text` is a bright shade legible on the dark `-subtle` bg.
86
+ 'danger-text': '#ff9592',
80
87
  'success-solid': '#3dd68c',
81
88
  'success-subtle': '#0f291e',
82
89
  'success-fg': '#ffffff',
90
+ 'success-text': '#4cc38a',
83
91
  'warning-solid': '#ffca16',
84
92
  'warning-subtle': '#3a2e00',
85
93
  'warning-fg': '#1c2024',
94
+ 'warning-text': '#ffca16',
86
95
  };
87
96
  function scaleRecord(gray, accent, status) {
88
97
  const out = {};
@@ -111,15 +120,20 @@ export const semanticColors = {
111
120
  'color-primary-active': 'var(--flx-ui-accent-11)',
112
121
  'color-primary-fg': '#ffffff',
113
122
  'color-primary-subtle': 'var(--flx-ui-accent-3)',
123
+ // Legible text shade for a tinted (subtle) background.
124
+ 'color-primary-text': 'var(--flx-ui-accent-11)',
114
125
  'color-danger': 'var(--flx-ui-danger-solid)',
115
126
  'color-danger-fg': 'var(--flx-ui-danger-fg)',
116
127
  'color-danger-subtle': 'var(--flx-ui-danger-subtle)',
128
+ 'color-danger-text': 'var(--flx-ui-danger-text)',
117
129
  'color-success': 'var(--flx-ui-success-solid)',
118
130
  'color-success-fg': 'var(--flx-ui-success-fg)',
119
131
  'color-success-subtle': 'var(--flx-ui-success-subtle)',
132
+ 'color-success-text': 'var(--flx-ui-success-text)',
120
133
  'color-warning': 'var(--flx-ui-warning-solid)',
121
134
  'color-warning-fg': 'var(--flx-ui-warning-fg)',
122
135
  'color-warning-subtle': 'var(--flx-ui-warning-subtle)',
136
+ 'color-warning-text': 'var(--flx-ui-warning-text)',
123
137
  'color-overlay': 'rgba(0, 0, 0, 0.4)',
124
138
  };
125
139
  export const semanticOverrides = {
package/dist/preset.css CHANGED
@@ -10,7 +10,12 @@
10
10
  @layer flx.reset, flx.base, flx.tokens, flx.components, flx.skin;
11
11
 
12
12
  @import './css/base.css';
13
+ @import './css/layout.css';
14
+ @import './css/scroll-area.css';
13
15
  @import './css/button.css';
16
+ @import './css/icon-button.css';
17
+ @import './css/fab.css';
18
+ @import './css/speed-dial.css';
14
19
  @import './css/badge.css';
15
20
  @import './css/toggle.css';
16
21
  @import './css/toolbar.css';
@@ -18,6 +23,7 @@
18
23
  @import './css/field.css';
19
24
  @import './css/input.css';
20
25
  @import './css/number-field.css';
26
+ @import './css/pin-input.css';
21
27
  @import './css/tags-input.css';
22
28
  @import './css/image.css';
23
29
  @import './css/file-upload.css';
@@ -26,8 +32,12 @@
26
32
  @import './css/alert.css';
27
33
  @import './css/skeleton.css';
28
34
  @import './css/kbd.css';
35
+ @import './css/empty.css';
36
+ @import './css/statistic.css';
37
+ @import './css/descriptions.css';
29
38
  @import './css/switch.css';
30
39
  @import './css/checkbox-radio.css';
40
+ @import './css/rating.css';
31
41
  @import './css/tabs.css';
32
42
  @import './css/accordion.css';
33
43
  @import './css/progress.css';
@@ -35,12 +45,14 @@
35
45
  @import './css/separator.css';
36
46
  @import './css/breadcrumb.css';
37
47
  @import './css/pagination.css';
48
+ @import './css/timeline.css';
38
49
  @import './css/surface.css';
39
50
  @import './css/card.css';
40
51
  @import './css/glow.css';
41
52
  @import './css/aspect-ratio.css';
42
53
  @import './css/stepper.css';
43
54
  @import './css/select-combobox.css';
55
+ @import './css/field-variants.css';
44
56
  @import './css/parts/listbox.css';
45
57
  @import './css/parts/overlays.css';
46
58
  @import './css/drawer.css';