@fragments-sdk/ui 0.4.0 → 0.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/README.md +98 -2
- package/fragments.json +1 -1
- package/package.json +3 -2
- package/src/components/Accordion/Accordion.fragment.tsx +1 -1
- package/src/components/Alert/Alert.fragment.tsx +1 -1
- package/src/components/AppShell/AppShell.fragment.tsx +4 -4
- package/src/components/Avatar/Avatar.fragment.tsx +2 -2
- package/src/components/Badge/Badge.fragment.tsx +2 -2
- package/src/components/Badge/Badge.module.scss +1 -1
- package/src/components/Box/Box.fragment.tsx +1 -1
- package/src/components/Button/Button.fragment.tsx +2 -2
- package/src/components/ButtonGroup/ButtonGroup.fragment.tsx +153 -0
- package/src/components/Card/Card.fragment.tsx +1 -1
- package/src/components/Chart/Chart.fragment.tsx +213 -0
- package/src/components/Chart/Chart.module.scss +123 -0
- package/src/components/Chart/index.tsx +267 -0
- package/src/components/Checkbox/Checkbox.fragment.tsx +1 -1
- package/src/components/CodeBlock/CodeBlock.fragment.tsx +265 -6
- package/src/components/CodeBlock/CodeBlock.module.scss +141 -3
- package/src/components/CodeBlock/index.tsx +250 -36
- package/src/components/Collapsible/Collapsible.fragment.tsx +199 -0
- package/src/components/Collapsible/Collapsible.module.scss +117 -0
- package/src/components/Collapsible/index.tsx +219 -0
- package/src/components/ColorPicker/ColorPicker.fragment.tsx +196 -0
- package/src/components/ColorPicker/ColorPicker.module.scss +33 -23
- package/src/components/ColorPicker/index.tsx +34 -12
- package/src/components/ConversationList/ConversationList.fragment.tsx +202 -0
- package/src/components/ConversationList/ConversationList.module.scss +160 -0
- package/src/components/ConversationList/index.tsx +254 -0
- package/src/components/Dialog/Dialog.fragment.tsx +3 -3
- package/src/components/EmptyState/EmptyState.fragment.tsx +2 -2
- package/src/components/Field/Field.fragment.tsx +3 -3
- package/src/components/Fieldset/Fieldset.fragment.tsx +7 -7
- package/src/components/Form/Form.fragment.tsx +11 -11
- package/src/components/Grid/Grid.fragment.tsx +1 -1
- package/src/components/Header/Header.fragment.tsx +4 -4
- package/src/components/Header/Header.module.scss +9 -10
- package/src/components/Icon/Icon.fragment.tsx +2 -2
- package/src/components/Image/Image.fragment.tsx +2 -2
- package/src/components/Input/Input.fragment.tsx +1 -1
- package/src/components/Input/Input.module.scss +2 -2
- package/src/components/Link/Link.fragment.tsx +1 -1
- package/src/components/List/List.fragment.tsx +2 -2
- package/src/components/Listbox/Listbox.fragment.tsx +1 -1
- package/src/components/Loading/Loading.fragment.tsx +153 -0
- package/src/components/Loading/Loading.module.scss +256 -0
- package/src/components/Loading/index.tsx +236 -0
- package/src/components/Menu/Menu.fragment.tsx +3 -3
- package/src/components/Message/Message.fragment.tsx +200 -0
- package/src/components/Message/Message.module.scss +224 -0
- package/src/components/Message/index.tsx +278 -0
- package/src/components/Popover/Popover.fragment.tsx +4 -4
- package/src/components/Progress/Progress.fragment.tsx +1 -1
- package/src/components/Prompt/Prompt.fragment.tsx +2 -2
- package/src/components/RadioGroup/RadioGroup.fragment.tsx +1 -1
- package/src/components/RadioGroup/RadioGroup.module.scss +7 -4
- package/src/components/Select/Select.fragment.tsx +1 -1
- package/src/components/Select/Select.module.scss +8 -0
- package/src/components/Select/index.tsx +85 -5
- package/src/components/Separator/Separator.fragment.tsx +1 -1
- package/src/components/Sidebar/Sidebar.fragment.tsx +2 -2
- package/src/components/Sidebar/Sidebar.module.scss +19 -0
- package/src/components/Sidebar/index.tsx +52 -11
- package/src/components/Skeleton/Skeleton.fragment.tsx +1 -1
- package/src/components/Slider/Slider.fragment.tsx +201 -0
- package/src/components/Stack/Stack.fragment.tsx +194 -0
- package/src/components/Table/Table.fragment.tsx +3 -3
- package/src/components/Tabs/Tabs.fragment.tsx +1 -1
- package/src/components/Tabs/Tabs.module.scss +2 -2
- package/src/components/Text/Text.fragment.tsx +188 -0
- package/src/components/Textarea/Textarea.fragment.tsx +1 -1
- package/src/components/Theme/Theme.fragment.tsx +2 -2
- package/src/components/Theme/ThemeToggle.module.scss +13 -13
- package/src/components/ThinkingIndicator/ThinkingIndicator.fragment.tsx +182 -0
- package/src/components/ThinkingIndicator/ThinkingIndicator.module.scss +226 -0
- package/src/components/ThinkingIndicator/index.tsx +258 -0
- package/src/components/Toast/Toast.fragment.tsx +1 -1
- package/src/components/Toggle/Toggle.fragment.tsx +1 -1
- package/src/components/ToggleGroup/ToggleGroup.fragment.tsx +207 -0
- package/src/components/Tooltip/Tooltip.fragment.tsx +3 -3
- package/src/components/VisuallyHidden/VisuallyHidden.fragment.tsx +2 -2
- package/src/index.ts +86 -3
- package/src/recipes/AIChat.recipe.ts +266 -0
- package/src/tokens/_computed.scss +212 -0
- package/src/tokens/_density.scss +171 -0
- package/src/tokens/_derive.scss +287 -0
- package/src/tokens/_index.scss +39 -1
- package/src/tokens/_mixins.scss +41 -0
- package/src/tokens/_palettes.scss +185 -0
- package/src/tokens/_radius.scss +107 -0
- package/src/tokens/_seeds.scss +59 -0
- package/src/tokens/_variables.scss +171 -130
- package/src/components/ColorChip/ColorChip.module.scss +0 -165
- package/src/components/ColorChip/index.tsx +0 -157
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// @fragments/ui Density Scales
|
|
3
|
+
// ============================================
|
|
4
|
+
//
|
|
5
|
+
// Defines 3 density presets that control spacing and sizing.
|
|
6
|
+
// Each preset uses a different base unit to scale all spacing.
|
|
7
|
+
//
|
|
8
|
+
// ============================================
|
|
9
|
+
|
|
10
|
+
@use 'sass:math';
|
|
11
|
+
@use 'sass:map';
|
|
12
|
+
|
|
13
|
+
// --------------------------------------------
|
|
14
|
+
// Density Definitions
|
|
15
|
+
// --------------------------------------------
|
|
16
|
+
// Each density includes:
|
|
17
|
+
// - base-unit: The fundamental spacing unit
|
|
18
|
+
// - multipliers: Scale factors for spacing tokens
|
|
19
|
+
|
|
20
|
+
$density-compact: (
|
|
21
|
+
base-unit: 6px,
|
|
22
|
+
base-font-size: 14px,
|
|
23
|
+
// Button heights (more compact)
|
|
24
|
+
button-height-sm: 24px, // ~4 units
|
|
25
|
+
button-height-md: 30px, // 5 units
|
|
26
|
+
button-height-lg: 36px, // 6 units
|
|
27
|
+
// Input height
|
|
28
|
+
input-height: 32px, // ~5.3 units
|
|
29
|
+
input-height-sm: 24px, // 4 units
|
|
30
|
+
input-height-lg: 36px, // 6 units
|
|
31
|
+
// Touch targets (minimum for accessibility)
|
|
32
|
+
touch-sm: 24px,
|
|
33
|
+
touch-md: 30px,
|
|
34
|
+
touch-lg: 36px
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
$density-default: (
|
|
38
|
+
base-unit: 7px,
|
|
39
|
+
base-font-size: 14px,
|
|
40
|
+
// Button heights (current values)
|
|
41
|
+
button-height-sm: 28px, // 4 units
|
|
42
|
+
button-height-md: 36px, // ~5 units
|
|
43
|
+
button-height-lg: 44px, // ~6 units
|
|
44
|
+
// Input height
|
|
45
|
+
input-height: 40px, // ~6 units
|
|
46
|
+
input-height-sm: 28px, // 4 units
|
|
47
|
+
input-height-lg: 44px, // ~6 units
|
|
48
|
+
// Touch targets
|
|
49
|
+
touch-sm: 24px,
|
|
50
|
+
touch-md: 32px,
|
|
51
|
+
touch-lg: 44px
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
$density-relaxed: (
|
|
55
|
+
base-unit: 8px,
|
|
56
|
+
base-font-size: 14px,
|
|
57
|
+
// Button heights (more spacious)
|
|
58
|
+
button-height-sm: 32px, // 4 units
|
|
59
|
+
button-height-md: 40px, // 5 units
|
|
60
|
+
button-height-lg: 48px, // 6 units
|
|
61
|
+
// Input height
|
|
62
|
+
input-height: 44px, // ~5.5 units
|
|
63
|
+
input-height-sm: 32px, // 4 units
|
|
64
|
+
input-height-lg: 48px, // 6 units
|
|
65
|
+
// Touch targets
|
|
66
|
+
touch-sm: 32px,
|
|
67
|
+
touch-md: 40px,
|
|
68
|
+
touch-lg: 48px
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// --------------------------------------------
|
|
72
|
+
// Density Map for Dynamic Access
|
|
73
|
+
// --------------------------------------------
|
|
74
|
+
$densities: (
|
|
75
|
+
"compact": $density-compact,
|
|
76
|
+
"default": $density-default,
|
|
77
|
+
"relaxed": $density-relaxed
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
// --------------------------------------------
|
|
81
|
+
// Helper Functions
|
|
82
|
+
// --------------------------------------------
|
|
83
|
+
|
|
84
|
+
/// Get a density configuration by name
|
|
85
|
+
/// @param {String} $name - Density name (compact, default, relaxed)
|
|
86
|
+
/// @return {Map} The density configuration map
|
|
87
|
+
@function get-density($name) {
|
|
88
|
+
@if not map.has-key($densities, $name) {
|
|
89
|
+
@warn "Unknown density '#{$name}'. Using 'default' as fallback.";
|
|
90
|
+
@return $density-default;
|
|
91
|
+
}
|
|
92
|
+
@return map.get($densities, $name);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/// Get a specific value from a density configuration
|
|
96
|
+
/// @param {Map} $density - A density configuration map
|
|
97
|
+
/// @param {String} $key - The key to retrieve
|
|
98
|
+
/// @return {*} The value
|
|
99
|
+
@function density-value($density, $key) {
|
|
100
|
+
@if not map.has-key($density, $key) {
|
|
101
|
+
@warn "Unknown density key '#{$key}'.";
|
|
102
|
+
@return null;
|
|
103
|
+
}
|
|
104
|
+
@return map.get($density, $key);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/// Derive spacing scale from base unit
|
|
108
|
+
/// Returns a map with spacing tokens
|
|
109
|
+
/// @param {Map} $density - A density configuration map
|
|
110
|
+
/// @return {Map} Spacing tokens
|
|
111
|
+
@function derive-spacing($density) {
|
|
112
|
+
$base: map.get($density, base-unit);
|
|
113
|
+
$font-size: map.get($density, base-font-size);
|
|
114
|
+
|
|
115
|
+
// Convert to rem based on font size
|
|
116
|
+
// 1 unit = base-unit / font-size * 1rem
|
|
117
|
+
$unit-rem: math.div($base, $font-size) * 1rem;
|
|
118
|
+
|
|
119
|
+
@return (
|
|
120
|
+
// Micro spacing (pixel-precise for tiny alignments)
|
|
121
|
+
px: 1px,
|
|
122
|
+
0-5: $unit-rem * 0.3, // ~2px for 7px base
|
|
123
|
+
0-75: $unit-rem * 0.43, // ~3px for 7px base
|
|
124
|
+
|
|
125
|
+
// Standard spacing scale
|
|
126
|
+
1: $unit-rem, // 1 unit
|
|
127
|
+
2: $unit-rem * 2, // 2 units
|
|
128
|
+
3: $unit-rem * 3, // 3 units
|
|
129
|
+
4: $unit-rem * 4, // 4 units
|
|
130
|
+
5: $unit-rem * 5, // 5 units
|
|
131
|
+
6: $unit-rem * 6, // 6 units
|
|
132
|
+
8: $unit-rem * 8, // 8 units
|
|
133
|
+
10: $unit-rem * 10, // 10 units
|
|
134
|
+
12: $unit-rem * 12 // 12 units
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/// Derive container padding from density
|
|
139
|
+
/// @param {Map} $density - A density configuration map
|
|
140
|
+
/// @return {Map} Padding tokens
|
|
141
|
+
@function derive-padding($density) {
|
|
142
|
+
$base: map.get($density, base-unit);
|
|
143
|
+
$font-size: map.get($density, base-font-size);
|
|
144
|
+
$unit-rem: math.div($base, $font-size) * 1rem;
|
|
145
|
+
|
|
146
|
+
@return (
|
|
147
|
+
// Container padding: Cards, Dialogs, Popovers
|
|
148
|
+
container-sm: $unit-rem * 3, // 3 units
|
|
149
|
+
container-md: $unit-rem * 4, // 4 units
|
|
150
|
+
container-lg: $unit-rem * 6, // 6 units
|
|
151
|
+
|
|
152
|
+
// Inline padding: Alerts, Toasts
|
|
153
|
+
inline-sm: $unit-rem * 2, // 2 units
|
|
154
|
+
inline-md: $unit-rem * 3, // 3 units
|
|
155
|
+
inline-lg: $unit-rem * 4, // 4 units
|
|
156
|
+
|
|
157
|
+
// Item padding: Accordion, Tabs, Menu items
|
|
158
|
+
item-sm: $unit-rem * 2, // 2 units
|
|
159
|
+
item-md: $unit-rem * 3, // 3 units
|
|
160
|
+
item-lg: $unit-rem * 4 // 4 units
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/// Convert pixel value to rem based on density
|
|
165
|
+
/// @param {Map} $density - A density configuration map
|
|
166
|
+
/// @param {Number} $px - Pixel value to convert
|
|
167
|
+
/// @return {Number} Value in rem
|
|
168
|
+
@function px-to-rem($density, $px) {
|
|
169
|
+
$font-size: map.get($density, base-font-size);
|
|
170
|
+
@return math.div($px, $font-size) * 1rem;
|
|
171
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// @fragments/ui Token Derivation Functions
|
|
3
|
+
// ============================================
|
|
4
|
+
//
|
|
5
|
+
// Functions that derive complete token sets from seed values.
|
|
6
|
+
// These enable the seed-based design system where users configure
|
|
7
|
+
// ~5-10 seeds and everything else derives automatically.
|
|
8
|
+
//
|
|
9
|
+
// ============================================
|
|
10
|
+
|
|
11
|
+
@use 'sass:color';
|
|
12
|
+
@use 'sass:math';
|
|
13
|
+
@use 'palettes' as *;
|
|
14
|
+
|
|
15
|
+
// --------------------------------------------
|
|
16
|
+
// Color Utility Functions
|
|
17
|
+
// --------------------------------------------
|
|
18
|
+
|
|
19
|
+
/// Check if a color is considered "dark" (luminance < 0.5)
|
|
20
|
+
/// @param {Color} $color - Color to check
|
|
21
|
+
/// @return {Boolean} True if dark
|
|
22
|
+
@function is-dark-color($color) {
|
|
23
|
+
$r: math.div(color.channel($color, 'red', $space: rgb), 255);
|
|
24
|
+
$g: math.div(color.channel($color, 'green', $space: rgb), 255);
|
|
25
|
+
$b: math.div(color.channel($color, 'blue', $space: rgb), 255);
|
|
26
|
+
|
|
27
|
+
// Relative luminance formula (simplified)
|
|
28
|
+
$luminance: 0.2126 * $r + 0.7152 * $g + 0.0722 * $b;
|
|
29
|
+
|
|
30
|
+
@return $luminance < 0.5;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// Get appropriate contrast color (black or white)
|
|
34
|
+
/// @param {Color} $bg-color - Background color
|
|
35
|
+
/// @return {Color} Black or white for best contrast
|
|
36
|
+
@function contrast-color($bg-color) {
|
|
37
|
+
@if is-dark-color($bg-color) {
|
|
38
|
+
@return #ffffff;
|
|
39
|
+
} @else {
|
|
40
|
+
@return #000000;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// --------------------------------------------
|
|
45
|
+
// Accent Color Derivation
|
|
46
|
+
// --------------------------------------------
|
|
47
|
+
|
|
48
|
+
/// Derive hover state for accent color
|
|
49
|
+
/// @param {Color} $base - Base accent color
|
|
50
|
+
/// @param {Boolean} $is-dark - Whether in dark mode
|
|
51
|
+
/// @return {Color} Hover state color
|
|
52
|
+
@function derive-accent-hover($base, $is-dark: false) {
|
|
53
|
+
@if $is-dark {
|
|
54
|
+
// In dark mode, lighten for hover
|
|
55
|
+
@return color.scale($base, $lightness: 5%);
|
|
56
|
+
} @else {
|
|
57
|
+
// In light mode, darken for hover
|
|
58
|
+
@return color.scale($base, $lightness: -8%);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/// Derive active state for accent color
|
|
63
|
+
/// @param {Color} $base - Base accent color
|
|
64
|
+
/// @param {Boolean} $is-dark - Whether in dark mode
|
|
65
|
+
/// @return {Color} Active state color
|
|
66
|
+
@function derive-accent-active($base, $is-dark: false) {
|
|
67
|
+
@if $is-dark {
|
|
68
|
+
// In dark mode, lighten more for active
|
|
69
|
+
@return color.scale($base, $lightness: 10%);
|
|
70
|
+
} @else {
|
|
71
|
+
// In light mode, darken more for active
|
|
72
|
+
@return color.scale($base, $lightness: -15%);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// Derive a light variant of accent for dark mode
|
|
77
|
+
/// Auto-lightens dark brand colors so they're visible on dark backgrounds
|
|
78
|
+
/// @param {Color} $brand - Brand color
|
|
79
|
+
/// @return {Color} Lightened accent for dark mode
|
|
80
|
+
@function derive-dark-accent($brand) {
|
|
81
|
+
@if is-dark-color($brand) {
|
|
82
|
+
// If brand is dark, invert to light for dark mode
|
|
83
|
+
// Use a light gray as the dark mode accent
|
|
84
|
+
@return #f2f2f2;
|
|
85
|
+
} @else {
|
|
86
|
+
// If brand is already light, use it as-is or slightly adjust
|
|
87
|
+
@return color.scale($brand, $lightness: 10%);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// --------------------------------------------
|
|
92
|
+
// Surface/Background Derivation
|
|
93
|
+
// --------------------------------------------
|
|
94
|
+
|
|
95
|
+
/// Derive surface/background tokens from a neutral palette
|
|
96
|
+
/// Maps shade levels to semantic surface tokens for visual depth layering
|
|
97
|
+
/// @param {Map} $palette - Neutral palette map
|
|
98
|
+
/// @param {Boolean} $is-dark - Whether in dark mode
|
|
99
|
+
/// @return {Map} Surface token values
|
|
100
|
+
@function derive-surfaces($palette, $is-dark: false) {
|
|
101
|
+
@if $is-dark {
|
|
102
|
+
// Dark mode: darker = more recessed, lighter = elevated
|
|
103
|
+
@return (
|
|
104
|
+
primary: get-shade($palette, 950), // Page background (darkest)
|
|
105
|
+
secondary: get-shade($palette, 900), // Sidebar, panels
|
|
106
|
+
tertiary: get-shade($palette, 800), // Content areas (lighter)
|
|
107
|
+
elevated: get-shade($palette, 900), // Cards (slightly lighter than page)
|
|
108
|
+
subtle: interpolate-shade($palette, 925), // Between primary and secondary
|
|
109
|
+
hover: rgba(255, 255, 255, 0.06), // Interactive hover
|
|
110
|
+
active: rgba(255, 255, 255, 0.08) // Interactive active
|
|
111
|
+
);
|
|
112
|
+
} @else {
|
|
113
|
+
// Light mode: lighter = more recessed, darker shades for depth
|
|
114
|
+
@return (
|
|
115
|
+
primary: #ffffff, // Page background (white)
|
|
116
|
+
secondary: get-shade($palette, 100), // Sidebar, secondary panels
|
|
117
|
+
tertiary: get-shade($palette, 100), // Nested sections
|
|
118
|
+
elevated: #ffffff, // Cards, modals (floats above)
|
|
119
|
+
subtle: get-shade($palette, 50), // Very subtle backgrounds
|
|
120
|
+
hover: rgba(0, 0, 0, 0.04), // Interactive hover
|
|
121
|
+
active: rgba(0, 0, 0, 0.06) // Interactive active
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// --------------------------------------------
|
|
127
|
+
// Text Color Derivation
|
|
128
|
+
// --------------------------------------------
|
|
129
|
+
|
|
130
|
+
/// Derive text tokens from a neutral palette
|
|
131
|
+
/// Maps shade levels to semantic text tokens with contrast verification
|
|
132
|
+
/// @param {Map} $palette - Neutral palette map
|
|
133
|
+
/// @param {Boolean} $is-dark - Whether in dark mode
|
|
134
|
+
/// @return {Map} Text token values
|
|
135
|
+
@function derive-text($palette, $is-dark: false) {
|
|
136
|
+
@if $is-dark {
|
|
137
|
+
// Dark mode: light text on dark backgrounds
|
|
138
|
+
@return (
|
|
139
|
+
primary: get-shade($palette, 100), // Main text (light on dark)
|
|
140
|
+
secondary: get-shade($palette, 400), // Secondary text
|
|
141
|
+
tertiary: get-shade($palette, 500), // Muted text
|
|
142
|
+
inverse: get-shade($palette, 900) // Text on light accents
|
|
143
|
+
);
|
|
144
|
+
} @else {
|
|
145
|
+
// Light mode: dark text on light backgrounds
|
|
146
|
+
@return (
|
|
147
|
+
primary: get-shade($palette, 900), // Main text (high contrast)
|
|
148
|
+
secondary: get-shade($palette, 600), // Secondary text
|
|
149
|
+
tertiary: get-shade($palette, 500), // Muted/disabled text
|
|
150
|
+
inverse: get-shade($palette, 100) // Text on dark accents
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// --------------------------------------------
|
|
156
|
+
// Border Color Derivation
|
|
157
|
+
// --------------------------------------------
|
|
158
|
+
|
|
159
|
+
/// Derive border tokens from a neutral palette
|
|
160
|
+
/// @param {Map} $palette - Neutral palette map
|
|
161
|
+
/// @param {Boolean} $is-dark - Whether in dark mode
|
|
162
|
+
/// @return {Map} Border token values
|
|
163
|
+
@function derive-borders($palette, $is-dark: false) {
|
|
164
|
+
@if $is-dark {
|
|
165
|
+
// Dark mode: subtle light borders
|
|
166
|
+
@return (
|
|
167
|
+
default: get-shade($palette, 800), // Subtle dark borders
|
|
168
|
+
strong: get-shade($palette, 700) // Prominent dark borders
|
|
169
|
+
);
|
|
170
|
+
} @else {
|
|
171
|
+
// Light mode: subtle dark borders
|
|
172
|
+
@return (
|
|
173
|
+
default: get-shade($palette, 200), // Subtle borders
|
|
174
|
+
strong: get-shade($palette, 300) // Prominent borders
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// --------------------------------------------
|
|
180
|
+
// Shadow Derivation
|
|
181
|
+
// --------------------------------------------
|
|
182
|
+
|
|
183
|
+
/// Derive shadow tokens based on mode
|
|
184
|
+
/// @param {Boolean} $is-dark - Whether in dark mode
|
|
185
|
+
/// @return {Map} Shadow token values
|
|
186
|
+
@function derive-shadows($is-dark: false) {
|
|
187
|
+
@if $is-dark {
|
|
188
|
+
// Dark mode: deeper shadows for depth
|
|
189
|
+
@return (
|
|
190
|
+
sm: (0 1px 2px 0 rgba(0, 0, 0, 0.3)),
|
|
191
|
+
md: (0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -2px rgba(0, 0, 0, 0.3)),
|
|
192
|
+
lg: (0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -4px rgba(0, 0, 0, 0.4))
|
|
193
|
+
);
|
|
194
|
+
} @else {
|
|
195
|
+
// Light mode: subtle shadows
|
|
196
|
+
@return (
|
|
197
|
+
sm: (0 1px 2px 0 rgba(0, 0, 0, 0.05)),
|
|
198
|
+
md: (0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)),
|
|
199
|
+
lg: (0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1))
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// --------------------------------------------
|
|
205
|
+
// Scrollbar Derivation
|
|
206
|
+
// --------------------------------------------
|
|
207
|
+
|
|
208
|
+
/// Derive scrollbar tokens from a neutral palette
|
|
209
|
+
/// @param {Map} $palette - Neutral palette map
|
|
210
|
+
/// @param {Boolean} $is-dark - Whether in dark mode
|
|
211
|
+
/// @return {Map} Scrollbar token values
|
|
212
|
+
@function derive-scrollbar($palette, $is-dark: false) {
|
|
213
|
+
@if $is-dark {
|
|
214
|
+
@return (
|
|
215
|
+
track: get-shade($palette, 800),
|
|
216
|
+
thumb: get-shade($palette, 600),
|
|
217
|
+
thumb-hover: get-shade($palette, 500)
|
|
218
|
+
);
|
|
219
|
+
} @else {
|
|
220
|
+
@return (
|
|
221
|
+
track: get-shade($palette, 100),
|
|
222
|
+
thumb: get-shade($palette, 300),
|
|
223
|
+
thumb-hover: get-shade($palette, 400)
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// --------------------------------------------
|
|
229
|
+
// Semantic Color Backgrounds
|
|
230
|
+
// --------------------------------------------
|
|
231
|
+
|
|
232
|
+
/// Derive semantic background colors (danger, success, etc.)
|
|
233
|
+
/// @param {Color} $color - The semantic color
|
|
234
|
+
/// @param {Boolean} $is-dark - Whether in dark mode
|
|
235
|
+
/// @return {Color} Background color with appropriate opacity
|
|
236
|
+
@function derive-semantic-bg($color, $is-dark: false) {
|
|
237
|
+
@if $is-dark {
|
|
238
|
+
// Dark mode: slightly higher opacity for visibility
|
|
239
|
+
@return rgba($color, 0.15);
|
|
240
|
+
} @else {
|
|
241
|
+
// Light mode: subtle background
|
|
242
|
+
@return rgba($color, 0.1);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/// Derive hover state for semantic colors (like danger-hover)
|
|
247
|
+
/// @param {Color} $color - The semantic color
|
|
248
|
+
/// @return {Color} Hover state color
|
|
249
|
+
@function derive-semantic-hover($color) {
|
|
250
|
+
@return color.scale($color, $lightness: -10%);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// --------------------------------------------
|
|
254
|
+
// Focus Ring Derivation
|
|
255
|
+
// --------------------------------------------
|
|
256
|
+
|
|
257
|
+
/// Derive focus ring color from brand/accent
|
|
258
|
+
/// @param {Color} $brand - Brand color
|
|
259
|
+
/// @param {Boolean} $is-dark - Whether in dark mode
|
|
260
|
+
/// @return {Color} Focus ring color
|
|
261
|
+
@function derive-focus-ring($brand, $is-dark: false) {
|
|
262
|
+
@if $is-dark {
|
|
263
|
+
// In dark mode with dark brand, use light focus ring
|
|
264
|
+
@if is-dark-color($brand) {
|
|
265
|
+
@return #f2f2f2;
|
|
266
|
+
}
|
|
267
|
+
@return $brand;
|
|
268
|
+
} @else {
|
|
269
|
+
// In light mode, use brand color
|
|
270
|
+
@return $brand;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// --------------------------------------------
|
|
275
|
+
// Backdrop Derivation
|
|
276
|
+
// --------------------------------------------
|
|
277
|
+
|
|
278
|
+
/// Derive backdrop/overlay colors
|
|
279
|
+
/// @param {Boolean} $is-dark - Whether in dark mode
|
|
280
|
+
/// @return {Color} Backdrop color
|
|
281
|
+
@function derive-backdrop($is-dark: false) {
|
|
282
|
+
@if $is-dark {
|
|
283
|
+
@return rgba(0, 0, 0, 0.8);
|
|
284
|
+
} @else {
|
|
285
|
+
@return rgba(0, 0, 0, 0.5);
|
|
286
|
+
}
|
|
287
|
+
}
|
package/src/tokens/_index.scss
CHANGED
|
@@ -1,3 +1,41 @@
|
|
|
1
|
-
//
|
|
1
|
+
// ============================================
|
|
2
|
+
// @fragments/ui Design Tokens Index
|
|
3
|
+
// ============================================
|
|
4
|
+
//
|
|
5
|
+
// This module exports the complete token system.
|
|
6
|
+
// Import with: @use '@fragments-sdk/ui/tokens';
|
|
7
|
+
//
|
|
8
|
+
// SEED-BASED CONFIGURATION:
|
|
9
|
+
// Set seed variables before importing to customize your theme.
|
|
10
|
+
// See _seeds.scss for available options.
|
|
11
|
+
//
|
|
12
|
+
// Example:
|
|
13
|
+
// $fui-brand: #0066ff;
|
|
14
|
+
// $fui-neutral: "steel";
|
|
15
|
+
// @use '@fragments-sdk/ui/tokens';
|
|
16
|
+
//
|
|
17
|
+
// ============================================
|
|
18
|
+
|
|
19
|
+
// Forward seed configuration (for users to override)
|
|
20
|
+
@forward 'seeds';
|
|
21
|
+
|
|
22
|
+
// Forward palette definitions (for advanced customization)
|
|
23
|
+
@forward 'palettes';
|
|
24
|
+
|
|
25
|
+
// Forward density scales
|
|
26
|
+
@forward 'density';
|
|
27
|
+
|
|
28
|
+
// Forward radius styles
|
|
29
|
+
@forward 'radius';
|
|
30
|
+
|
|
31
|
+
// Forward derivation functions (for advanced users)
|
|
32
|
+
@forward 'derive';
|
|
33
|
+
|
|
34
|
+
// Forward computed values (internal use)
|
|
35
|
+
@forward 'computed';
|
|
36
|
+
|
|
37
|
+
// Forward main variables (includes all token definitions)
|
|
2
38
|
@forward 'variables';
|
|
39
|
+
|
|
40
|
+
// Forward mixins
|
|
3
41
|
@forward 'mixins';
|
package/src/tokens/_mixins.scss
CHANGED
|
@@ -150,3 +150,44 @@
|
|
|
150
150
|
0 0 0 var(--fui-focus-ring-offset, #{$fui-focus-ring-offset}) var(--fui-bg-primary, #{$fui-bg-primary}),
|
|
151
151
|
0 0 0 calc(var(--fui-focus-ring-offset, #{$fui-focus-ring-offset}) + var(--fui-focus-ring-width, #{$fui-focus-ring-width})) var(--fui-color-danger, #{$fui-color-danger});
|
|
152
152
|
}
|
|
153
|
+
|
|
154
|
+
// ============================================
|
|
155
|
+
// Size Variant Mixins
|
|
156
|
+
// ============================================
|
|
157
|
+
|
|
158
|
+
/// Control size mixin for standardized sizing across buttons, inputs, selects
|
|
159
|
+
/// @param {String} $size - Size variant: 'sm', 'md', or 'lg'
|
|
160
|
+
/// @param {String} $component - Component type: 'button', 'input', or 'select'
|
|
161
|
+
@mixin control-size($size, $component: 'button') {
|
|
162
|
+
@if $size == 'sm' {
|
|
163
|
+
@if $component == 'input' {
|
|
164
|
+
height: var(--fui-input-height-sm, #{$fui-input-height-sm});
|
|
165
|
+
padding: 0 var(--fui-space-2, #{$fui-space-2});
|
|
166
|
+
font-size: var(--fui-font-size-xs, #{$fui-font-size-xs});
|
|
167
|
+
} @else {
|
|
168
|
+
height: var(--fui-button-height-sm, #{$fui-button-height-sm});
|
|
169
|
+
padding: 0 var(--fui-space-2, #{$fui-space-2});
|
|
170
|
+
font-size: var(--fui-font-size-xs, #{$fui-font-size-xs});
|
|
171
|
+
}
|
|
172
|
+
} @else if $size == 'md' {
|
|
173
|
+
@if $component == 'input' {
|
|
174
|
+
height: var(--fui-input-height, #{$fui-input-height});
|
|
175
|
+
padding: 0 var(--fui-space-3, #{$fui-space-3});
|
|
176
|
+
font-size: var(--fui-font-size-sm, #{$fui-font-size-sm});
|
|
177
|
+
} @else {
|
|
178
|
+
height: var(--fui-button-height-md, #{$fui-button-height-md});
|
|
179
|
+
padding: 0 var(--fui-space-4, #{$fui-space-4});
|
|
180
|
+
font-size: var(--fui-font-size-sm, #{$fui-font-size-sm});
|
|
181
|
+
}
|
|
182
|
+
} @else if $size == 'lg' {
|
|
183
|
+
@if $component == 'input' {
|
|
184
|
+
height: var(--fui-input-height-lg, #{$fui-input-height-lg});
|
|
185
|
+
padding: 0 var(--fui-space-4, #{$fui-space-4});
|
|
186
|
+
font-size: var(--fui-font-size-base, #{$fui-font-size-base});
|
|
187
|
+
} @else {
|
|
188
|
+
height: var(--fui-button-height-lg, #{$fui-button-height-lg});
|
|
189
|
+
padding: 0 var(--fui-space-5, #{$fui-space-5});
|
|
190
|
+
font-size: var(--fui-font-size-base, #{$fui-font-size-base});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|