@recoui/style 0.0.0-stage → 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +14 -2
- package/dist/index.css +1 -0
- package/package.json +51 -4
- package/src/index.scss +1 -0
- package/src/styles/container/box.scss +15 -0
- package/src/styles/container/dropdown.scss +93 -0
- package/src/styles/container/index.scss +3 -0
- package/src/styles/container/modal.scss +91 -0
- package/src/styles/display/badge.scss +55 -0
- package/src/styles/display/index.scss +3 -0
- package/src/styles/display/pill.scss +67 -0
- package/src/styles/display/tooltip.scss +161 -0
- package/src/styles/form/field.scss +74 -0
- package/src/styles/form/form.scss +131 -0
- package/src/styles/form/index.scss +2 -0
- package/src/styles/group/group.scss +15 -0
- package/src/styles/group/index.scss +2 -0
- package/src/styles/group/join.scss +64 -0
- package/src/styles/index.scss +6 -0
- package/src/styles/input/base.scss +99 -0
- package/src/styles/input/button.scss +147 -0
- package/src/styles/input/checkbox.scss +110 -0
- package/src/styles/input/index.scss +11 -0
- package/src/styles/input/indicators.scss +270 -0
- package/src/styles/input/input.scss +203 -0
- package/src/styles/input/label-wrapper.scss +37 -0
- package/src/styles/input/native.scss +154 -0
- package/src/styles/input/options.scss +99 -0
- package/src/styles/input/slider.scss +218 -0
- package/src/styles/input/switch.scss +111 -0
- package/src/styles/input/tabs.scss +179 -0
- package/src/styles/variables.scss +30 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
@layer components.ui {
|
|
2
|
+
// tooltip 显示样式
|
|
3
|
+
%ui-tooltip {
|
|
4
|
+
z-index: var(--ui-tooltip-z-index, 1100);
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
inline-size: max-content;
|
|
7
|
+
max-inline-size: min(var(--ui-tooltip-max-width, 20rem), calc(100vw - 2rem));
|
|
8
|
+
margin: 0;
|
|
9
|
+
padding: 0.375rem 0.5rem;
|
|
10
|
+
border: 0;
|
|
11
|
+
border-radius: var(--radius-sm);
|
|
12
|
+
background: var(--color-foreground);
|
|
13
|
+
color: var(--color-background);
|
|
14
|
+
box-shadow: var(--shadow-sm);
|
|
15
|
+
font-family: var(--font-family, inherit);
|
|
16
|
+
font-size: 0.75rem;
|
|
17
|
+
font-weight: 400;
|
|
18
|
+
line-height: 1.5;
|
|
19
|
+
letter-spacing: normal;
|
|
20
|
+
text-align: start;
|
|
21
|
+
text-decoration: none;
|
|
22
|
+
text-transform: none;
|
|
23
|
+
white-space: normal;
|
|
24
|
+
overflow-wrap: anywhere;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Portal / 浮层定位库可以直接设置 top、left 或 transform。
|
|
28
|
+
.ui-tooltip {
|
|
29
|
+
@extend %ui-tooltip;
|
|
30
|
+
position: fixed;
|
|
31
|
+
display: block;
|
|
32
|
+
opacity: 1;
|
|
33
|
+
visibility: visible;
|
|
34
|
+
transition:
|
|
35
|
+
opacity var(--transition),
|
|
36
|
+
visibility var(--transition),
|
|
37
|
+
display var(--transition);
|
|
38
|
+
transition-behavior: allow-discrete;
|
|
39
|
+
|
|
40
|
+
&[hidden] {
|
|
41
|
+
display: none;
|
|
42
|
+
opacity: 0;
|
|
43
|
+
visibility: hidden;
|
|
44
|
+
pointer-events: none;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@starting-style {
|
|
49
|
+
.ui-tooltip {
|
|
50
|
+
opacity: 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.ui-tooltip-wrapper {
|
|
55
|
+
position: relative;
|
|
56
|
+
display: inline-flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
box-sizing: border-box;
|
|
59
|
+
inline-size: fit-content;
|
|
60
|
+
vertical-align: middle;
|
|
61
|
+
|
|
62
|
+
&::before,
|
|
63
|
+
&::after {
|
|
64
|
+
position: absolute;
|
|
65
|
+
opacity: 0;
|
|
66
|
+
visibility: hidden;
|
|
67
|
+
pointer-events: none;
|
|
68
|
+
transition:
|
|
69
|
+
opacity var(--transition),
|
|
70
|
+
visibility var(--transition);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
&::after {
|
|
74
|
+
@extend %ui-tooltip;
|
|
75
|
+
content: attr(data-tooltip);
|
|
76
|
+
bottom: calc(100% + var(--ui-tooltip-offset, 0.5rem));
|
|
77
|
+
left: 50%;
|
|
78
|
+
transform: translateX(-50%);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 透明区域连接目标和提示,鼠标跨过间隙时仍可保持显示。
|
|
82
|
+
&::before {
|
|
83
|
+
content: "";
|
|
84
|
+
z-index: var(--ui-tooltip-z-index, 1100);
|
|
85
|
+
bottom: 100%;
|
|
86
|
+
left: 0;
|
|
87
|
+
inline-size: 100%;
|
|
88
|
+
block-size: var(--ui-tooltip-offset, 0.5rem);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
&[data-side="bottom"] {
|
|
92
|
+
&::after {
|
|
93
|
+
top: calc(100% + var(--ui-tooltip-offset, 0.5rem));
|
|
94
|
+
bottom: auto;
|
|
95
|
+
}
|
|
96
|
+
&::before {
|
|
97
|
+
top: 100%;
|
|
98
|
+
bottom: auto;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
&:is([data-side="left"], [data-side="right"]) {
|
|
103
|
+
&::after {
|
|
104
|
+
top: 50%;
|
|
105
|
+
bottom: auto;
|
|
106
|
+
transform: translateY(-50%);
|
|
107
|
+
}
|
|
108
|
+
&::before {
|
|
109
|
+
top: 0;
|
|
110
|
+
bottom: auto;
|
|
111
|
+
inline-size: var(--ui-tooltip-offset, 0.5rem);
|
|
112
|
+
block-size: 100%;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
&[data-side="left"] {
|
|
117
|
+
&::after {
|
|
118
|
+
right: calc(100% + var(--ui-tooltip-offset, 0.5rem));
|
|
119
|
+
left: auto;
|
|
120
|
+
}
|
|
121
|
+
&::before {
|
|
122
|
+
right: 100%;
|
|
123
|
+
left: auto;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
&[data-side="right"] {
|
|
128
|
+
&::after {
|
|
129
|
+
left: calc(100% + var(--ui-tooltip-offset, 0.5rem));
|
|
130
|
+
}
|
|
131
|
+
&::before {
|
|
132
|
+
left: 100%;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
&:not([data-state="closed"]):is(:hover, :focus-within, [data-state="open"]) {
|
|
137
|
+
&::before,
|
|
138
|
+
&::after {
|
|
139
|
+
opacity: 1;
|
|
140
|
+
visibility: visible;
|
|
141
|
+
pointer-events: auto;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
&:not([data-tooltip]),
|
|
146
|
+
&[data-tooltip=""] {
|
|
147
|
+
&::before,
|
|
148
|
+
&::after {
|
|
149
|
+
content: none;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
@media (prefers-reduced-motion: reduce) {
|
|
155
|
+
.ui-tooltip,
|
|
156
|
+
.ui-tooltip-wrapper::before,
|
|
157
|
+
.ui-tooltip-wrapper::after {
|
|
158
|
+
transition: none;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
@layer components.ui {
|
|
2
|
+
// 只组织字段结构,不限定控件类型,也不覆盖控件本身的尺寸和交互。
|
|
3
|
+
.ui-field {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
align-items: flex-start;
|
|
7
|
+
gap: 0.375rem;
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
inline-size: 100%;
|
|
10
|
+
min-inline-size: 0;
|
|
11
|
+
margin: 0;
|
|
12
|
+
font-family: inherit;
|
|
13
|
+
font-size: var(--font-size-input, 0.875rem);
|
|
14
|
+
color: var(--color-foreground);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.ui-field[data-orientation="horizontal"] {
|
|
18
|
+
flex-direction: row;
|
|
19
|
+
gap: 0.5rem;
|
|
20
|
+
|
|
21
|
+
> :is(.ui-checkbox, .ui-radio, .ui-switch, input[type="checkbox"], input[type="radio"]) {
|
|
22
|
+
flex-shrink: 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
> :is(.ui-checkbox, .ui-radio, .ui-switch) {
|
|
26
|
+
margin-block-start: max(
|
|
27
|
+
0px,
|
|
28
|
+
calc((var(--font-size-input, 0.875rem) * 1.5 - var(--ui-switch-height, 1.25rem)) / 2)
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
> .ui-field-content {
|
|
33
|
+
flex: 1 1 auto;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.ui-field-content {
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
align-items: flex-start;
|
|
41
|
+
gap: 0.25rem;
|
|
42
|
+
box-sizing: border-box;
|
|
43
|
+
min-inline-size: 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:is(.ui-field, .ui-field > .ui-field-content) > .ui-field-label {
|
|
47
|
+
display: inline-flex;
|
|
48
|
+
align-items: center;
|
|
49
|
+
gap: 0.25rem;
|
|
50
|
+
max-inline-size: 100%;
|
|
51
|
+
margin: 0;
|
|
52
|
+
font-family: inherit;
|
|
53
|
+
font-size: var(--font-size-input, 0.875rem);
|
|
54
|
+
font-weight: 500;
|
|
55
|
+
line-height: 1.5;
|
|
56
|
+
color: inherit;
|
|
57
|
+
overflow-wrap: anywhere;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
:is(.ui-field, .ui-field > .ui-field-content) > .ui-field-description {
|
|
61
|
+
align-self: stretch;
|
|
62
|
+
min-inline-size: 0;
|
|
63
|
+
margin: 0;
|
|
64
|
+
font-family: inherit;
|
|
65
|
+
font-size: 0.75rem;
|
|
66
|
+
line-height: 1.5;
|
|
67
|
+
color: var(--color-disabled);
|
|
68
|
+
overflow-wrap: anywhere;
|
|
69
|
+
|
|
70
|
+
&:empty {
|
|
71
|
+
display: none;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
@layer components.ui {
|
|
2
|
+
:where(.ui-form, .ui-fieldset, .ui-legend, .ui-progress, .ui-meter) {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
font-family: inherit;
|
|
5
|
+
font-size: 0.875rem;
|
|
6
|
+
color: var(--color-foreground);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.ui-form {
|
|
10
|
+
display: grid;
|
|
11
|
+
gap: 1rem;
|
|
12
|
+
min-inline-size: 0;
|
|
13
|
+
margin: 0;
|
|
14
|
+
text-align: start;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.ui-fieldset {
|
|
18
|
+
min-inline-size: 0;
|
|
19
|
+
margin: 0;
|
|
20
|
+
padding: 1rem;
|
|
21
|
+
border: 1px solid var(--color-border);
|
|
22
|
+
border-radius: var(--radius);
|
|
23
|
+
|
|
24
|
+
&:disabled {
|
|
25
|
+
background: color-mix(in oklch, var(--color-foreground) 2%, var(--color-background));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&:disabled :is(.ui-label, .ui-legend) {
|
|
29
|
+
color: var(--color-disabled);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.ui-legend {
|
|
34
|
+
padding-inline: 0.375rem;
|
|
35
|
+
font-weight: 600;
|
|
36
|
+
line-height: 1.5;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.ui-datalist {
|
|
40
|
+
display: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.ui-progress,
|
|
44
|
+
.ui-meter {
|
|
45
|
+
--ui-color: var(--color-primary);
|
|
46
|
+
appearance: none;
|
|
47
|
+
display: block;
|
|
48
|
+
inline-size: 100%;
|
|
49
|
+
block-size: 0.5rem;
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
border: 0;
|
|
52
|
+
border-radius: var(--radius);
|
|
53
|
+
background: var(--color-input-fill);
|
|
54
|
+
accent-color: var(--ui-color);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.ui-progress::-webkit-progress-bar {
|
|
58
|
+
border-radius: inherit;
|
|
59
|
+
background: var(--color-input-fill);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.ui-progress::-webkit-progress-value {
|
|
63
|
+
border-radius: inherit;
|
|
64
|
+
background: var(--ui-color);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.ui-progress::-moz-progress-bar {
|
|
68
|
+
border-radius: inherit;
|
|
69
|
+
background: var(--ui-color);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.ui-progress:indeterminate::-webkit-progress-bar {
|
|
73
|
+
background: var(--ui-color);
|
|
74
|
+
clip-path: inset(0 32.5% round var(--radius));
|
|
75
|
+
animation: ui-progress-indeterminate 1.4s linear infinite;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.ui-meter {
|
|
79
|
+
--ui-color: var(--color-success);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.ui-meter::-webkit-meter-bar {
|
|
83
|
+
block-size: 0.5rem;
|
|
84
|
+
border: 0;
|
|
85
|
+
border-radius: inherit;
|
|
86
|
+
background: var(--color-input-fill);
|
|
87
|
+
box-shadow: none;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.ui-meter::-webkit-meter-optimum-value {
|
|
91
|
+
border-radius: inherit;
|
|
92
|
+
background: var(--ui-color);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.ui-meter::-webkit-meter-suboptimum-value {
|
|
96
|
+
border-radius: inherit;
|
|
97
|
+
background: var(--color-warning);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.ui-meter::-webkit-meter-even-less-good-value {
|
|
101
|
+
border-radius: inherit;
|
|
102
|
+
background: var(--color-error);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.ui-meter:-moz-meter-optimum::-moz-meter-bar {
|
|
106
|
+
background: var(--ui-color);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.ui-meter:-moz-meter-sub-optimum::-moz-meter-bar {
|
|
110
|
+
background: var(--color-warning);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.ui-meter:-moz-meter-sub-sub-optimum::-moz-meter-bar {
|
|
114
|
+
background: var(--color-error);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@keyframes ui-progress-indeterminate {
|
|
118
|
+
from {
|
|
119
|
+
clip-path: inset(0 100% 0 -35% round var(--radius));
|
|
120
|
+
}
|
|
121
|
+
to {
|
|
122
|
+
clip-path: inset(0 -35% 0 100% round var(--radius));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@media (prefers-reduced-motion: reduce) {
|
|
127
|
+
.ui-progress:indeterminate::-webkit-progress-bar {
|
|
128
|
+
animation: none;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
@layer components.ui {
|
|
2
|
+
.ui-group {
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: row;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: 1rem;
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
min-inline-size: 0;
|
|
9
|
+
|
|
10
|
+
&[data-orientation="vertical"] {
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
align-items: flex-start;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
@layer components.ui {
|
|
2
|
+
.ui-join {
|
|
3
|
+
display: inline-flex;
|
|
4
|
+
align-items: stretch;
|
|
5
|
+
gap: 0;
|
|
6
|
+
box-sizing: border-box;
|
|
7
|
+
min-inline-size: 0;
|
|
8
|
+
max-inline-size: 100%;
|
|
9
|
+
vertical-align: middle;
|
|
10
|
+
isolation: isolate;
|
|
11
|
+
|
|
12
|
+
// 混合输入框时填满可用宽度,按钮保留内容宽度,输入区域占据剩余空间。
|
|
13
|
+
&:has(> .ui-input:not([type="hidden"])) {
|
|
14
|
+
inline-size: 100%;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
> :is(.ui-button, .ui-input):not([type="hidden"]) {
|
|
18
|
+
position: relative;
|
|
19
|
+
z-index: 0;
|
|
20
|
+
flex: 0 0 auto;
|
|
21
|
+
min-inline-size: 0;
|
|
22
|
+
|
|
23
|
+
// 只计算实际控件,避免隐藏字段影响首尾圆角和边框拼接。
|
|
24
|
+
&:not(:nth-child(1 of :is(.ui-button, .ui-input):not([type="hidden"]))) {
|
|
25
|
+
margin-inline-start: -1px;
|
|
26
|
+
border-start-start-radius: 0;
|
|
27
|
+
border-end-start-radius: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&:not(:nth-last-child(1 of :is(.ui-button, .ui-input):not([type="hidden"]))) {
|
|
31
|
+
border-start-end-radius: 0;
|
|
32
|
+
border-end-end-radius: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&:is(
|
|
36
|
+
:hover,
|
|
37
|
+
:invalid,
|
|
38
|
+
[aria-invalid="true"],
|
|
39
|
+
[data-warning],
|
|
40
|
+
:has(> input:is(:invalid, [aria-invalid="true"], [data-warning]))
|
|
41
|
+
) {
|
|
42
|
+
z-index: 1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
&:is(:focus-visible, :focus-within) {
|
|
46
|
+
z-index: 2;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
> .ui-input:not([type="hidden"]):is(
|
|
51
|
+
:not([data-width]),
|
|
52
|
+
[data-width="default"],
|
|
53
|
+
[data-width=""]
|
|
54
|
+
) {
|
|
55
|
+
flex: 1 1 0%;
|
|
56
|
+
inline-size: 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 保持拼接边框稳定,按下按钮时不做单独的纵向位移。
|
|
60
|
+
> .ui-button:active {
|
|
61
|
+
transform: none;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
@layer components.ui {
|
|
2
|
+
// 表单元素基础设置
|
|
3
|
+
:where(
|
|
4
|
+
.ui-button,
|
|
5
|
+
.ui-addon-button,
|
|
6
|
+
.ui-checkbox,
|
|
7
|
+
.ui-radio,
|
|
8
|
+
.ui-switch,
|
|
9
|
+
.ui-slider,
|
|
10
|
+
.ui-tabs-list,
|
|
11
|
+
.ui-tab,
|
|
12
|
+
.ui-input,
|
|
13
|
+
.ui-label
|
|
14
|
+
) {
|
|
15
|
+
&,
|
|
16
|
+
& * {
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
font-family: inherit;
|
|
19
|
+
appearance: none;
|
|
20
|
+
position: relative;
|
|
21
|
+
margin: 0;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 共用 --ui-radius,让原生元素及其选择器弹层沿用同一圆角设置。
|
|
26
|
+
:is(.ui-input, .ui-button)[data-radius] {
|
|
27
|
+
--ui-radius: attr(data-radius type(*), var(--radius));
|
|
28
|
+
|
|
29
|
+
&:is([data-radius="default"], [data-radius=""]) {
|
|
30
|
+
--ui-radius: var(--radius);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&[data-radius="rounded"] {
|
|
34
|
+
--ui-radius: 9999px;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 默认值保留各控件原有宽度;显式尺寸优先于原生输入类型的专用宽度。
|
|
39
|
+
:is(.ui-input, .ui-button, .ui-addon-button)[data-width]:not(
|
|
40
|
+
[data-width="default"],
|
|
41
|
+
[data-width=""],
|
|
42
|
+
[type="hidden"]
|
|
43
|
+
) {
|
|
44
|
+
inline-size: attr(data-width type(*));
|
|
45
|
+
|
|
46
|
+
&[data-width="block"] {
|
|
47
|
+
display: var(--ui-block-display, flex);
|
|
48
|
+
inline-size: 100%;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
&[data-width="icon"] {
|
|
52
|
+
inline-size: var(--ui-height);
|
|
53
|
+
block-size: var(--ui-height);
|
|
54
|
+
min-block-size: var(--ui-height);
|
|
55
|
+
padding: 0;
|
|
56
|
+
flex-shrink: 0;
|
|
57
|
+
text-align: center;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
:is(
|
|
62
|
+
.ui-button,
|
|
63
|
+
.ui-addon-button,
|
|
64
|
+
.ui-input,
|
|
65
|
+
.ui-radio,
|
|
66
|
+
.ui-checkbox,
|
|
67
|
+
.ui-switch,
|
|
68
|
+
.ui-slider,
|
|
69
|
+
.ui-tabs-list,
|
|
70
|
+
.ui-tab,
|
|
71
|
+
.ui-progress,
|
|
72
|
+
.ui-meter,
|
|
73
|
+
.ui-badge,
|
|
74
|
+
.ui-pill
|
|
75
|
+
)[data-color] {
|
|
76
|
+
--ui-color: attr(data-color type(<color>));
|
|
77
|
+
&[data-color="neutral"] {
|
|
78
|
+
--ui-color: var(--color-foreground);
|
|
79
|
+
}
|
|
80
|
+
&[data-color="primary"] {
|
|
81
|
+
--ui-color: var(--color-primary);
|
|
82
|
+
}
|
|
83
|
+
&[data-color="success"] {
|
|
84
|
+
--ui-color: var(--color-success);
|
|
85
|
+
}
|
|
86
|
+
&[data-color="danger"] {
|
|
87
|
+
--ui-color: var(--color-danger);
|
|
88
|
+
}
|
|
89
|
+
&[data-color="error"] {
|
|
90
|
+
--ui-color: var(--color-error);
|
|
91
|
+
}
|
|
92
|
+
&[data-color="warning"] {
|
|
93
|
+
--ui-color: var(--color-warning);
|
|
94
|
+
}
|
|
95
|
+
&[data-color="info"] {
|
|
96
|
+
--ui-color: var(--color-info);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
@layer components.ui {
|
|
2
|
+
%ui-ghost-button-hover {
|
|
3
|
+
background-color: oklch(from var(--ui-display-color) calc(l * 0.1 + 0.9) calc(c * 0.2) h / 20%);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// button 结构性样式
|
|
7
|
+
.ui-button,
|
|
8
|
+
.ui-addon-button {
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
min-block-size: var(--ui-height);
|
|
12
|
+
padding-block: 0;
|
|
13
|
+
padding-inline: 1rem;
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
|
|
16
|
+
border: 1px solid transparent;
|
|
17
|
+
background: transparent;
|
|
18
|
+
border-radius: var(--ui-radius, 0);
|
|
19
|
+
|
|
20
|
+
--ui-display-color: var(--ui-color);
|
|
21
|
+
|
|
22
|
+
transition:
|
|
23
|
+
border-color var(--transition),
|
|
24
|
+
box-shadow var(--transition),
|
|
25
|
+
background-color var(--transition),
|
|
26
|
+
transform var(--transition),
|
|
27
|
+
outline var(--transition);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// button 通用外观
|
|
31
|
+
.ui-button,
|
|
32
|
+
.ui-addon-button {
|
|
33
|
+
--ui-radius: var(--radius);
|
|
34
|
+
--ui-color: var(--color-foreground, currentColor);
|
|
35
|
+
outline: 0 solid transparent;
|
|
36
|
+
&:focus-visible {
|
|
37
|
+
outline-width: 4px;
|
|
38
|
+
border-color: var(--ui-display-color);
|
|
39
|
+
outline-color: oklch(from var(--ui-display-color) l c h / 20%);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// button 按下位移
|
|
44
|
+
.ui-button {
|
|
45
|
+
&:active:not(:disabled, [aria-disabled="true"]) {
|
|
46
|
+
transform: translateY(1px);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// button 默认外观
|
|
51
|
+
.ui-button:is([data-variant="default"], [data-variant=""], :not([data-variant])) {
|
|
52
|
+
border-color: var(--color-border);
|
|
53
|
+
background: var(--color-background);
|
|
54
|
+
color: var(--ui-display-color);
|
|
55
|
+
|
|
56
|
+
&:hover:not(:disabled, [aria-disabled="true"]) {
|
|
57
|
+
background: color-mix(
|
|
58
|
+
in oklch,
|
|
59
|
+
oklch(from var(--color-foreground) calc(l * 0.1 + 0.9) calc(c * 0.2) h) 20%,
|
|
60
|
+
var(--color-background)
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// button 特殊外观
|
|
66
|
+
.ui-button[data-variant="outline"] {
|
|
67
|
+
background: transparent;
|
|
68
|
+
border-color: var(--ui-display-color);
|
|
69
|
+
color: var(--ui-display-color);
|
|
70
|
+
|
|
71
|
+
&:hover:not(:disabled, [aria-disabled="true"]) {
|
|
72
|
+
background: oklch(from var(--ui-display-color) calc(l * 0.1 + 0.9) calc(c * 0.2) h / 20%);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.ui-button[data-variant="filled"] {
|
|
77
|
+
background: var(--ui-display-color);
|
|
78
|
+
border-color: transparent;
|
|
79
|
+
color: var(--color-white, white);
|
|
80
|
+
|
|
81
|
+
&:hover:not(:disabled, [aria-disabled="true"]) {
|
|
82
|
+
background: oklch(from var(--ui-display-color) calc(l + 0.1) c h);
|
|
83
|
+
}
|
|
84
|
+
&:focus-visible {
|
|
85
|
+
border-color: var(--color-white, white);
|
|
86
|
+
outline-color: oklch(from var(--ui-display-color) l c h / 40%);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.ui-button[data-variant="light"] {
|
|
91
|
+
background: oklch(from var(--ui-display-color) calc(l * 0.05 + 0.95) calc(c * 0.1) h);
|
|
92
|
+
border-color: transparent;
|
|
93
|
+
color: var(--ui-display-color);
|
|
94
|
+
|
|
95
|
+
&:hover:not(:disabled, [aria-disabled="true"]) {
|
|
96
|
+
background: oklch(from var(--ui-display-color) calc(l * 0.05 + 0.925) calc(c * 0.15) h);
|
|
97
|
+
}
|
|
98
|
+
&:focus-visible {
|
|
99
|
+
border-color: var(--ui-display-color);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.ui-button[data-variant="ghost"],
|
|
104
|
+
.ui-addon-button {
|
|
105
|
+
background: transparent;
|
|
106
|
+
border-color: transparent;
|
|
107
|
+
color: var(--ui-display-color);
|
|
108
|
+
|
|
109
|
+
&:hover:not(:disabled, [aria-disabled="true"]) {
|
|
110
|
+
@extend %ui-ghost-button-hover;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.ui-button[data-variant="text"] {
|
|
115
|
+
background: transparent;
|
|
116
|
+
border-color: transparent;
|
|
117
|
+
color: var(--ui-display-color);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
:is(.ui-button, .ui-addon-button):is(:disabled, [aria-disabled="true"]) {
|
|
121
|
+
border-color: var(--color-border);
|
|
122
|
+
background: var(--color-input-fill);
|
|
123
|
+
color: var(--color-disabled);
|
|
124
|
+
cursor: not-allowed;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 复用 Ghost 按钮的交互,缩小高度、内边距和焦点环以适配输入框内部。
|
|
128
|
+
.ui-addon-button {
|
|
129
|
+
--ui-height: var(--ui-addon-height, max(0px, calc(var(--height-input) - 0.5rem)));
|
|
130
|
+
--ui-radius: max(0px, calc(var(--radius) - 0.125rem));
|
|
131
|
+
block-size: var(--ui-height);
|
|
132
|
+
flex: 0 0 auto;
|
|
133
|
+
gap: 0.25rem;
|
|
134
|
+
padding-inline: 0.5rem;
|
|
135
|
+
font-size: 0.8125rem;
|
|
136
|
+
white-space: nowrap;
|
|
137
|
+
|
|
138
|
+
&:focus-visible {
|
|
139
|
+
outline-width: 2px;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
&:is(:disabled, [aria-disabled="true"]) {
|
|
143
|
+
border-color: transparent;
|
|
144
|
+
background: transparent;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|