@passui/react 0.1.45 → 0.1.46

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 (140) hide show
  1. package/README.md +57 -46
  2. package/dist/types/src/components/accordion/accordion.d.ts +1 -1
  3. package/dist/types/src/components/breadcrumb/breadcrumb.d.ts +1 -1
  4. package/dist/types/src/components/inline-disclosure/inline-disclosure.d.ts +1 -1
  5. package/dist/types/src/components/popover/anchored-surface.d.ts +5 -1
  6. package/dist/types/src/components/popover/index.d.ts +41 -0
  7. package/dist/types/src/components/popover/popover-content.d.ts +32 -0
  8. package/dist/types/src/components/popover/popover-root.d.ts +22 -0
  9. package/dist/types/src/components/popover/popover-trigger.d.ts +23 -0
  10. package/dist/types/src/components/stepper/rolling-digit.d.ts +1 -1
  11. package/dist/types/src/components/table/table.d.ts +1 -1
  12. package/dist/types/src/components/view-controller/view-controller.d.ts +2 -2
  13. package/dist/types/src/index.d.ts +1 -1
  14. package/dist/types/src/machines/popover.machine.d.ts +30 -0
  15. package/package.json +307 -307
  16. package/src/appearance/index.ts +2 -2
  17. package/src/appearance/platform.tsx +76 -60
  18. package/src/appearance/theme.tsx +409 -377
  19. package/src/components/accordion/accordion.tsx +58 -49
  20. package/src/components/ambient/ambient.tsx +25 -25
  21. package/src/components/ambient/index.ts +1 -1
  22. package/src/components/aspect-ratio/aspect-ratio.tsx +21 -16
  23. package/src/components/breadcrumb/breadcrumb.tsx +63 -57
  24. package/src/components/button/button-styles.ts +39 -32
  25. package/src/components/button/button.tsx +91 -84
  26. package/src/components/button/icon-button.tsx +27 -25
  27. package/src/components/button/pending-spinner.tsx +8 -8
  28. package/src/components/button/use-pending-indicator.ts +11 -11
  29. package/src/components/chip/chip.tsx +35 -30
  30. package/src/components/code-block/code-block.tsx +40 -39
  31. package/src/components/combo-box/combo-box.tsx +5 -5
  32. package/src/components/command/command.tsx +124 -94
  33. package/src/components/compact-date-picker/calendar-month.ts +75 -53
  34. package/src/components/compact-date-picker/compact-date-picker.tsx +308 -289
  35. package/src/components/compact-time-picker/compact-time-picker.tsx +288 -281
  36. package/src/components/compact-time-picker/time-value.ts +32 -29
  37. package/src/components/content-unavailable-view/content-unavailable-view.tsx +64 -48
  38. package/src/components/content-view/content-view.tsx +168 -159
  39. package/src/components/content-view/index.ts +1 -1
  40. package/src/components/context-menu/conceal-menu-source.ts +25 -25
  41. package/src/components/context-menu/context-menu-host.tsx +439 -402
  42. package/src/components/context-menu/context-menu-store.ts +125 -123
  43. package/src/components/context-menu/menu-navigation.ts +25 -18
  44. package/src/components/context-menu/menu-position.ts +33 -29
  45. package/src/components/context-menu/menu-reveal.ts +32 -32
  46. package/src/components/context-menu/use-context-menu.ts +63 -56
  47. package/src/components/conversation/conversation.tsx +265 -263
  48. package/src/components/conversation/index.ts +1 -1
  49. package/src/components/date-picker/date-picker.tsx +95 -94
  50. package/src/components/date-picker/date-value.ts +20 -10
  51. package/src/components/dialog/dialog-host.tsx +105 -103
  52. package/src/components/dialog/dialog-store.ts +37 -36
  53. package/src/components/dialog/dialog.tsx +192 -179
  54. package/src/components/dialog/index.ts +1 -1
  55. package/src/components/disclosure-group/disclosure-group.tsx +93 -86
  56. package/src/components/divider/divider.tsx +24 -22
  57. package/src/components/inline-disclosure/inline-disclosure.tsx +40 -36
  58. package/src/components/keyboard-shortcut/keyboard-shortcut.tsx +23 -19
  59. package/src/components/labeled-content/labeled-content.tsx +68 -68
  60. package/src/components/locale-switcher/index.ts +1 -1
  61. package/src/components/locale-switcher/locale-switcher.tsx +279 -251
  62. package/src/components/menu/menu.tsx +75 -58
  63. package/src/components/morph/index.ts +2 -2
  64. package/src/components/morph/morph.tsx +227 -201
  65. package/src/components/morph/use-morph-disclosure.ts +19 -19
  66. package/src/components/one-time-code/one-time-code.tsx +216 -200
  67. package/src/components/picker/picker-trigger.ts +16 -13
  68. package/src/components/picker/picker.tsx +371 -345
  69. package/src/components/popover/anchored-surface.tsx +253 -229
  70. package/src/components/popover/index.ts +50 -0
  71. package/src/components/popover/popover-content.tsx +334 -0
  72. package/src/components/popover/popover-fit.ts +58 -53
  73. package/src/components/popover/popover-root.tsx +97 -0
  74. package/src/components/popover/popover-trigger.tsx +71 -0
  75. package/src/components/profile-image/profile-image.tsx +80 -64
  76. package/src/components/progress-view/progress-view.tsx +61 -59
  77. package/src/components/progress-view/use-liquid-progress.ts +38 -38
  78. package/src/components/radio-group/radio-group.tsx +71 -68
  79. package/src/components/search-field/expanding-search-field.tsx +191 -177
  80. package/src/components/search-field/search-field.tsx +59 -50
  81. package/src/components/search-list/search-list.tsx +246 -236
  82. package/src/components/section/section.tsx +58 -58
  83. package/src/components/secure-field/secure-field.tsx +3 -3
  84. package/src/components/segmented-control/segmented-control.tsx +136 -136
  85. package/src/components/sheet/modal-environment.ts +71 -64
  86. package/src/components/sheet/sheet-portal.tsx +58 -53
  87. package/src/components/sheet/sheet.tsx +146 -141
  88. package/src/components/sheet/use-sheet-focus.ts +97 -82
  89. package/src/components/sidebar/sidebar.tsx +78 -78
  90. package/src/components/skeleton/skeleton.tsx +30 -21
  91. package/src/components/slider/slider.tsx +113 -104
  92. package/src/components/slosh-slider/liquid-step.ts +32 -31
  93. package/src/components/slosh-slider/slosh-slider.tsx +265 -228
  94. package/src/components/stat-tile/index.ts +1 -1
  95. package/src/components/stat-tile/stat-tile.tsx +79 -68
  96. package/src/components/status-indicator/status-indicator.tsx +40 -37
  97. package/src/components/stepper/rolling-digit.tsx +82 -68
  98. package/src/components/stepper/stepper.tsx +122 -113
  99. package/src/components/swatch-picker/swatch-picker.tsx +120 -120
  100. package/src/components/tab-bar/tab-bar.tsx +149 -148
  101. package/src/components/tab-view/tab-view.tsx +140 -137
  102. package/src/components/table/table.tsx +117 -98
  103. package/src/components/text-editor/text-editor.tsx +34 -29
  104. package/src/components/text-field/text-field.tsx +182 -180
  105. package/src/components/toast/toast-store.ts +127 -115
  106. package/src/components/toast/toaster.tsx +361 -347
  107. package/src/components/toggle/toggle.tsx +297 -282
  108. package/src/components/tooltip/tooltip-host.tsx +157 -150
  109. package/src/components/view-controller/index.ts +1 -1
  110. package/src/components/view-controller/view-controller.tsx +64 -53
  111. package/src/components/wake-slider/wake-slider.tsx +220 -205
  112. package/src/hooks/scroll/minimize-decision.ts +11 -7
  113. package/src/hooks/use-anchored-disclosure.ts +19 -19
  114. package/src/hooks/use-anchored-placement.ts +29 -25
  115. package/src/hooks/use-dismiss.ts +33 -29
  116. package/src/hooks/use-floating-dismiss.ts +24 -22
  117. package/src/hooks/use-media-query.ts +67 -60
  118. package/src/hooks/use-minimize-on-scroll.ts +69 -60
  119. package/src/hooks/use-visual-viewport.ts +63 -63
  120. package/src/hooks/viewport/types.ts +16 -16
  121. package/src/hooks/viewport/viewport-metrics.ts +16 -10
  122. package/src/icons/icons.tsx +440 -328
  123. package/src/index.ts +91 -91
  124. package/src/lib/anchored-placement.ts +70 -65
  125. package/src/lib/class-names.ts +14 -13
  126. package/src/lib/clipboard.ts +8 -7
  127. package/src/lib/date.ts +61 -60
  128. package/src/lib/floating-layers.ts +39 -24
  129. package/src/lib/haptics.ts +10 -10
  130. package/src/lib/language.ts +9 -9
  131. package/src/lib/range-value.ts +27 -21
  132. package/src/lib/screen-edges.ts +33 -30
  133. package/src/lib/shapes.ts +38 -34
  134. package/src/machines/popover.machine.ts +51 -0
  135. package/src/motion/transitions.ts +46 -43
  136. package/src/styles/code-block.css +69 -43
  137. package/src/styles/motion-controls.css +393 -191
  138. package/src/tokens.ts +1 -1
  139. package/dist/types/src/components/popover/popover.d.ts +0 -21
  140. package/src/components/popover/popover.tsx +0 -334
