@fluixi-ui/skin-soft 0.1.0-alpha.1
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/LICENSE +21 -0
- package/README.md +38 -0
- package/package.json +32 -0
- package/soft.css +201 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fluixi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# @fluixi-ui/skin-soft
|
|
2
|
+
|
|
3
|
+
A soft, corporate dashboard skin for Fluixi UI. Restyles the components to a
|
|
4
|
+
clean "Soft Elevated" look — generous consistent rounding, gentle two-layer
|
|
5
|
+
elevation used with intent, a single restrained accent, comfortable density, and
|
|
6
|
+
system typography. No gradients, no glass, no decorative shadow.
|
|
7
|
+
|
|
8
|
+
It touches only shape, elevation, density and motion, so colour stays
|
|
9
|
+
theme-driven: `data-theme` (light/dark/high-contrast) and `data-accent` keep
|
|
10
|
+
working unchanged.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
Import the stylesheet after the tokens + preset, then activate with
|
|
15
|
+
`data-ui="soft"` on a root (or any subtree):
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import '@fluixi-ui/tokens/preset.css';
|
|
19
|
+
import '@fluixi-ui/skin-soft/styles.css';
|
|
20
|
+
|
|
21
|
+
document.documentElement.dataset.ui = 'soft';
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Because it targets `data-ui="soft"`, you can scope it to a subtree — mix skins on
|
|
25
|
+
one page by setting the attribute on a container instead of the root.
|
|
26
|
+
|
|
27
|
+
## What it changes
|
|
28
|
+
|
|
29
|
+
- **Buttons** — pill shape; filled primary rests on a soft shadow and lifts a
|
|
30
|
+
touch on hover.
|
|
31
|
+
- **Fields** — 10px radius, comfortable height, soft single-halo focus ring.
|
|
32
|
+
- **Surfaces** — cards and overlays get larger radius and gentle elevation.
|
|
33
|
+
- **Menus / listboxes** — rounded, inset row highlights instead of full-bleed
|
|
34
|
+
bars.
|
|
35
|
+
- **Selection controls** — rounder checkbox, larger switch, calmer focus.
|
|
36
|
+
|
|
37
|
+
Layered in `flx.skin` (above `flx.components`), so it overrides the default look
|
|
38
|
+
while your own unlayered CSS still wins.
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fluixi-ui/skin-soft",
|
|
3
|
+
"version": "0.1.0-alpha.1",
|
|
4
|
+
"description": "Soft corporate skin for Fluixi UI — clean, gently elevated dashboard look; activate with data-ui=\"soft\"",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"private": false,
|
|
7
|
+
"type": "module",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"registry": "https://registry.npmjs.org/",
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/fluixi/ui.git",
|
|
15
|
+
"directory": "packages/skin-soft"
|
|
16
|
+
},
|
|
17
|
+
"sideEffects": [
|
|
18
|
+
"*.css"
|
|
19
|
+
],
|
|
20
|
+
"files": [
|
|
21
|
+
"soft.css",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"exports": {
|
|
26
|
+
"./package.json": "./package.json",
|
|
27
|
+
"./styles.css": "./soft.css"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "true"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/soft.css
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fluixi-ui/skin-soft — a soft, corporate dashboard skin for Fluixi UI.
|
|
3
|
+
*
|
|
4
|
+
* Activate by setting `data-ui="soft"` on a root (or any subtree). All rules live
|
|
5
|
+
* in the `flx.skin` cascade layer, above `flx.components`, so they override the
|
|
6
|
+
* default fluixi look wherever they match; consumer CSS stays unlayered and still
|
|
7
|
+
* wins. Import after the tokens + preset.
|
|
8
|
+
*
|
|
9
|
+
* Design language ("Soft Elevated", à la modern SaaS dashboards): generous but
|
|
10
|
+
* consistent rounding, gentle two-layer elevation used with intent (surfaces and
|
|
11
|
+
* overlays lift, flat controls carry only a hairline), a single accent spent on
|
|
12
|
+
* primary action / selection, comfortable density, system typography. No
|
|
13
|
+
* gradients, no glass, no decorative shadow — structure comes from spacing,
|
|
14
|
+
* rounding and one restrained accent.
|
|
15
|
+
*
|
|
16
|
+
* Colour stays theme-driven: this skin only touches shape, elevation, density and
|
|
17
|
+
* motion, so it inherits `data-theme` (light/dark/hc) and `data-accent` untouched.
|
|
18
|
+
*/
|
|
19
|
+
@layer flx.tokens, flx.components, flx.skin;
|
|
20
|
+
|
|
21
|
+
@layer flx.skin {
|
|
22
|
+
/* ---- Global soft tokens --------------------------------------------------
|
|
23
|
+
Re-scoping the token scale is the main lever: radius, elevation, motion and
|
|
24
|
+
type flow into every component automatically. */
|
|
25
|
+
[data-ui='soft'] {
|
|
26
|
+
--flx-ui-font-family-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI',
|
|
27
|
+
'Inter', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
28
|
+
|
|
29
|
+
--flx-ui-radius-sm: 8px;
|
|
30
|
+
--flx-ui-radius-md: 10px;
|
|
31
|
+
--flx-ui-radius-lg: 14px;
|
|
32
|
+
--flx-ui-radius-xl: 20px;
|
|
33
|
+
|
|
34
|
+
--flx-ui-font-size-md: 15px;
|
|
35
|
+
--flx-ui-line-height-normal: 1.5;
|
|
36
|
+
|
|
37
|
+
--flx-ui-duration-fast: 130ms;
|
|
38
|
+
--flx-ui-duration-normal: 200ms;
|
|
39
|
+
--flx-ui-ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
|
|
40
|
+
--flx-ui-ease-emphasized: cubic-bezier(0.32, 0.72, 0, 1);
|
|
41
|
+
|
|
42
|
+
/* Soft two-layer elevation — low-alpha, cool-tinted, spread over distance
|
|
43
|
+
rather than a single hard drop. */
|
|
44
|
+
--flx-ui-shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06), 0 1px 3px rgba(16, 24, 40, 0.04);
|
|
45
|
+
--flx-ui-shadow-md: 0 2px 8px rgba(16, 24, 40, 0.06), 0 1px 3px rgba(16, 24, 40, 0.05);
|
|
46
|
+
--flx-ui-shadow-lg: 0 8px 24px rgba(16, 24, 40, 0.1), 0 2px 8px rgba(16, 24, 40, 0.06);
|
|
47
|
+
--flx-ui-shadow-xl: 0 16px 40px rgba(16, 24, 40, 0.14), 0 4px 12px rgba(16, 24, 40, 0.08);
|
|
48
|
+
|
|
49
|
+
/* A softer, single-halo focus ring (no surface gap) reads calmer than the
|
|
50
|
+
default two-step ring against rounded controls. */
|
|
51
|
+
--flx-ui-ctl-ring: 0 0 0 3px var(--flx-ui-color-primary-subtle);
|
|
52
|
+
|
|
53
|
+
/* Uniform hairline: soft controls carry the same low-contrast border as
|
|
54
|
+
surfaces (no darker "strong" control border). */
|
|
55
|
+
--flx-ui-color-border-strong: var(--flx-ui-gray-6);
|
|
56
|
+
|
|
57
|
+
font-family: var(--flx-ui-font-family-sans);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* ---- Button: pill, flat by default, one accent, soft lift on primary ------ */
|
|
61
|
+
[data-ui='soft'] :where([data-variant]) {
|
|
62
|
+
border-radius: 9999px;
|
|
63
|
+
height: 40px;
|
|
64
|
+
padding: 0 18px;
|
|
65
|
+
font-weight: 600;
|
|
66
|
+
letter-spacing: -0.005em;
|
|
67
|
+
box-shadow: none;
|
|
68
|
+
transition:
|
|
69
|
+
background var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
|
|
70
|
+
border-color var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
|
|
71
|
+
box-shadow var(--flx-ui-duration-normal) var(--flx-ui-ease-standard),
|
|
72
|
+
transform var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
|
|
73
|
+
}
|
|
74
|
+
/* Filled primary: rests on a soft shadow, lifts a touch on hover, settles on
|
|
75
|
+
press. Depth comes from elevation, not a colour sheen. */
|
|
76
|
+
[data-ui='soft'] :where([data-variant='solid']) {
|
|
77
|
+
box-shadow: var(--flx-ui-shadow-sm);
|
|
78
|
+
}
|
|
79
|
+
[data-ui='soft'] :where([data-variant='solid']:hover:not([data-disabled])) {
|
|
80
|
+
box-shadow: var(--flx-ui-shadow-md);
|
|
81
|
+
transform: translateY(-1px);
|
|
82
|
+
}
|
|
83
|
+
[data-ui='soft'] :where([data-variant='solid']:active:not([data-disabled])) {
|
|
84
|
+
box-shadow: var(--flx-ui-shadow-sm);
|
|
85
|
+
transform: translateY(0);
|
|
86
|
+
}
|
|
87
|
+
/* Soft/outline/ghost stay flat; ghost is tighter. */
|
|
88
|
+
[data-ui='soft'] :where([data-variant='ghost']) {
|
|
89
|
+
padding: 0 12px;
|
|
90
|
+
}
|
|
91
|
+
[data-ui='soft'] :where([data-variant]:focus-visible) {
|
|
92
|
+
outline: none;
|
|
93
|
+
box-shadow: var(--flx-ui-ctl-ring);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Badges also carry [data-variant] — keep them as chips, not buttons. */
|
|
97
|
+
[data-ui='soft'] :where(.flx-ui-badge[data-variant]) {
|
|
98
|
+
height: auto;
|
|
99
|
+
padding: 2px 10px;
|
|
100
|
+
box-shadow: none;
|
|
101
|
+
transform: none;
|
|
102
|
+
font-weight: 600;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* ---- Text fields: clean, comfortable, soft focus ------------------------- */
|
|
106
|
+
[data-ui='soft'] :where([data-input], button[role='combobox'], [data-combobox-control]) {
|
|
107
|
+
min-height: 40px;
|
|
108
|
+
border-radius: var(--flx-ui-radius-md);
|
|
109
|
+
border-color: var(--flx-ui-color-border);
|
|
110
|
+
background: var(--flx-ui-color-bg);
|
|
111
|
+
transition:
|
|
112
|
+
border-color var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
|
|
113
|
+
box-shadow var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
|
|
114
|
+
}
|
|
115
|
+
[data-ui='soft'] :where([data-input]:hover:not(:focus):not([data-invalid]),
|
|
116
|
+
button[role='combobox']:hover) {
|
|
117
|
+
border-color: var(--flx-ui-gray-7);
|
|
118
|
+
}
|
|
119
|
+
[data-ui='soft'] :where([data-input]:focus-visible,
|
|
120
|
+
button[role='combobox']:focus-visible) {
|
|
121
|
+
outline: none;
|
|
122
|
+
border-color: var(--flx-ui-color-primary);
|
|
123
|
+
box-shadow: var(--flx-ui-ctl-ring);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* ---- Selection controls: rounder box, calm focus ------------------------- */
|
|
127
|
+
[data-ui='soft'] :where([role='checkbox']) {
|
|
128
|
+
border-radius: 6px;
|
|
129
|
+
}
|
|
130
|
+
[data-ui='soft'] :where([role='switch']) {
|
|
131
|
+
width: 44px;
|
|
132
|
+
height: 26px;
|
|
133
|
+
}
|
|
134
|
+
[data-ui='soft'] :where([role='switch'])::after {
|
|
135
|
+
width: 22px;
|
|
136
|
+
height: 22px;
|
|
137
|
+
}
|
|
138
|
+
[data-ui='soft'] :where([role='switch'][data-state='checked'])::after {
|
|
139
|
+
transform: translateX(18px);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* ---- Surfaces: cards lift gently, larger radius -------------------------- */
|
|
143
|
+
[data-ui='soft'] :where([data-card]) {
|
|
144
|
+
border-radius: var(--flx-ui-radius-lg);
|
|
145
|
+
border: 1px solid var(--flx-ui-color-border);
|
|
146
|
+
box-shadow: var(--flx-ui-shadow-sm);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* ---- Overlays: rounded, softly raised ------------------------------------ */
|
|
150
|
+
[data-ui='soft'] :where([role='dialog'], [role='menu'], [role='listbox'],
|
|
151
|
+
[data-hovercard-content], [data-popover-content]) {
|
|
152
|
+
border-radius: var(--flx-ui-radius-lg);
|
|
153
|
+
box-shadow: var(--flx-ui-shadow-lg);
|
|
154
|
+
}
|
|
155
|
+
[data-ui='soft'] :where([role='tooltip']) {
|
|
156
|
+
border-radius: var(--flx-ui-radius-sm);
|
|
157
|
+
}
|
|
158
|
+
/* Menu / listbox rows: rounded highlight instead of a full-bleed bar. */
|
|
159
|
+
[data-ui='soft'] :where([role='menuitem'], [role='option']) {
|
|
160
|
+
border-radius: var(--flx-ui-radius-sm);
|
|
161
|
+
margin: 0 6px;
|
|
162
|
+
}
|
|
163
|
+
[data-ui='soft'] :where([role='menu'], [role='listbox']) {
|
|
164
|
+
padding: 6px;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* ---- Sidenav: rounded, soft active pill --------------------------------- */
|
|
168
|
+
[data-ui='soft'] :where([data-sidenav-link]) {
|
|
169
|
+
border-radius: var(--flx-ui-radius-md);
|
|
170
|
+
font-weight: 500;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/* ---- Tabs: enclosed segmented control (not an underline) ----------------- */
|
|
174
|
+
[data-ui='soft'] :where([role='tablist']) {
|
|
175
|
+
gap: 3px;
|
|
176
|
+
padding: 4px;
|
|
177
|
+
background: var(--flx-ui-color-bg-muted);
|
|
178
|
+
border: none;
|
|
179
|
+
border-radius: var(--flx-ui-radius-md);
|
|
180
|
+
}
|
|
181
|
+
[data-ui='soft'] :where([role='tab']) {
|
|
182
|
+
border: none;
|
|
183
|
+
border-radius: calc(var(--flx-ui-radius-md) - 3px);
|
|
184
|
+
margin: 0;
|
|
185
|
+
padding: 6px 14px;
|
|
186
|
+
font-weight: 550;
|
|
187
|
+
color: var(--flx-ui-color-fg-muted);
|
|
188
|
+
transition:
|
|
189
|
+
background var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
|
|
190
|
+
color var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
|
|
191
|
+
box-shadow var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
|
|
192
|
+
}
|
|
193
|
+
[data-ui='soft'] :where([role='tab']:hover:not([data-state='active'])) {
|
|
194
|
+
color: var(--flx-ui-color-fg);
|
|
195
|
+
}
|
|
196
|
+
[data-ui='soft'] :where([role='tab'][data-state='active']) {
|
|
197
|
+
background: var(--flx-ui-color-bg);
|
|
198
|
+
color: var(--flx-ui-color-fg);
|
|
199
|
+
box-shadow: var(--flx-ui-shadow-sm);
|
|
200
|
+
}
|
|
201
|
+
}
|