@ibobbyts/svelte-ui-utils 0.5.2 → 0.5.3
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 +21 -0
- package/dist/dropdown/Dropdown.svelte +8 -4
- package/dist/dropdown/Dropdown.svelte.d.ts.map +1 -1
- package/dist/style.css +66 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -890,6 +890,27 @@ inside a theme root:
|
|
|
890
890
|
}
|
|
891
891
|
```
|
|
892
892
|
|
|
893
|
+
### Overlay surface tokens
|
|
894
|
+
|
|
895
|
+
Dropdown menus render as floating overlays: they step the page background up
|
|
896
|
+
(`--suu-color-elevated`, derived from the surface/bg palette) and lift off the
|
|
897
|
+
page with `--suu-shadow-overlay` (a deep shadow plus a hairline ring so the
|
|
898
|
+
outline stays readable over host grid lines). Both resolve against the current
|
|
899
|
+
theme palette automatically.
|
|
900
|
+
|
|
901
|
+
Inside the menu, row semantics come from `--suu-dropdown-*` tokens declared on
|
|
902
|
+
`.suu-dropdown`: `--suu-dropdown-option-separator` (faint line between
|
|
903
|
+
options), `--suu-dropdown-group-border` / `--suu-dropdown-group-bg` /
|
|
904
|
+
`--suu-dropdown-group-text` (the section header band), and
|
|
905
|
+
`--suu-dropdown-option-hover-bg` / `--suu-dropdown-option-selected-bg` /
|
|
906
|
+
`--suu-dropdown-option-selected-hover-bg`. They are palette-derived color
|
|
907
|
+
mixes, so light and dark themes keep the same hierarchy: panel frame > group
|
|
908
|
+
band boundary > option separator, and selected > hover. Only override them for
|
|
909
|
+
a deliberately different overlay treatment.
|
|
910
|
+
|
|
911
|
+
下拉选项默认最小行高为 36px,分组标题为 32px;长文本仍可撑高。
|
|
912
|
+
分组通过中性底色、加粗标题和组内选项缩进区分,未分组的选项不缩进。
|
|
913
|
+
|
|
893
914
|
### Corner-radius tokens
|
|
894
915
|
|
|
895
916
|
All non-zero component corner radii come from the token definitions in
|
|
@@ -65,7 +65,11 @@
|
|
|
65
65
|
export let onTriggerClick: DropdownTriggerClickHandler | undefined = undefined;
|
|
66
66
|
|
|
67
67
|
const viewportMargin = 20;
|
|
68
|
-
const menuGap =
|
|
68
|
+
const menuGap = 4;
|
|
69
|
+
// The menu overhangs the trigger horizontally so its edges break from the
|
|
70
|
+
// host layout's lines (table column borders, adjacent inputs) and read as an
|
|
71
|
+
// independent floating layer instead of a continuation of the grid.
|
|
72
|
+
const menuOutset = 4;
|
|
69
73
|
const instanceId = ++dropdownInstanceCount;
|
|
70
74
|
|
|
71
75
|
let open = false;
|
|
@@ -783,12 +787,12 @@
|
|
|
783
787
|
)}px`;
|
|
784
788
|
if (menuAlign === 'right') {
|
|
785
789
|
portalMenuLeft = undefined;
|
|
786
|
-
portalMenuRight = `${Math.round(window.innerWidth - rect.right)}px`;
|
|
790
|
+
portalMenuRight = `${Math.max(0, Math.round(window.innerWidth - rect.right - menuOutset))}px`;
|
|
787
791
|
} else {
|
|
788
|
-
portalMenuLeft = `${Math.round(rect.left)}px`;
|
|
792
|
+
portalMenuLeft = `${Math.max(0, Math.round(rect.left - menuOutset))}px`;
|
|
789
793
|
portalMenuRight = undefined;
|
|
790
794
|
}
|
|
791
|
-
portalMenuWidth = `${Math.round(rect.width)}px`;
|
|
795
|
+
portalMenuWidth = `${Math.round(rect.width + menuOutset * 2)}px`;
|
|
792
796
|
}
|
|
793
797
|
|
|
794
798
|
function portalMenu(node: HTMLDivElement, enabled: boolean) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/Dropdown.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAER,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EAGnB,iBAAiB,EAGjB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,8BAA8B,EAC9B,2BAA2B,EAC3B,iBAAiB,EACjB,2BAA2B,EAE5B,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/Dropdown.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAER,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EAGnB,iBAAiB,EAGjB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,8BAA8B,EAC9B,2BAA2B,EAC3B,iBAAiB,EACjB,2BAA2B,EAE5B,MAAM,YAAY,CAAC;AAs9BtB,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,QAAQ;SAXw3B,MAAM,GAAG,SAAS;YAAU,iBAAiB;;cAA8C,cAAc,EAAE;mBAAiB,mBAAmB,EAAE,GAAG,SAAS;IACniC,sFAAsF,mBAAkB,cAAc,EAAE;+BAA6B,MAAM,GAAG,OAAO,GAAG,MAAM;;iBAAuC,kBAAkB;mBAAiB,uBAAuB;kBAAgB,mBAAmB,GAAG,SAAS;;;wBAAoG,MAAM,GAAG,SAAS;kBAAgB,MAAM,GAAG,SAAS;eAAa,UAAU;kBAAgB,MAAM,GAAG,SAAS;oBAAkB,MAAM,GAAG,SAAS;gBAAc,MAAM,GAAG,SAAS;gBAAc,MAAM,GAAG,SAAS;gBAAc,iBAAiB;gBAAc,iBAAiB;;;;WAAuG,MAAM,GAAG,SAAS;;YAAsC,MAAM,GAAG,SAAS;eAAa,MAAM,GAAG,SAAS;eAAa,MAAM,GAAG,SAAS;gBAAc,MAAM,GAAG,SAAS;;eAAqC,8BAA8B,GAAG,SAAS;qBAAmB,2BAA2B,GAAG,SAAS;qBAAmB,2BAA2B,GAAG,SAAS;;;;;kBAUtiC,CAAC;AAC5E,KAAK,QAAQ,GAAG,YAAY,CAAC,OAAO,QAAQ,CAAC,CAAC;AAChD,eAAe,QAAQ,CAAC"}
|
package/dist/style.css
CHANGED
|
@@ -12,6 +12,14 @@
|
|
|
12
12
|
--suu-color-warning: #d97706;
|
|
13
13
|
--suu-color-info: #2563eb;
|
|
14
14
|
--suu-shadow: 0 12px 30px rgb(15 23 42 / 0.14);
|
|
15
|
+
/* Overlay surfaces (dropdown menus) float above the page: they step the page
|
|
16
|
+
background up toward the surface color instead of reusing it and get a
|
|
17
|
+
deep shadow plus a hairline ring so their outline stays readable even
|
|
18
|
+
where host grid lines (table borders, adjacent inputs) run under them.
|
|
19
|
+
The elevated token references the base palette lazily, so theme and
|
|
20
|
+
consumer-side remaps of surface/border apply automatically. */
|
|
21
|
+
--suu-color-elevated: color-mix(in srgb, var(--suu-color-surface) 45%, var(--suu-color-bg));
|
|
22
|
+
--suu-shadow-overlay: 0 12px 32px rgb(15 23 42 / 0.2), 0 0 0 1px rgb(15 23 42 / 0.06);
|
|
15
23
|
--suu-radius-xs: 4px;
|
|
16
24
|
--suu-radius-sm: 6px;
|
|
17
25
|
--suu-radius-md: 8px;
|
|
@@ -37,6 +45,7 @@
|
|
|
37
45
|
--suu-color-warning: #fbbf24;
|
|
38
46
|
--suu-color-info: #60a5fa;
|
|
39
47
|
--suu-shadow: 0 16px 34px rgb(0 0 0 / 0.32);
|
|
48
|
+
--suu-shadow-overlay: 0 12px 32px rgb(0 0 0 / 0.45), 0 0 0 1px rgb(255 255 255 / 0.025);
|
|
40
49
|
}
|
|
41
50
|
|
|
42
51
|
.suu-visually-hidden {
|
|
@@ -895,6 +904,16 @@
|
|
|
895
904
|
|
|
896
905
|
.suu-dropdown {
|
|
897
906
|
--suu-dropdown-space: 14px;
|
|
907
|
+
/* Menu row semantics, all derived from the theme palette so light and dark
|
|
908
|
+
keep the same ladder: panel frame > group band boundary > option
|
|
909
|
+
separator, and selected > hover. */
|
|
910
|
+
--suu-dropdown-option-separator: color-mix(in srgb, var(--suu-color-border) 24%, transparent);
|
|
911
|
+
--suu-dropdown-group-border: color-mix(in srgb, var(--suu-color-border) 80%, transparent);
|
|
912
|
+
--suu-dropdown-group-bg: color-mix(in srgb, var(--suu-color-muted) 18%, var(--suu-color-elevated));
|
|
913
|
+
--suu-dropdown-group-text: var(--suu-color-text);
|
|
914
|
+
--suu-dropdown-option-hover-bg: color-mix(in srgb, var(--suu-color-muted) 7%, var(--suu-color-elevated));
|
|
915
|
+
--suu-dropdown-option-selected-bg: color-mix(in srgb, var(--suu-color-accent) 12%, var(--suu-color-elevated));
|
|
916
|
+
--suu-dropdown-option-selected-hover-bg: color-mix(in srgb, var(--suu-color-accent) 18%, var(--suu-color-elevated));
|
|
898
917
|
|
|
899
918
|
position: relative;
|
|
900
919
|
display: inline-flex;
|
|
@@ -1018,18 +1037,24 @@
|
|
|
1018
1037
|
transform: translateY(-20%) rotate(45deg);
|
|
1019
1038
|
}
|
|
1020
1039
|
|
|
1040
|
+
/* The menu is a floating overlay, not a table that grew downward: its
|
|
1041
|
+
background steps above the page, the shadow ring keeps the outline readable
|
|
1042
|
+
where host grid lines run under it, and it overhangs the trigger by 4px on
|
|
1043
|
+
each side so its edges never sit on the same lines as the surrounding
|
|
1044
|
+
layout. Internal lines follow the --suu-dropdown-* row tokens so the
|
|
1045
|
+
ladder stays: panel frame > group band boundary > option separator. */
|
|
1021
1046
|
.suu-dropdown__menu {
|
|
1022
1047
|
position: absolute;
|
|
1023
|
-
top: calc(100% +
|
|
1024
|
-
right:
|
|
1048
|
+
top: calc(100% + 4px);
|
|
1049
|
+
right: -4px;
|
|
1025
1050
|
left: auto;
|
|
1026
1051
|
z-index: 100;
|
|
1027
|
-
min-width: 100
|
|
1052
|
+
min-width: calc(100% + 8px);
|
|
1028
1053
|
overflow: hidden;
|
|
1029
1054
|
border: 1px solid var(--suu-color-border);
|
|
1030
1055
|
border-radius: var(--suu-radius);
|
|
1031
|
-
background: var(--suu-color-
|
|
1032
|
-
box-shadow:
|
|
1056
|
+
background: var(--suu-color-elevated);
|
|
1057
|
+
box-shadow: var(--suu-shadow-overlay);
|
|
1033
1058
|
/* Reset inherited host whitespace (e.g. a nowrap table cell) so every menu
|
|
1034
1059
|
text — group titles, status labels — wraps by default; the single-line
|
|
1035
1060
|
fit-content rules set nowrap explicitly where needed. */
|
|
@@ -1057,17 +1082,17 @@
|
|
|
1057
1082
|
|
|
1058
1083
|
.suu-dropdown__menu--left:not(.suu-dropdown__menu--portal) {
|
|
1059
1084
|
right: auto;
|
|
1060
|
-
left:
|
|
1085
|
+
left: -4px;
|
|
1061
1086
|
}
|
|
1062
1087
|
|
|
1063
1088
|
.suu-dropdown__menu--right:not(.suu-dropdown__menu--portal) {
|
|
1064
|
-
right:
|
|
1089
|
+
right: -4px;
|
|
1065
1090
|
left: auto;
|
|
1066
1091
|
}
|
|
1067
1092
|
|
|
1068
1093
|
.suu-dropdown__menu--up:not(.suu-dropdown__menu--portal) {
|
|
1069
1094
|
top: auto;
|
|
1070
|
-
bottom: calc(100% +
|
|
1095
|
+
bottom: calc(100% + 4px);
|
|
1071
1096
|
}
|
|
1072
1097
|
|
|
1073
1098
|
.suu-dropdown__menu--fit-content:not(.suu-dropdown__menu--portal) {
|
|
@@ -1102,26 +1127,31 @@
|
|
|
1102
1127
|
max-height: var(--suu-dropdown-panel-max-height, 100vh);
|
|
1103
1128
|
overflow-y: auto;
|
|
1104
1129
|
overflow-x: hidden;
|
|
1105
|
-
background: var(--suu-color-
|
|
1130
|
+
background: var(--suu-color-elevated);
|
|
1106
1131
|
overscroll-behavior: contain;
|
|
1107
1132
|
}
|
|
1108
1133
|
|
|
1109
1134
|
.suu-dropdown__group + .suu-dropdown__group {
|
|
1110
|
-
border-top: 1px solid var(--suu-
|
|
1135
|
+
border-top: 1px solid var(--suu-dropdown-group-border);
|
|
1111
1136
|
}
|
|
1112
1137
|
|
|
1138
|
+
/* 分组用中性底色和粗体形成标题带,避免与蓝色选中态混淆。
|
|
1139
|
+
font 简写必须位于字号和字重之前,防止覆盖标题层级。 */
|
|
1113
1140
|
.suu-dropdown__group-label {
|
|
1114
1141
|
display: flex;
|
|
1115
1142
|
width: 100%;
|
|
1116
1143
|
border: 0;
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1144
|
+
border-bottom: 1px solid var(--suu-dropdown-group-border);
|
|
1145
|
+
min-height: 32px;
|
|
1146
|
+
padding: 6px 14px;
|
|
1147
|
+
background: var(--suu-dropdown-group-bg);
|
|
1148
|
+
color: var(--suu-dropdown-group-text);
|
|
1120
1149
|
cursor: pointer;
|
|
1121
|
-
font
|
|
1150
|
+
font: inherit;
|
|
1151
|
+
font-size: 0.8125em;
|
|
1122
1152
|
font-weight: 700;
|
|
1153
|
+
line-height: 1.3;
|
|
1123
1154
|
letter-spacing: 0.02em;
|
|
1124
|
-
font: inherit;
|
|
1125
1155
|
text-align: left;
|
|
1126
1156
|
align-items: center;
|
|
1127
1157
|
justify-content: space-between;
|
|
@@ -1150,12 +1180,15 @@
|
|
|
1150
1180
|
transform: rotate(45deg);
|
|
1151
1181
|
}
|
|
1152
1182
|
|
|
1183
|
+
/* 收紧单行选项的留白,长名称仍由内容撑高;分隔线保持弱于分组边界。 */
|
|
1153
1184
|
.suu-dropdown__option {
|
|
1154
|
-
display:
|
|
1185
|
+
display: flex;
|
|
1186
|
+
align-items: center;
|
|
1155
1187
|
width: 100%;
|
|
1156
|
-
|
|
1188
|
+
min-height: 36px;
|
|
1189
|
+
padding: 6px 14px;
|
|
1157
1190
|
border: 0;
|
|
1158
|
-
border-bottom: 1px solid var(--suu-
|
|
1191
|
+
border-bottom: 1px solid var(--suu-dropdown-option-separator);
|
|
1159
1192
|
background: transparent;
|
|
1160
1193
|
color: var(--suu-color-text);
|
|
1161
1194
|
cursor: pointer;
|
|
@@ -1163,14 +1196,13 @@
|
|
|
1163
1196
|
text-align: left;
|
|
1164
1197
|
}
|
|
1165
1198
|
|
|
1166
|
-
|
|
1167
|
-
|
|
1199
|
+
/* 仅有标题的组选项缩进,未分组的「未选择」等操作保持原始对齐。 */
|
|
1200
|
+
.suu-dropdown__group-label ~ .suu-dropdown__option {
|
|
1201
|
+
padding-inline-start: 24px;
|
|
1168
1202
|
}
|
|
1169
1203
|
|
|
1170
1204
|
.suu-dropdown--multiselect .suu-dropdown__option {
|
|
1171
|
-
display: flex;
|
|
1172
1205
|
gap: 10px;
|
|
1173
|
-
align-items: center;
|
|
1174
1206
|
}
|
|
1175
1207
|
|
|
1176
1208
|
.suu-dropdown__checkbox {
|
|
@@ -1207,15 +1239,24 @@
|
|
|
1207
1239
|
.suu-dropdown__option:hover,
|
|
1208
1240
|
.suu-dropdown__option:focus-visible,
|
|
1209
1241
|
.suu-dropdown__option--active {
|
|
1210
|
-
background: var(--suu-
|
|
1242
|
+
background: var(--suu-dropdown-option-hover-bg);
|
|
1211
1243
|
outline: none;
|
|
1212
1244
|
}
|
|
1213
1245
|
|
|
1246
|
+
/* The selected row is a clear area, not just colored text; hover on top of it
|
|
1247
|
+
deepens the tint one step so the two states stay distinguishable. */
|
|
1214
1248
|
.suu-dropdown__option[aria-selected='true'] {
|
|
1249
|
+
background: var(--suu-dropdown-option-selected-bg);
|
|
1215
1250
|
color: var(--suu-color-accent);
|
|
1216
1251
|
font-weight: 700;
|
|
1217
1252
|
}
|
|
1218
1253
|
|
|
1254
|
+
.suu-dropdown__option[aria-selected='true']:hover,
|
|
1255
|
+
.suu-dropdown__option[aria-selected='true']:focus-visible,
|
|
1256
|
+
.suu-dropdown__option[aria-selected='true'].suu-dropdown__option--active {
|
|
1257
|
+
background: var(--suu-dropdown-option-selected-hover-bg);
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1219
1260
|
.suu-dropdown__option--disabled,
|
|
1220
1261
|
.suu-dropdown__option:disabled {
|
|
1221
1262
|
cursor: not-allowed;
|
|
@@ -1228,8 +1269,8 @@
|
|
|
1228
1269
|
gap: 8px;
|
|
1229
1270
|
align-items: center;
|
|
1230
1271
|
padding: 8px 14px;
|
|
1231
|
-
border-bottom: 1px solid var(--suu-
|
|
1232
|
-
background: var(--suu-color-
|
|
1272
|
+
border-bottom: 1px solid var(--suu-dropdown-group-border);
|
|
1273
|
+
background: var(--suu-color-surface);
|
|
1233
1274
|
}
|
|
1234
1275
|
|
|
1235
1276
|
.suu-dropdown__search-icon {
|