@@ -3,202 +3,404 @@
3
3
  background; pane-edge to separator; font-ui to font-sans. Color mixes
4
4
  replace rgba RGB triples, so no Bencho variables or new globals leak. */
5
5
  @layer components {
6
- .passui-search-pill { transition: scale 90ms ease; }
7
- .passui-search-pill:active { scale: 0.98; }
8
- /* The outline stays whole; its legend opens a real gap under the label.
6
+ .passui-search-pill {
7
+ transition: scale 90ms ease;
8
+ }
9
+ .passui-search-pill:active {
10
+ scale: 0.98;
11
+ }
12
+ /* The outline stays whole; its legend opens a real gap under the label.
9
13
  No painted background patch needs to match the field's surroundings. */
10
- .passui-field-outline {
11
- position: absolute;
12
- inset: calc(var(--text-footnote) / -2) 0 0;
13
- min-width: 0;
14
- margin: 0;
15
- padding: 0 0.5rem;
16
- border: 1px solid var(--color-separator);
17
- border-radius: inherit;
18
- pointer-events: none;
19
- transition: border-color 200ms ease;
20
- }
21
- .passui-field-outline legend {
22
- max-width: 0;
23
- overflow: hidden;
24
- padding: 0;
25
- font-size: var(--text-footnote);
26
- line-height: 1;
27
- height: 1em;
28
- white-space: nowrap;
29
- visibility: hidden;
30
- transition: max-width 320ms ease, padding 320ms ease;
31
- }
32
- .passui-floating-label {
33
- position: absolute;
34
- inset-inline-start: 0.75rem;
35
- top: 50%;
36
- z-index: 1;
37
- max-width: calc(100% - 1.5rem);
38
- overflow: hidden;
39
- text-overflow: ellipsis;
40
- white-space: nowrap;
41
- color: var(--color-label-secondary);
42
- font-size: var(--text-body);
43
- line-height: 1;
44
- transform: translateY(-50%);
45
- transform-origin: left center;
46
- transition: top 320ms ease, transform 320ms ease, color 200ms ease;
47
- pointer-events: none;
48
- }
49
- .passui-floating-label:dir(rtl) { transform-origin: right center; }
50
- .passui-floating-label-with-icon { inset-inline-start: 2.5rem; }
51
- .passui-floating-field input::placeholder { opacity: 0; }
52
- .passui-floating-field:focus-within input::placeholder { opacity: 1; }
53
- .passui-floating-field:focus-within .passui-field-outline { border-color: var(--color-label); }
54
- .passui-floating-field:has(input[aria-invalid="true"]) .passui-field-outline { border-color: var(--color-danger); }
55
- .passui-floating-field:is(:focus-within, :has(input:not(:placeholder-shown))) .passui-floating-label {
56
- top: 0;
57
- inset-inline-start: 0.75rem;
58
- transform: translateY(-50%) scale(0.78);
59
- color: var(--color-label);
60
- }
61
- .passui-floating-field:is(:focus-within, :has(input:not(:placeholder-shown))) legend {
62
- max-width: 100%;
63
- padding-inline: 0.25rem;
64
- }
65
- .passui-one-time-code { width: 100%; max-width: calc(var(--otp-length) * 2.5rem + (var(--otp-length) - 1) * 0.5rem); }
66
- .passui-otp-row { position: relative; height: 3rem; }
67
- .passui-otp-materials, .passui-otp-digits { display: flex; position: absolute; inset: 0; gap: 0.5rem; pointer-events: none; }
68
- .passui-otp-cell, .passui-otp-digit { flex: 1; min-width: 0; border-radius: var(--radius-xl); }
69
- .passui-otp-cell {
70
- background: var(--color-fill);
71
- transition: transform 560ms cubic-bezier(0.22, 1, 0.36, 1), background-color 200ms;
72
- }
73
- .passui-otp-digit { display: grid; place-items: center; font-size: var(--text-title3); color: var(--color-label); font-variant-numeric: tabular-nums; }
74
- .passui-otp-input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: text; }
75
- .passui-one-time-code:focus-within .passui-otp-digit[data-active] { box-shadow: inset 0 0 0 2px var(--color-accent-text); }
76
- .passui-otp-glyph { animation: passui-otp-in 200ms ease-out both; }
77
- @keyframes passui-otp-in { from { transform: translateY(45%) scale(0.86); opacity: 0; filter: blur(3px); } }
78
- .passui-otp-capsule { position: absolute; inset-block: 0; left: 50%; width: 60%; border-radius: var(--radius-full); background: var(--color-accent); transform: translateX(-50%) scaleX(0); opacity: 0; transition: transform 560ms cubic-bezier(0.22, 1, 0.36, 1), opacity 160ms; }
79
- .passui-one-time-code:is([data-status="verifying"], [data-status="success"]) .passui-otp-cell { transform: translateX(calc((var(--otp-middle) - var(--otp-index)) * (100% + 0.5rem))); background: var(--color-accent); }
80
- .passui-one-time-code:is([data-status="verifying"], [data-status="success"]) .passui-otp-capsule { opacity: 1; transform: translateX(-50%) scaleX(1); }
81
- .passui-one-time-code:is([data-status="verifying"], [data-status="success"]) .passui-otp-digits { opacity: 0; }
82
- .passui-otp-check { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); color: var(--color-on-accent); opacity: 0; pointer-events: none; }
83
- .passui-one-time-code[data-size="sm"] .passui-otp-row { height: 2.5rem; }
84
- .passui-one-time-code[data-size="sm"] .passui-otp-digit { font-size: var(--text-title); }
85
- .passui-one-time-code[data-size="lg"] .passui-otp-row { height: 3.5rem; }
86
- .passui-one-time-code[data-size="lg"] .passui-otp-digit { font-size: var(--text-title2); }
87
- .passui-one-time-code[data-status="success"] .passui-otp-check { opacity: 1; transition: opacity 160ms 240ms; }
88
- /* A wrong code shivers, then drains right to left. Selecting the single
14
+ .passui-field-outline {
15
+ position: absolute;
16
+ inset: calc(var(--text-footnote) / -2) 0 0;
17
+ min-width: 0;
18
+ margin: 0;
19
+ padding: 0 0.5rem;
20
+ border: 1px solid var(--color-separator);
21
+ border-radius: inherit;
22
+ pointer-events: none;
23
+ transition: border-color 200ms ease;
24
+ }
25
+ .passui-field-outline legend {
26
+ max-width: 0;
27
+ overflow: hidden;
28
+ padding: 0;
29
+ font-size: var(--text-footnote);
30
+ line-height: 1;
31
+ height: 1em;
32
+ white-space: nowrap;
33
+ visibility: hidden;
34
+ transition:
35
+ max-width 320ms ease,
36
+ padding 320ms ease;
37
+ }
38
+ .passui-floating-label {
39
+ position: absolute;
40
+ inset-inline-start: 0.75rem;
41
+ top: 50%;
42
+ z-index: 1;
43
+ max-width: calc(100% - 1.5rem);
44
+ overflow: hidden;
45
+ text-overflow: ellipsis;
46
+ white-space: nowrap;
47
+ color: var(--color-label-secondary);
48
+ font-size: var(--text-body);
49
+ line-height: 1;
50
+ transform: translateY(-50%);
51
+ transform-origin: left center;
52
+ transition:
53
+ top 320ms ease,
54
+ transform 320ms ease,
55
+ color 200ms ease;
56
+ pointer-events: none;
57
+ }
58
+ .passui-floating-label:dir(rtl) {
59
+ transform-origin: right center;
60
+ }
61
+ .passui-floating-label-with-icon {
62
+ inset-inline-start: 2.5rem;
63
+ }
64
+ .passui-floating-field input::placeholder {
65
+ opacity: 0;
66
+ }
67
+ .passui-floating-field:focus-within input::placeholder {
68
+ opacity: 1;
69
+ }
70
+ .passui-floating-field:focus-within .passui-field-outline {
71
+ border-color: var(--color-label);
72
+ }
73
+ .passui-floating-field:has(input[aria-invalid="true"]) .passui-field-outline {
74
+ border-color: var(--color-danger);
75
+ }
76
+ .passui-floating-field:is(:focus-within, :has(input:not(:placeholder-shown)))
77
+ .passui-floating-label {
78
+ top: 0;
79
+ inset-inline-start: 0.75rem;
80
+ transform: translateY(-50%) scale(0.78);
81
+ color: var(--color-label);
82
+ }
83
+ .passui-floating-field:is(:focus-within, :has(input:not(:placeholder-shown)))
84
+ legend {
85
+ max-width: 100%;
86
+ padding-inline: 0.25rem;
87
+ }
88
+ .passui-one-time-code {
89
+ width: 100%;
90
+ max-width: calc(
91
+ var(--otp-length) *
92
+ 2.5rem +
93
+ (var(--otp-length) - 1) *
94
+ 0.5rem
95
+ );
96
+ }
97
+ .passui-otp-row {
98
+ position: relative;
99
+ height: 3rem;
100
+ }
101
+ .passui-otp-materials,
102
+ .passui-otp-digits {
103
+ display: flex;
104
+ position: absolute;
105
+ inset: 0;
106
+ gap: 0.5rem;
107
+ pointer-events: none;
108
+ }
109
+ .passui-otp-cell,
110
+ .passui-otp-digit {
111
+ flex: 1;
112
+ min-width: 0;
113
+ border-radius: var(--radius-xl);
114
+ }
115
+ .passui-otp-cell {
116
+ background: var(--color-fill);
117
+ transition:
118
+ transform 560ms cubic-bezier(0.22, 1, 0.36, 1),
119
+ background-color 200ms;
120
+ }
121
+ .passui-otp-digit {
122
+ display: grid;
123
+ place-items: center;
124
+ font-size: var(--text-title3);
125
+ color: var(--color-label);
126
+ font-variant-numeric: tabular-nums;
127
+ }
128
+ .passui-otp-input {
129
+ position: absolute;
130
+ inset: 0;
131
+ width: 100%;
132
+ height: 100%;
133
+ opacity: 0;
134
+ cursor: text;
135
+ }
136
+ .passui-one-time-code:focus-within .passui-otp-digit[data-active] {
137
+ box-shadow: inset 0 0 0 2px var(--color-accent-text);
138
+ }
139
+ .passui-otp-glyph {
140
+ animation: passui-otp-in 200ms ease-out both;
141
+ }
142
+ @keyframes passui-otp-in {
143
+ from {
144
+ transform: translateY(45%) scale(0.86);
145
+ opacity: 0;
146
+ filter: blur(3px);
147
+ }
148
+ }
149
+ .passui-otp-capsule {
150
+ position: absolute;
151
+ inset-block: 0;
152
+ left: 50%;
153
+ width: 60%;
154
+ border-radius: var(--radius-full);
155
+ background: var(--color-accent);
156
+ transform: translateX(-50%) scaleX(0);
157
+ opacity: 0;
158
+ transition:
159
+ transform 560ms cubic-bezier(0.22, 1, 0.36, 1),
160
+ opacity 160ms;
161
+ }
162
+ .passui-one-time-code:is([data-status="verifying"], [data-status="success"])
163
+ .passui-otp-cell {
164
+ transform: translateX(
165
+ calc((var(--otp-middle) - var(--otp-index)) * (100% + 0.5rem))
166
+ );
167
+ background: var(--color-accent);
168
+ }
169
+ .passui-one-time-code:is([data-status="verifying"], [data-status="success"])
170
+ .passui-otp-capsule {
171
+ opacity: 1;
172
+ transform: translateX(-50%) scaleX(1);
173
+ }
174
+ .passui-one-time-code:is([data-status="verifying"], [data-status="success"])
175
+ .passui-otp-digits {
176
+ opacity: 0;
177
+ }
178
+ .passui-otp-check {
179
+ position: absolute;
180
+ left: 50%;
181
+ top: 50%;
182
+ transform: translate(-50%, -50%);
183
+ color: var(--color-on-accent);
184
+ opacity: 0;
185
+ pointer-events: none;
186
+ }
187
+ .passui-one-time-code[data-size="sm"] .passui-otp-row {
188
+ height: 2.5rem;
189
+ }
190
+ .passui-one-time-code[data-size="sm"] .passui-otp-digit {
191
+ font-size: var(--text-title);
192
+ }
193
+ .passui-one-time-code[data-size="lg"] .passui-otp-row {
194
+ height: 3.5rem;
195
+ }
196
+ .passui-one-time-code[data-size="lg"] .passui-otp-digit {
197
+ font-size: var(--text-title2);
198
+ }
199
+ .passui-one-time-code[data-status="success"] .passui-otp-check {
200
+ opacity: 1;
201
+ transition: opacity 160ms 240ms;
202
+ }
203
+ /* A wrong code shivers, then drains right to left. Selecting the single
89
204
  input afterward lets the next keystroke replace it without a trap. */
