@celestia-island/hikari 0.43.10 → 0.43.13
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/package.json +1 -1
- package/src/components/HkAboutModal.scss +12 -1
- package/src/components/HkAdaptiveDialog.scss +2 -2
- package/src/components/HkAffixPicker.scss +55 -27
- package/src/components/HkAlert.scss +35 -31
- package/src/components/HkAltSignIn.scss +10 -4
- package/src/components/HkAuthMethodList.scss +5 -5
- package/src/components/HkAuthSubmitButton.scss +3 -3
- package/src/components/HkAvatar.scss +10 -49
- package/src/components/HkBadge.scss +6 -9
- package/src/components/HkBlockingToast.scss +27 -10
- package/src/components/HkBoard.scss +26 -6
- package/src/components/HkBreadcrumb.scss +82 -268
- package/src/components/HkButton.scss +26 -3
- package/src/components/HkCaptchaWidget.scss +2 -3
- package/src/components/HkCard.scss +14 -8
- package/src/components/HkCheckbox.scss +11 -9
- package/src/components/HkColorPicker.scss +22 -8
- package/src/components/HkContextRing.scss +8 -4
- package/src/components/HkCookieConsent.scss +12 -3
- package/src/components/HkDatePicker.scss +49 -65
- package/src/components/HkDateTimePicker.scss +48 -31
- package/src/components/HkDivider.scss +14 -15
- package/src/components/HkDraggableGrid.scss +41 -11
- package/src/components/HkDraggableList.scss +22 -11
- package/src/components/HkDrawer.scss +24 -4
- package/src/components/HkEmptyState.scss +10 -11
- package/src/components/HkErrorLanding.scss +5 -5
- package/src/components/HkExpansionPanel.scss +6 -2
- package/src/components/HkFab.scss +29 -12
- package/src/components/HkFileBrowserDialog.scss +21 -10
- package/src/components/HkFileField.scss +20 -9
- package/src/components/HkFilePickerField.scss +12 -6
- package/src/components/HkGaugeRing.scss +8 -0
- package/src/components/HkHoverRevealAction.scss +30 -12
- package/src/components/HkIcon.scss +0 -18
- package/src/components/HkIconButton.scss +29 -62
- package/src/components/HkIconButtonVars.scss +8 -28
- package/src/components/HkImageLightbox.scss +4 -3
- package/src/components/HkImagePreview.scss +17 -9
- package/src/components/HkImageViewer.scss +8 -0
- package/src/components/HkInput.scss +28 -28
- package/src/components/HkJsonTree.scss +13 -9
- package/src/components/HkKeywordSearchModal.scss +40 -29
- package/src/components/HkLabel.scss +8 -3
- package/src/components/HkListTransition.scss +16 -1
- package/src/components/HkLoadMore.scss +11 -2
- package/src/components/HkLocalizedInput.scss +11 -11
- package/src/components/HkLogWindow.scss +22 -4
- package/src/components/HkLogo.scss +12 -3
- package/src/components/HkMarkdownRenderer.scss +19 -13
- package/src/components/HkMediaControlBar.scss +2 -4
- package/src/components/HkMediaSlider.scss +0 -2
- package/src/components/HkMenu.scss +32 -20
- package/src/components/HkMenuIdentityItem.scss +3 -3
- package/src/components/HkMinimap.scss +23 -8
- package/src/components/HkModal.scss +17 -20
- package/src/components/HkModalBreadcrumb.scss +25 -6
- package/src/components/HkModelTag.scss +23 -13
- package/src/components/HkNavItem.scss +27 -14
- package/src/components/HkNumberInput.scss +25 -21
- package/src/components/HkPageHeader.scss +7 -6
- package/src/components/HkPasswordInput.scss +36 -36
- package/src/components/HkPhaseTransition.scss +16 -0
- package/src/components/HkPhoneInput.scss +10 -5
- package/src/components/HkPickerPane.scss +32 -5
- package/src/components/HkPlaceholderMarquee.scss +7 -2
- package/src/components/HkPlaceholderMarquee.test.ts +27 -0
- package/src/components/HkPlaceholderMarquee.tsx +14 -6
- package/src/components/HkPopover.scss +18 -10
- package/src/components/HkPopupSelect.scss +28 -7
- package/src/components/HkProgressBar.scss +29 -7
- package/src/components/HkProgressDialog.scss +4 -2
- package/src/components/HkProgressRing.scss +7 -14
- package/src/components/HkProtocolModal.scss +0 -3
- package/src/components/HkQrCode.scss +2 -2
- package/src/components/HkRadio.scss +15 -6
- package/src/components/HkRichInput.scss +29 -13
- package/src/components/HkRollingNumber.scss +14 -6
- package/src/components/HkScrollContainer.scss +20 -8
- package/src/components/HkSearchInput.scss +12 -10
- package/src/components/HkSecretRevealModal.scss +11 -1
- package/src/components/HkSelect.scss +35 -17
- package/src/components/HkSelectionGrid.scss +41 -20
- package/src/components/HkSelectionWaterfall.scss +21 -9
- package/src/components/HkShareBar.scss +14 -5
- package/src/components/HkSidebar.scss +23 -9
- package/src/components/HkSkeleton.scss +16 -8
- package/src/components/HkSlider.scss +12 -2
- package/src/components/HkSpinner.scss +15 -9
- package/src/components/HkSplash.scss +10 -10
- package/src/components/HkStatCard.scss +7 -3
- package/src/components/HkStatusPill.scss +4 -7
- package/src/components/HkStepFlow.scss +24 -4
- package/src/components/HkSwitch.scss +41 -9
- package/src/components/HkTable.scss +25 -20
- package/src/components/HkTabs.scss +40 -26
- package/src/components/HkTag.scss +35 -29
- package/src/components/HkTagInput.scss +22 -16
- package/src/components/HkTextarea.scss +8 -6
- package/src/components/HkThemeToggle.scss +28 -18
- package/src/components/HkTimeline.scss +46 -29
- package/src/components/HkTimeline.test.tsx +39 -0
- package/src/components/HkTimeline.tsx +16 -2
- package/src/components/HkTitleBar.scss +16 -7
- package/src/components/HkToast.scss +40 -10
- package/src/components/HkTokenUsagePanel.scss +11 -6
- package/src/components/HkToolBlock.scss +23 -11
- package/src/components/HkTooltip.scss +5 -9
- package/src/components/HkTree.scss +26 -35
- package/src/components/HkVoiceInputPopup.scss +11 -6
- package/src/components/HkWindowedItem.scss +3 -9
- package/src/components/HkZoomToolbar.scss +12 -10
- package/src/components/_menu-item.scss +4 -3
- package/src/components/window-close.scss +8 -13
- package/src/composables/layoutGeometry.test.ts +177 -0
- package/src/composables/layoutGeometry.ts +231 -0
- package/src/composables/useOverlayScrollbar.test.ts +32 -0
- package/src/composables/useOverlayScrollbar.ts +9 -1
- package/src/composables/usePointerReorder.test.ts +5 -2
- package/src/composables/usePointerReorder.ts +83 -147
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* Field caption, mirroring .hk-input-label in HkInput.scss (the number
|
|
2
|
-
input carries its own copy so it does not depend on
|
|
2
|
+
input carries its own copy so it does not depend on HkInput's stylesheet
|
|
3
3
|
being loaded too). */
|
|
4
4
|
.hk-input-label {
|
|
5
5
|
display: block;
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
align-items: center;
|
|
26
26
|
background: var(--hi-color-surface);
|
|
27
27
|
border: 1px solid var(--hi-color-border);
|
|
28
|
-
border-radius: var(--hi-radius-md,
|
|
28
|
+
border-radius: var(--hi-radius-md, 8px);
|
|
29
29
|
overflow: hidden;
|
|
30
30
|
transition:
|
|
31
31
|
background-color var(--hi-transition-base, 200ms cubic-bezier(0.4, 0, 0.2, 1)),
|
|
@@ -53,9 +53,10 @@
|
|
|
53
53
|
outline: none;
|
|
54
54
|
color: var(--hi-color-text-primary);
|
|
55
55
|
font-family: inherit;
|
|
56
|
-
|
|
56
|
+
/* Font size / horizontal padding come from the per-size blocks below —
|
|
57
|
+
the size class is always on the wrapper (HkNumberInput.tsx), so the
|
|
58
|
+
md block is the single source for those metrics. */
|
|
57
59
|
line-height: 1.5;
|
|
58
|
-
padding: 0 0.75rem;
|
|
59
60
|
|
|
60
61
|
&::placeholder {
|
|
61
62
|
color: var(--hi-color-muted);
|
|
@@ -83,11 +84,11 @@
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
.hk-number-input-prefix {
|
|
86
|
-
padding-
|
|
87
|
+
padding-inline-start: var(--space-12, 0.75rem);
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
.hk-number-input-suffix {
|
|
90
|
-
padding-
|
|
91
|
+
padding-inline-end: var(--space-8, 0.5rem);
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
.hk-number-input-steppers {
|
|
@@ -98,14 +99,17 @@
|
|
|
98
99
|
against the real box height and the divider spans it fully —
|
|
99
100
|
content-sized centering left a floating ~28px stack in a 36px box. */
|
|
100
101
|
align-self: stretch;
|
|
101
|
-
|
|
102
|
+
/* Inline-start so the divider faces the field/suffix side in both
|
|
103
|
+
LTR and RTL (the flex row flips under direction: rtl). */
|
|
104
|
+
border-inline-start: 1px solid var(--hi-color-border);
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
.hk-number-input-step {
|
|
105
108
|
display: flex;
|
|
106
109
|
align-items: center;
|
|
107
110
|
justify-content: center;
|
|
108
|
-
|
|
111
|
+
/* Width comes from the per-size blocks below (the size class is always
|
|
112
|
+
on the wrapper); height stays here as the size-independent half. */
|
|
109
113
|
height: 50%;
|
|
110
114
|
padding: 0;
|
|
111
115
|
background: transparent;
|
|
@@ -135,18 +139,18 @@
|
|
|
135
139
|
/* --- Size variants --- */
|
|
136
140
|
|
|
137
141
|
.hk-number-input-sm .hk-number-input-field {
|
|
138
|
-
font-size: 0.75rem;
|
|
139
|
-
padding: 0 0.5rem;
|
|
140
|
-
height: 1.75rem;
|
|
142
|
+
font-size: var(--text-xs, 0.75rem);
|
|
143
|
+
padding: 0 var(--space-8, 0.5rem);
|
|
144
|
+
height: var(--space-28, 1.75rem);
|
|
141
145
|
}
|
|
142
146
|
|
|
143
147
|
.hk-number-input-sm .hk-number-input-prefix,
|
|
144
148
|
.hk-number-input-sm .hk-number-input-suffix {
|
|
145
|
-
font-size: 0.75rem;
|
|
149
|
+
font-size: var(--text-xs, 0.75rem);
|
|
146
150
|
}
|
|
147
151
|
|
|
148
152
|
.hk-number-input-sm .hk-number-input-step {
|
|
149
|
-
width: 1.25rem;
|
|
153
|
+
width: var(--space-20, 1.25rem);
|
|
150
154
|
}
|
|
151
155
|
|
|
152
156
|
.hk-number-input-sm .hk-number-input-step svg {
|
|
@@ -155,33 +159,33 @@
|
|
|
155
159
|
}
|
|
156
160
|
|
|
157
161
|
.hk-number-input-md .hk-number-input-field {
|
|
158
|
-
font-size: 0.875rem;
|
|
159
|
-
padding: 0 0.75rem;
|
|
162
|
+
font-size: var(--text-base, 0.875rem);
|
|
163
|
+
padding: 0 var(--space-12, 0.75rem);
|
|
160
164
|
height: 2.25rem;
|
|
161
165
|
}
|
|
162
166
|
|
|
163
167
|
.hk-number-input-md .hk-number-input-prefix,
|
|
164
168
|
.hk-number-input-md .hk-number-input-suffix {
|
|
165
|
-
font-size: 0.875rem;
|
|
169
|
+
font-size: var(--text-base, 0.875rem);
|
|
166
170
|
}
|
|
167
171
|
|
|
168
172
|
.hk-number-input-md .hk-number-input-step {
|
|
169
|
-
width: 1.5rem;
|
|
173
|
+
width: var(--space-24, 1.5rem);
|
|
170
174
|
}
|
|
171
175
|
|
|
172
176
|
.hk-number-input-lg .hk-number-input-field {
|
|
173
|
-
font-size: 1rem;
|
|
174
|
-
padding: 0 1rem;
|
|
177
|
+
font-size: var(--text-md, 1rem);
|
|
178
|
+
padding: 0 var(--space-16, 1rem);
|
|
175
179
|
height: 2.75rem;
|
|
176
180
|
}
|
|
177
181
|
|
|
178
182
|
.hk-number-input-lg .hk-number-input-prefix,
|
|
179
183
|
.hk-number-input-lg .hk-number-input-suffix {
|
|
180
|
-
font-size: 1rem;
|
|
184
|
+
font-size: var(--text-md, 1rem);
|
|
181
185
|
}
|
|
182
186
|
|
|
183
187
|
.hk-number-input-lg .hk-number-input-step {
|
|
184
|
-
width: 1.75rem;
|
|
188
|
+
width: var(--space-28, 1.75rem);
|
|
185
189
|
}
|
|
186
190
|
|
|
187
191
|
.hk-number-input-lg .hk-number-input-step svg {
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
display: inline-flex;
|
|
34
34
|
align-items: center;
|
|
35
35
|
justify-content: center;
|
|
36
|
-
width: 1.75rem;
|
|
37
|
-
height: 1.75rem;
|
|
36
|
+
width: var(--space-28, 1.75rem);
|
|
37
|
+
height: var(--space-28, 1.75rem);
|
|
38
38
|
flex-shrink: 0;
|
|
39
39
|
border-radius: var(--radius-sm, 6px);
|
|
40
40
|
background: rgb(var(--color-primary) / 10%);
|
|
@@ -59,8 +59,9 @@
|
|
|
59
59
|
align-items: center;
|
|
60
60
|
gap: var(--space-8, 0.5rem);
|
|
61
61
|
flex-shrink: 0;
|
|
62
|
-
/* Align the tool row with the title baseline;
|
|
63
|
-
|
|
62
|
+
/* Align the tool row with the title baseline; align-items: flex-end
|
|
63
|
+
applies per wrapped line too, and this 2px nudge optically matches
|
|
64
|
+
the title's descender space. */
|
|
64
65
|
padding-block-end: var(--space-2, 0.125rem);
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -73,7 +74,7 @@
|
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
.hk-page-header-icon {
|
|
76
|
-
width: 1.5rem;
|
|
77
|
-
height: 1.5rem;
|
|
77
|
+
width: var(--space-24, 1.5rem);
|
|
78
|
+
height: var(--space-24, 1.5rem);
|
|
78
79
|
}
|
|
79
80
|
}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
.hk-pwd-required {
|
|
19
|
-
margin-
|
|
19
|
+
margin-inline-start: var(--space-2);
|
|
20
20
|
color: var(--hi-color-danger, #f85149);
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
display: flex;
|
|
26
26
|
align-items: center;
|
|
27
27
|
min-height: 2.5rem;
|
|
28
|
-
padding:
|
|
28
|
+
padding: var(--space-8) var(--space-12);
|
|
29
29
|
background: color-mix(in srgb, rgb(var(--color-surface)) 55%, transparent);
|
|
30
30
|
border: 1px solid color-mix(in srgb, rgb(var(--color-text)) 14%, transparent);
|
|
31
31
|
border-radius: 6px;
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
|
|
52
52
|
.hk-pwd-box[data-error][data-focused] {
|
|
53
53
|
border-color: var(--hi-color-danger, #f85149);
|
|
54
|
-
box-shadow: 0 0 0 3px
|
|
54
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--hi-color-danger, #f85149) 15%, transparent);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
.hk-pwd-box[data-disabled] {
|
|
@@ -101,12 +101,15 @@
|
|
|
101
101
|
cursor: pointer;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
/* Hover feedback for the hold-to-reveal control, mirroring the blur
|
|
105
|
+
* hint's hover; suppressed while revealing (press restores full
|
|
106
|
+
* primary) and while disabled (reveal is unreachable). */
|
|
107
|
+
.hk-pwd-box:not([data-disabled]) .hk-pwd-lock-filled:hover:not([data-revealing]) {
|
|
108
|
+
color: color-mix(in srgb, var(--hi-color-primary, #58a6ff) 75%, transparent);
|
|
107
109
|
}
|
|
108
110
|
|
|
109
|
-
.hk-pwd-
|
|
111
|
+
.hk-pwd-box:focus-within .hk-pwd-lock,
|
|
112
|
+
.hk-pwd-box[data-focused] .hk-pwd-lock {
|
|
110
113
|
color: var(--hi-color-primary, #58a6ff);
|
|
111
114
|
}
|
|
112
115
|
|
|
@@ -128,7 +131,7 @@
|
|
|
128
131
|
justify-content: center;
|
|
129
132
|
z-index: 1;
|
|
130
133
|
user-select: none;
|
|
131
|
-
font-size:
|
|
134
|
+
font-size: var(--text-base);
|
|
132
135
|
color: var(--hi-color-primary, rgba(88, 166, 255, 0.7));
|
|
133
136
|
animation: hk-pwd-breathe 3s ease-in-out infinite;
|
|
134
137
|
/* Default overflow strategy: hard-cut with an ellipsis (the marquee
|
|
@@ -150,6 +153,17 @@
|
|
|
150
153
|
50% { opacity: 0.7; }
|
|
151
154
|
}
|
|
152
155
|
|
|
156
|
+
/* Reduced motion: stop the infinite breathe pulse. The global switch
|
|
157
|
+
* (`html[data-css-animations="0"]`) pauses it too when the host wired
|
|
158
|
+
* it; the media block covers hosts that never did. */
|
|
159
|
+
@media (prefers-reduced-motion: reduce) {
|
|
160
|
+
.hk-pwd-placeholder,
|
|
161
|
+
.hk-pwd-blur-hint,
|
|
162
|
+
.hk-pwd-select-hint {
|
|
163
|
+
animation: none;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
153
167
|
.hk-pwd-blur-hint {
|
|
154
168
|
position: absolute;
|
|
155
169
|
inset: 0;
|
|
@@ -158,7 +172,7 @@
|
|
|
158
172
|
justify-content: center;
|
|
159
173
|
z-index: 1;
|
|
160
174
|
user-select: none;
|
|
161
|
-
font-size:
|
|
175
|
+
font-size: var(--text-base);
|
|
162
176
|
font-style: italic;
|
|
163
177
|
color: var(--hi-color-text-secondary, #666);
|
|
164
178
|
cursor: pointer;
|
|
@@ -182,7 +196,7 @@
|
|
|
182
196
|
justify-content: center;
|
|
183
197
|
z-index: 1;
|
|
184
198
|
user-select: none;
|
|
185
|
-
font-size:
|
|
199
|
+
font-size: var(--text-base);
|
|
186
200
|
font-style: italic;
|
|
187
201
|
color: var(--hi-color-text-secondary, #666);
|
|
188
202
|
pointer-events: none;
|
|
@@ -199,7 +213,7 @@
|
|
|
199
213
|
pointer-events: none;
|
|
200
214
|
user-select: none;
|
|
201
215
|
font-family: var(--font-mono, vars.$hikari-font-family-mono);
|
|
202
|
-
font-size:
|
|
216
|
+
font-size: var(--text-sm);
|
|
203
217
|
letter-spacing: 0.04em;
|
|
204
218
|
color: var(--hi-color-text-primary, #333);
|
|
205
219
|
}
|
|
@@ -220,7 +234,7 @@
|
|
|
220
234
|
|
|
221
235
|
.hk-pwd-strength {
|
|
222
236
|
position: absolute;
|
|
223
|
-
|
|
237
|
+
inset-inline-end: var(--space-12);
|
|
224
238
|
top: 50%;
|
|
225
239
|
transform: translateY(-50%);
|
|
226
240
|
width: 0.55rem;
|
|
@@ -235,29 +249,25 @@
|
|
|
235
249
|
|
|
236
250
|
.hk-pwd-strength[data-level="weak"] {
|
|
237
251
|
background: var(--hi-color-danger, #f85149);
|
|
238
|
-
box-shadow: 0 0 6px
|
|
252
|
+
box-shadow: 0 0 6px color-mix(in srgb, var(--hi-color-danger, #f85149) 60%, transparent);
|
|
239
253
|
}
|
|
240
254
|
|
|
241
255
|
.hk-pwd-strength[data-level="fair"] {
|
|
242
256
|
background: var(--hi-color-warning, #d29922);
|
|
243
|
-
box-shadow: 0 0 6px
|
|
257
|
+
box-shadow: 0 0 6px color-mix(in srgb, var(--hi-color-warning, #d29922) 60%, transparent);
|
|
244
258
|
}
|
|
245
259
|
|
|
246
260
|
.hk-pwd-strength[data-level="strong"] {
|
|
247
261
|
background: var(--hi-color-success, #3fb950);
|
|
248
|
-
box-shadow: 0 0 6px
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
.hk-pwd-hints {
|
|
252
|
-
min-height: 0;
|
|
262
|
+
box-shadow: 0 0 6px color-mix(in srgb, var(--hi-color-success, #3fb950) 60%, transparent);
|
|
253
263
|
}
|
|
254
264
|
|
|
255
265
|
.hk-pwd-hint {
|
|
256
266
|
display: inline-flex;
|
|
257
267
|
align-items: center;
|
|
258
|
-
gap:
|
|
259
|
-
margin-top:
|
|
260
|
-
font-size:
|
|
268
|
+
gap: var(--space-4);
|
|
269
|
+
margin-top: var(--space-4);
|
|
270
|
+
font-size: var(--text-xs);
|
|
261
271
|
}
|
|
262
272
|
|
|
263
273
|
.hk-pwd-hint[data-variant="caps"] {
|
|
@@ -268,25 +278,15 @@
|
|
|
268
278
|
color: var(--hi-color-danger, #f85149);
|
|
269
279
|
}
|
|
270
280
|
|
|
271
|
-
.hk-pwd-hint-enter-active,
|
|
272
|
-
.hk-pwd-hint-leave-active {
|
|
273
|
-
transition: opacity 0.3s ease;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
.hk-pwd-hint-enter-from,
|
|
277
|
-
.hk-pwd-hint-leave-to {
|
|
278
|
-
opacity: 0;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
281
|
.hk-pwd-error {
|
|
282
|
-
margin-top:
|
|
283
|
-
font-size:
|
|
282
|
+
margin-top: var(--space-4);
|
|
283
|
+
font-size: var(--text-xs);
|
|
284
284
|
color: var(--hi-color-danger, #f85149);
|
|
285
285
|
}
|
|
286
286
|
|
|
287
287
|
.hk-pwd-hint-text {
|
|
288
|
-
margin-top:
|
|
289
|
-
font-size:
|
|
288
|
+
margin-top: var(--space-4);
|
|
289
|
+
font-size: var(--text-xs);
|
|
290
290
|
color: var(--hi-color-text-secondary, #666);
|
|
291
291
|
}
|
|
292
292
|
|
|
@@ -20,6 +20,22 @@
|
|
|
20
20
|
transform: translateY(-8px);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
/* Reduced motion: keep the opacity cross-fade, drop the translateY
|
|
24
|
+
* slide. The global animation switch (`html[data-css-animations="0"]`)
|
|
25
|
+
* disables these transitions too when the host wired it; the media
|
|
26
|
+
* block covers hosts that never did. */
|
|
27
|
+
@media (prefers-reduced-motion: reduce) {
|
|
28
|
+
.hk-phase-enter-active,
|
|
29
|
+
.hk-phase-leave-active {
|
|
30
|
+
transition: opacity var(--hi-duration-fast, 0.15s) ease;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.hk-phase-enter-from,
|
|
34
|
+
.hk-phase-leave-to {
|
|
35
|
+
transform: none;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
23
39
|
.hk-phase-content {
|
|
24
40
|
width: 100%;
|
|
25
41
|
}
|
|
@@ -9,13 +9,11 @@
|
|
|
9
9
|
* handling live there). A button so it is focusable and AT-reachable;
|
|
10
10
|
* mousedown is suppressed in the shared picker so clicking it never
|
|
11
11
|
* steals focus from the number field. */
|
|
12
|
-
.hk-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
12
|
+
/* Width cap comes from the shared .hk-affix-chip base (max-width: 11rem);
|
|
13
|
+
* this class stays a tsx/test hook for hosts to layer overrides on. */
|
|
16
14
|
.hk-phone-chip-dial {
|
|
17
15
|
font-weight: 600;
|
|
18
|
-
font-size: var(--text-sm,
|
|
16
|
+
font-size: var(--text-sm, 0.8125rem);
|
|
19
17
|
white-space: nowrap;
|
|
20
18
|
font-variant-numeric: tabular-nums;
|
|
21
19
|
}
|
|
@@ -24,3 +22,10 @@
|
|
|
24
22
|
flex: none;
|
|
25
23
|
color: rgb(var(--color-muted));
|
|
26
24
|
}
|
|
25
|
+
|
|
26
|
+
/* Open disclosure state (aria-expanded sits on the chip button): flip the
|
|
27
|
+
* caret like the shared default chip does (HkAffixPicker.scss). Instant
|
|
28
|
+
* swap — no transition, so no reduced-motion entry is needed. */
|
|
29
|
+
.hk-phone-chip[aria-expanded="true"] .hk-phone-chip-caret {
|
|
30
|
+
transform: rotate(180deg);
|
|
31
|
+
}
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
.hk-dp-stage,
|
|
45
45
|
.hk-dtp-stage {
|
|
46
46
|
position: relative;
|
|
47
|
-
height: calc(var(--hk-picker-header) + var(--hk-picker-wd) + 6 * var(--hk-picker-cell) +
|
|
47
|
+
height: calc(var(--hk-picker-header) + var(--hk-picker-wd) + 6 * var(--hk-picker-cell) +
|
|
48
|
+
5 * var(--space-2, 2px));
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
.hk-dp-pane,
|
|
@@ -72,22 +73,48 @@
|
|
|
72
73
|
|
|
73
74
|
.hk-dp-stage[data-dir="fwd"] > .hk-picker-pane-enter-active,
|
|
74
75
|
.hk-dtp-stage[data-dir="fwd"] > .hk-picker-pane-enter-active {
|
|
75
|
-
animation: hk-picker-pane-fwd-in var(--hi-duration-normal, 0.
|
|
76
|
+
animation: hk-picker-pane-fwd-in var(--hi-duration-normal, 0.3s) cubic-bezier(0.16, 1, 0.3, 1);
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
.hk-dp-stage[data-dir="fwd"] > .hk-picker-pane-leave-active,
|
|
79
80
|
.hk-dtp-stage[data-dir="fwd"] > .hk-picker-pane-leave-active {
|
|
80
|
-
animation: hk-picker-pane-fwd-out var(--hi-duration-normal, 0.
|
|
81
|
+
animation: hk-picker-pane-fwd-out var(--hi-duration-normal, 0.3s) cubic-bezier(0.16, 1, 0.3, 1);
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
.hk-dp-stage[data-dir="back"] > .hk-picker-pane-enter-active,
|
|
84
85
|
.hk-dtp-stage[data-dir="back"] > .hk-picker-pane-enter-active {
|
|
85
|
-
animation: hk-picker-pane-back-in var(--hi-duration-normal, 0.
|
|
86
|
+
animation: hk-picker-pane-back-in var(--hi-duration-normal, 0.3s) cubic-bezier(0.16, 1, 0.3, 1);
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
.hk-dp-stage[data-dir="back"] > .hk-picker-pane-leave-active,
|
|
89
90
|
.hk-dtp-stage[data-dir="back"] > .hk-picker-pane-leave-active {
|
|
90
|
-
animation: hk-picker-pane-back-out var(--hi-duration-normal, 0.
|
|
91
|
+
animation: hk-picker-pane-back-out var(--hi-duration-normal, 0.3s) cubic-bezier(0.16, 1, 0.3, 1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* RTL: reading direction flips, so a forward drill flows left→right —
|
|
95
|
+
* swap the fwd/back keyframes (HkListTransition/HkBlockingToast
|
|
96
|
+
* [dir="rtl"] form; same registered keyframes, mirrored direction).
|
|
97
|
+
* Only the name is overridden: duration and easing carry over from the
|
|
98
|
+
* rules above, and the reduced-motion / data-css-animations guards below
|
|
99
|
+
* still win with !important. */
|
|
100
|
+
[dir="rtl"] .hk-dp-stage[data-dir="fwd"] > .hk-picker-pane-enter-active,
|
|
101
|
+
[dir="rtl"] .hk-dtp-stage[data-dir="fwd"] > .hk-picker-pane-enter-active {
|
|
102
|
+
animation-name: hk-picker-pane-back-in;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
[dir="rtl"] .hk-dp-stage[data-dir="fwd"] > .hk-picker-pane-leave-active,
|
|
106
|
+
[dir="rtl"] .hk-dtp-stage[data-dir="fwd"] > .hk-picker-pane-leave-active {
|
|
107
|
+
animation-name: hk-picker-pane-back-out;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
[dir="rtl"] .hk-dp-stage[data-dir="back"] > .hk-picker-pane-enter-active,
|
|
111
|
+
[dir="rtl"] .hk-dtp-stage[data-dir="back"] > .hk-picker-pane-enter-active {
|
|
112
|
+
animation-name: hk-picker-pane-fwd-in;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
[dir="rtl"] .hk-dp-stage[data-dir="back"] > .hk-picker-pane-leave-active,
|
|
116
|
+
[dir="rtl"] .hk-dtp-stage[data-dir="back"] > .hk-picker-pane-leave-active {
|
|
117
|
+
animation-name: hk-picker-pane-fwd-out;
|
|
91
118
|
}
|
|
92
119
|
|
|
93
120
|
/* The leaving pane overlays the fixed stage so the entering pane can take
|
|
@@ -58,7 +58,11 @@
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
&__copy {
|
|
61
|
-
|
|
61
|
+
// Trailing cushion between copies. Kept as a px literal (not a token)
|
|
62
|
+
// on purpose: it must equal COPY_SPACING = 24 in the tsx overflow math
|
|
63
|
+
// at every root font size. Logical axis so the cushion trails the
|
|
64
|
+
// reading direction under RTL hosts.
|
|
65
|
+
padding-inline-end: 24px;
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
// Hidden probe mode (text fits): visibility keeps the element laid out —
|
|
@@ -74,8 +78,9 @@
|
|
|
74
78
|
width: 100%;
|
|
75
79
|
overflow: hidden;
|
|
76
80
|
text-overflow: ellipsis;
|
|
81
|
+
// white-space stays local (ellipsis-trio idiom); text-align: center
|
|
82
|
+
// was dropped — the root already centers and hosts may re-align it.
|
|
77
83
|
white-space: nowrap;
|
|
78
|
-
text-align: center;
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
86
|
|
|
@@ -84,6 +84,33 @@ afterEach(() => {
|
|
|
84
84
|
}
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
+
describe("HkPlaceholderMarquee scale-aware measurement", () => {
|
|
88
|
+
it("converts the copy's drawn width into the host's own units before looping", async () => {
|
|
89
|
+
// The copy is measured where it is DRAWN while the host it is compared
|
|
90
|
+
// with (`clientWidth`) is laid out. Inside a scaled or zoomed root the two
|
|
91
|
+
// differ by the factor the space is drawn at: the raw rect would make the
|
|
92
|
+
// loop overshoot by (k-1) of a copy per cycle and report overflow for
|
|
93
|
+
// copies that fit k times over.
|
|
94
|
+
const { container } = mountMarquee({ text: "a very long placeholder that overflows".repeat(4) });
|
|
95
|
+
const host = container.querySelector(".hk-placeholder-marquee") as HTMLElement;
|
|
96
|
+
const copy = container.querySelector(".hk-placeholder-marquee__copy") as HTMLElement;
|
|
97
|
+
Object.defineProperty(host, "clientWidth", { configurable: true, get: () => 200 });
|
|
98
|
+
// The host is drawn twice the size it is laid out at: 800 drawn px are
|
|
99
|
+
// 400 of its own, while the copy really advances 500 of them.
|
|
100
|
+
Object.defineProperty(host, "getBoundingClientRect", {
|
|
101
|
+
configurable: true,
|
|
102
|
+
value: () => ({ width: 400, left: 0, top: 0, right: 400, bottom: 40, height: 40, x: 0, y: 0 }) as DOMRect,
|
|
103
|
+
});
|
|
104
|
+
Object.defineProperty(host, "offsetWidth", { configurable: true, get: () => 200 });
|
|
105
|
+
vi.spyOn(copy, "getBoundingClientRect").mockReturnValue({ width: 1000 } as DOMRect);
|
|
106
|
+
marqueeExposed(container)?.measure?.();
|
|
107
|
+
await nextTick();
|
|
108
|
+
|
|
109
|
+
const strip = container.querySelector(".hk-placeholder-marquee__strip") as HTMLElement;
|
|
110
|
+
expect(strip.style.getPropertyValue("--hk-marquee-shift"), "1000 drawn = 500 of the host's own").toBe("-500px");
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
87
114
|
describe("HkPlaceholderMarquee", () => {
|
|
88
115
|
it("stays a hidden single-copy probe while the text fits", () => {
|
|
89
116
|
const { container } = mountMarquee({ text: "用户名" });
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineComponent, ref, computed, onMounted, onBeforeUnmount, watch, type PropType } from "vue";
|
|
2
|
+
import { drawnScale } from "../composables/layoutGeometry";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Overflow strategy for a placeholder that does not fit its input.
|
|
@@ -64,12 +65,19 @@ export const HkPlaceholderMarquee = defineComponent({
|
|
|
64
65
|
// copy spacing as trailing padding). Reading the first copy element —
|
|
65
66
|
// instead of stripWidth / 3 — stays correct in the fitting case,
|
|
66
67
|
// where the strip holds a single copy, and through overflow flips,
|
|
67
|
-
// where the copy count changes under the same strip. The
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
|
|
68
|
+
// where the copy count changes under the same strip. The width is read
|
|
69
|
+
// where the copy is DRAWN and converted into the host's own units,
|
|
70
|
+
// because that is the space the CSS loop shift and `clientWidth` live
|
|
71
|
+
// in: inside a scaled or zoomed root the raw rect is k times the
|
|
72
|
+
// advance, so the loop would overshoot by (k-1) per cycle and the
|
|
73
|
+
// overflow test would fire on copies that fit k times over. The
|
|
74
|
+
// conversion keeps the fractional width that makes the shift
|
|
75
|
+
// bit-exact — an integer-rounded width would show a ≤0.5px seam at
|
|
76
|
+
// every wrap (the copy rides the animated strip, so the width itself
|
|
77
|
+
// is never affected by the strip's transform).
|
|
78
|
+
const space = drawnScale(host);
|
|
79
|
+
const factor = space.x > 0 ? space.x : 1;
|
|
80
|
+
const copyWidth = copy.getBoundingClientRect().width / factor;
|
|
73
81
|
loopWidth.value = copyWidth;
|
|
74
82
|
overflowing.value = copyWidth - COPY_SPACING > host.clientWidth;
|
|
75
83
|
emit("overflowChange", overflowing.value);
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
border: 1px solid rgb(var(--color-border) / 20%);
|
|
69
69
|
border-radius: var(--radius-sm);
|
|
70
70
|
box-shadow: var(--shadow-dropdown);
|
|
71
|
-
padding: var(--space-4,
|
|
71
|
+
padding: var(--space-4, 0.25rem);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
/* Locale picker menu items — unified menu-item spec (./_menu-item.scss). */
|
|
@@ -76,10 +76,6 @@
|
|
|
76
76
|
@include mi.item;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
.hk-popup-menu-item[data-active]:hover {
|
|
80
|
-
background: var(--c-primary-dim, rgb(var(--color-primary) / 10%));
|
|
81
|
-
}
|
|
82
|
-
|
|
83
79
|
.hk-locale-submenu {
|
|
84
80
|
min-width: 140px;
|
|
85
81
|
padding: var(--space-6);
|
|
@@ -125,6 +121,9 @@
|
|
|
125
121
|
border-left: 0;
|
|
126
122
|
border-right: 0;
|
|
127
123
|
border-bottom: 0;
|
|
124
|
+
// The panel is a programmatic focus surface (tabindex="-1", focused on
|
|
125
|
+
// sheet open) — suppress the UA focus ring like .hk-modal-content.
|
|
126
|
+
outline: none;
|
|
128
127
|
max-height: min(
|
|
129
128
|
72vh,
|
|
130
129
|
calc(
|
|
@@ -203,8 +202,11 @@
|
|
|
203
202
|
display: flex;
|
|
204
203
|
align-items: center;
|
|
205
204
|
gap: var(--space-8, 0.5rem);
|
|
206
|
-
|
|
207
|
-
|
|
205
|
+
// Logical longhand (was physical `0 x y title-inset`): the title inset is
|
|
206
|
+
// the inline START edge so RTL mirrors it with the mirrored title/close.
|
|
207
|
+
padding-block: 0 var(--space-8, 0.5rem);
|
|
208
|
+
padding-inline: var(--hk-sheet-title-inset, var(--space-12, 0.75rem))
|
|
209
|
+
var(--space-8, 0.5rem);
|
|
208
210
|
}
|
|
209
211
|
|
|
210
212
|
.hk-popover-sheet-title {
|
|
@@ -220,7 +222,7 @@
|
|
|
220
222
|
font-size: var(--text-base, 0.875rem);
|
|
221
223
|
font-weight: 600;
|
|
222
224
|
letter-spacing: 0.02em;
|
|
223
|
-
color: rgb(var(--color-muted,
|
|
225
|
+
color: rgb(var(--color-muted, 108 108 108));
|
|
224
226
|
user-select: none;
|
|
225
227
|
-webkit-user-select: none;
|
|
226
228
|
}
|
|
@@ -228,8 +230,9 @@
|
|
|
228
230
|
.hk-popover-sheet-close {
|
|
229
231
|
// Legacy placement hook — the chrome lives on the shared .hk-icon-button
|
|
230
232
|
// / .hk-window-close rules (window-close.scss) since the unified-close
|
|
231
|
-
// wave. Only the
|
|
232
|
-
|
|
233
|
+
// wave. Only the trailing-edge pinning stays here (logical, so the close
|
|
234
|
+
// mirrors to the left in RTL like HkInput/HkTagInput's auto inline start).
|
|
235
|
+
margin-inline-start: auto;
|
|
233
236
|
}
|
|
234
237
|
|
|
235
238
|
.hk-popover-sheet-enter-active {
|
|
@@ -257,6 +260,11 @@
|
|
|
257
260
|
@include sf.scrim-fade("hk-popover-scrim");
|
|
258
261
|
|
|
259
262
|
@media (prefers-reduced-motion: reduce) {
|
|
263
|
+
// Pop transitions included: the anchored panel's translateY+scale pop is
|
|
264
|
+
// the same non-trivial motion the sheet slide already silences here
|
|
265
|
+
// (house pattern: HkExpansionPanel.scss / HkAffixPicker.scss guards).
|
|
266
|
+
.hk-popover-enter-active,
|
|
267
|
+
.hk-popover-leave-active,
|
|
260
268
|
.hk-popover-sheet-enter-active,
|
|
261
269
|
.hk-popover-sheet-leave-active {
|
|
262
270
|
transition: none;
|