@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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -0
  3. package/package.json +32 -0
  4. 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
+ }