90
- .passui-one-time-code[data-status="error"] .passui-otp-digit { animation: passui-otp-shiver 380ms ease-out; }
91
- .passui-one-time-code[data-status="error"] .passui-otp-glyph { animation: passui-otp-drain 220ms calc(380ms + (var(--otp-length) - var(--otp-index)) * 35ms) both; }
92
- @keyframes passui-otp-shiver { 20% { transform: translateX(4px); } 40% { transform: translateX(-3px); } 60% { transform: translateX(2px); } 80% { transform: translateX(-1px); } }
93
- @keyframes passui-otp-drain { to { transform: translateY(65%); opacity: 0; filter: blur(3px); } }
94
- .passui-progress-fill {
95
- clip-path: polygon(0 0, calc(100% + var(--progress-lean, 0px)) 0,
96
- calc(100% - var(--progress-lean, 0px)) 100%, 0 100%);
97
- }
98
- .passui-slosh-slider {
99
- width: 100%;
100
- min-width: 0;
101
- font-family: var(--font-sans);
102
- color: var(--color-label);
103
- }
205
+ .passui-one-time-code[data-status="error"] .passui-otp-digit {
206
+ animation: passui-otp-shiver 380ms ease-out;
207
+ }
208
+ .passui-one-time-code[data-status="error"] .passui-otp-glyph {
209
+ animation: passui-otp-drain 220ms
210
+ calc(380ms + (var(--otp-length) - var(--otp-index)) * 35ms) both;
211
+ }
212
+ @keyframes passui-otp-shiver {
213
+ 20% {
214
+ transform: translateX(4px);
215
+ }
216
+ 40% {
217
+ transform: translateX(-3px);
218
+ }
219
+ 60% {
220
+ transform: translateX(2px);
221
+ }
222
+ 80% {
223
+ transform: translateX(-1px);
224
+ }
225
+ }
226
+ @keyframes passui-otp-drain {
227
+ to {
228
+ transform: translateY(65%);
229
+ opacity: 0;
230
+ filter: blur(3px);
231
+ }
232
+ }
233
+ .passui-progress-fill {
234
+ clip-path: polygon(
235
+ 0 0,
236
+ calc(100% + var(--progress-lean, 0px)) 0,
237
+ calc(100% - var(--progress-lean, 0px)) 100%,
238
+ 0 100%
239
+ );
240
+ }
241
+ .passui-slosh-slider {
242
+ width: 100%;
243
+ min-width: 0;
244
+ font-family: var(--font-sans);
245
+ color: var(--color-label);
246
+ }
104
247
 
105
- /* No transitions: every geometry value is written by the loop, and
248
+ /* No transitions: every geometry value is written by the loop, and
106
249
  a transition on top of a spring is two opinions about one number. */
107
- .passui-slosh-track {
108
- position: relative;
109
- height: 2.5rem;
110
- border-radius: var(--slosh-radius, var(--radius-full));
111
- /* Opaque, mixed from the surface's own pair. A translucent wash
250
+ .passui-slosh-track {
251
+ position: relative;
252
+ height: 2.5rem;
253
+ border-radius: var(--slosh-radius, var(--radius-full));
254
+ /* Opaque, mixed from the surface's own pair. A translucent wash
112
255
  changes with the stage behind it and can disappear in dark mode. */
113
- background: color-mix(in srgb, var(--color-label) 11%, var(--color-elevated));
114
- overflow: hidden;
115
- cursor: ew-resize;
116
- touch-action: pan-y;
117
- }
118
- .passui-slosh-track[aria-disabled="true"],
119
- .passui-wake-track[aria-disabled="true"] { cursor: not-allowed; }
120
- .passui-slosh-track:focus-visible,
121
- .passui-wake-track:focus-visible {
122
- outline: 2px solid var(--color-accent-text);
123
- outline-offset: 4px;
124
- }
125
- .passui-slosh-fill {
126
- position: absolute;
127
- inset-block: 0;
128
- inset-inline-start: 0;
129
- background: light-dark(var(--color-elevated), color-mix(in srgb, var(--color-label) 15%, var(--color-elevated)));
130
- /* Clipped, never skewed: a skew lifts the whole body off the floor;
256
+ background: color-mix(
257
+ in srgb,
258
+ var(--color-label) 11%,
259
+ var(--color-elevated)
260
+ );
261
+ overflow: hidden;
262
+ cursor: ew-resize;
263
+ touch-action: pan-y;
264
+ }
265
+ .passui-slosh-track[aria-disabled="true"],
266
+ .passui-wake-track[aria-disabled="true"] {
267
+ cursor: not-allowed;
268
+ }
269
+ .passui-slosh-track:focus-visible,
270
+ .passui-wake-track:focus-visible {
271
+ outline: 2px solid var(--color-accent-text);
272
+ outline-offset: 4px;
273
+ }
274
+ .passui-slosh-fill {
275
+ position: absolute;
276
+ inset-block: 0;
277
+ inset-inline-start: 0;
278
+ background: light-dark(
279
+ var(--color-elevated),
280
+ color-mix(in srgb, var(--color-label) 15%, var(--color-elevated))
281
+ );
282
+ /* Clipped, never skewed: a skew lifts the whole body off the floor;
131
283
  a meniscus leans only the moving edge. The track clips end stops. */
132
- clip-path: polygon(0 0, calc(100% + var(--slosh-lean, 0px)) 0,
133
- calc(100% - var(--slosh-lean, 0px)) 100%, 0 100%);
134
- }
135
- .passui-slosh-track:dir(rtl) .passui-slosh-fill { transform: scaleX(-1); }
136
- .passui-slosh-slider[data-size="sm"] .passui-slosh-track { height: 2rem; }
137
- .passui-slosh-slider[data-size="sm"] .passui-slosh-knob { top: 4px; bottom: 4px; }
138
- .passui-slosh-slider[data-size="lg"] .passui-slosh-track { height: 3rem; }
139
- .passui-slosh-slider[data-size="lg"] .passui-slosh-knob { top: 8px; bottom: 8px; width: 4px; margin-inline-start: -2px; }
140
- .passui-slosh-knob {
141
- position: absolute;
142
- top: 6px;
143
- bottom: 6px;
144
- width: 3px;
145
- margin-inline-start: -1.5px;
146
- border-radius: var(--radius-full);
147
- background: var(--color-label);
148
- pointer-events: none;
149
- }
150
- /* Each bar holds energy. Its height is written directly, while React
284
+ clip-path: polygon(
285
+ 0 0,
286
+ calc(100% + var(--slosh-lean, 0px)) 0,
287
+ calc(100% - var(--slosh-lean, 0px)) 100%,
288
+ 0 100%
289
+ );
290
+ }
291
+ .passui-slosh-track:dir(rtl) .passui-slosh-fill {
292
+ transform: scaleX(-1);
293
+ }
294
+ .passui-slosh-slider[data-size="sm"] .passui-slosh-track {
295
+ height: 2rem;
296
+ }
297
+ .passui-slosh-slider[data-size="sm"] .passui-slosh-knob {
298
+ top: 4px;
299
+ bottom: 4px;
300
+ }
301
+ .passui-slosh-slider[data-size="lg"] .passui-slosh-track {
302
+ height: 3rem;
303
+ }
304
+ .passui-slosh-slider[data-size="lg"] .passui-slosh-knob {
305
+ top: 8px;
306
+ bottom: 8px;
307
+ width: 4px;
308
+ margin-inline-start: -2px;
309
+ }
310
+ .passui-slosh-knob {
311
+ position: absolute;
312
+ top: 6px;
313
+ bottom: 6px;
314
+ width: 3px;
315
+ margin-inline-start: -1.5px;
316
+ border-radius: var(--radius-full);
317
+ background: var(--color-label);
318
+ pointer-events: none;
319
+ }
320
+ /* Each bar holds energy. Its height is written directly, while React
151
321
  owns the value and lit marks. No standing animation runs at rest. */
152
- .passui-wake-slider {
153
- display: flex;
154
- align-items: center;
155
- gap: 1rem;
156
- width: 100%;
157
- min-width: 0;
158
- color: var(--color-label);
159
- }
160
- .passui-wake-track {
161
- display: flex;
162
- flex: 1;
163
- min-width: 0;
164
- align-items: center;
165
- justify-content: space-between;
166
- gap: min(4px, calc(25% / var(--wake-bars, 36)));
167
- cursor: ew-resize;
168
- touch-action: pan-y;
169
- user-select: none;
170
- -webkit-user-select: none;
171
- -webkit-tap-highlight-color: transparent;
172
- border-radius: var(--radius-sm);
173
- }
174
- .passui-wake-bar {
175
- flex: 1 1 3px;
176
- max-width: 3px;
177
- min-width: 0;
178
- border-radius: var(--radius-full);
179
- background: color-mix(in srgb, var(--color-label) 24%, var(--color-elevated));
180
- transform-origin: 50% 50%;
181
- transition: background-color 160ms ease;
182
- }
183
- .passui-wake-bar[data-on] { background: var(--color-label); }
184
- .passui-wake-value {
185
- min-width: 3ch;
186
- font-family: var(--font-sans);
187
- font-size: var(--text-footnote);
188
- font-weight: 500;
189
- font-variant-numeric: tabular-nums;
190
- color: var(--color-label-secondary);
191
- }
192
- .passui-wake-slider[data-size="sm"] { gap: 0.75rem; }
193
- .passui-wake-slider[data-size="sm"] .passui-wake-value { font-size: var(--text-caption); }
194
- .passui-wake-slider[data-size="lg"] { gap: 1.25rem; }
195
- .passui-wake-slider[data-size="lg"] .passui-wake-value { font-size: var(--text-subheadline); }
196
- @media (prefers-reduced-motion: reduce) {
197
- .passui-wake-bar, .passui-search-pill { transition: none; }
198
- .passui-search-pill:active { scale: 1; }
199
- .passui-floating-label, .passui-field-outline, .passui-field-outline legend,
200
- .passui-otp-cell, .passui-otp-capsule, .passui-otp-check { transition: none; }
201
- .passui-otp-glyph, .passui-otp-digit { animation: none !important; }
202
- .passui-otp-materials { filter: none !important; }
203
- }
322
+ .passui-wake-slider {
323
+ display: flex;
324
+ align-items: center;
325
+ gap: 1rem;
326
+ width: 100%;
327
+ min-width: 0;
328
+ color: var(--color-label);
329
+ }
330
+ .passui-wake-track {
331
+ display: flex;
332
+ flex: 1;
333
+ min-width: 0;
334
+ align-items: center;
335
+ justify-content: space-between;
336
+ gap: min(4px, calc(25% / var(--wake-bars, 36)));
337
+ cursor: ew-resize;
338
+ touch-action: pan-y;
339
+ user-select: none;
340
+ -webkit-user-select: none;
341
+ -webkit-tap-highlight-color: transparent;
342
+ border-radius: var(--radius-sm);
343
+ }
344
+ .passui-wake-bar {
345
+ flex: 1 1 3px;
346
+ max-width: 3px;
347
+ min-width: 0;
348
+ border-radius: var(--radius-full);
349
+ background: color-mix(
350
+ in srgb,
351
+ var(--color-label) 24%,
352
+ var(--color-elevated)
353
+ );
354
+ transform-origin: 50% 50%;
355
+ transition: background-color 160ms ease;
356
+ }
357
+ .passui-wake-bar[data-on] {
358
+ background: var(--color-label);
359
+ }
360
+ .passui-wake-value {
361
+ min-width: 3ch;
362
+ font-family: var(--font-sans);
363
+ font-size: var(--text-footnote);
364
+ font-weight: 500;
365
+ font-variant-numeric: tabular-nums;
366
+ color: var(--color-label-secondary);
367
+ }
368
+ .passui-wake-slider[data-size="sm"] {
369
+ gap: 0.75rem;
370
+ }
371
+ .passui-wake-slider[data-size="sm"] .passui-wake-value {
372
+ font-size: var(--text-caption);
373
+ }
374
+ .passui-wake-slider[data-size="lg"] {
375
+ gap: 1.25rem;
376
+ }
377
+ .passui-wake-slider[data-size="lg"] .passui-wake-value {
378
+ font-size: var(--text-subheadline);
379
+ }
380
+ @media (prefers-reduced-motion: reduce) {
381
+ .passui-wake-bar,
382
+ .passui-search-pill {
383
+ transition: none;
384
+ }
385
+ .passui-search-pill:active {
386
+ scale: 1;
387
+ }
388
+ .passui-floating-label,
389
+ .passui-field-outline,
390
+ .passui-field-outline legend,
391
+ .passui-otp-cell,
392
+ .passui-otp-capsule,
393
+ .passui-otp-check {
394
+ transition: none;
395
+ }
396
+ .passui-otp-glyph,
397
+ .passui-otp-digit {
398
+ /* biome-ignore lint/complexity/noImportantStyles: CSS utility override */
399
+ animation: none !important;
400
+ }
401
+ .passui-otp-materials {
402
+ /* biome-ignore lint/complexity/noImportantStyles: CSS utility override */
403
+ filter: none !important;
404
+ }
405
+ }
204
406
  }
package/src/tokens.ts CHANGED
@@ -1 +1 @@
1
- export * from "@passui/tokens"
1
+ export * from "@passui/tokens";
@@ -1,21 +0,0 @@
1
- import { type HTMLMotionProps } from "motion/react";
2
- import { type ReactNode, type RefObject } from "react";
3
- export type PopoverOrigin = "top-left" | "top-right";
4
- export type PopoverSize = "sm" | "md";
5
- export interface PopoverProps extends Omit<HTMLMotionProps<"div">, "children"> {
6
- open: boolean;
7
- children?: ReactNode;
8
- /** Which corner the popover grows from. */
9
- origin?: PopoverOrigin;
10
- /** Trigger whose shape the popover uses during its opening and closing motion. */
11
- anchorRef?: RefObject<HTMLElement | null>;
12
- /** Surface corner radius. @default "md" */
13
- size?: PopoverSize;
14
- }
15
- /**
16
- * A glass surface that springs open from its anchor. Position it with
17
- * `className` (it is absolutely positioned within a relative parent); it
18
- * flips above its relative parent when the bottom edge is short, and
19
- * stays inside the visible viewport as it resizes or scrolls.
20
- */
21
- export declare function Popover({ open, ...props }: PopoverProps): import("react").JSX.Element;