aporia 0.2.6 → 0.2.8

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.
@@ -1 +1 @@
1
- {"version":3,"file":"Category.d.ts","sourceRoot":"","sources":["../../src/components/Category.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AAGd,OAAO,gBAAgB,CAAA;AAavB,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,SAAS,CAAA;IACnB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,KAAK,IAAI,CAAA;IAClD,yDAAyD;IACzD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,OAAO,KAAK,IAAI,CAAA;IACpD,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,QAAQ,EACR,QAAgB,EAChB,gBAAgB,EAChB,SAAS,EAAE,aAAa,EACxB,iBAAiB,EACjB,gBAAwB,EACxB,SAAS,GACV,EAAE,aAAa,2CAqJf"}
1
+ {"version":3,"file":"Category.d.ts","sourceRoot":"","sources":["../../src/components/Category.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AAGd,OAAO,gBAAgB,CAAA;AAavB,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,SAAS,CAAA;IACnB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,KAAK,IAAI,CAAA;IAClD,yDAAyD;IACzD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,OAAO,KAAK,IAAI,CAAA;IACpD,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,QAAQ,EACR,QAAgB,EAChB,gBAAgB,EAChB,SAAS,EAAE,aAAa,EACxB,iBAAiB,EACjB,gBAAwB,EACxB,SAAS,GACV,EAAE,aAAa,2CAsJf"}
@@ -1 +1 @@
1
- {"version":3,"file":"ColorPicker.d.ts","sourceRoot":"","sources":["../../src/components/ColorPicker.tsx"],"names":[],"mappings":"AAwBA,OAAO,mBAAmB,CAAA;AAE1B,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC,CAAA;AAoGD,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,gBAAgB,2CAwehE"}
1
+ {"version":3,"file":"ColorPicker.d.ts","sourceRoot":"","sources":["../../src/components/ColorPicker.tsx"],"names":[],"mappings":"AA0BA,OAAO,mBAAmB,CAAA;AAE1B,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC,CAAA;AA4FD,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,gBAAgB,2CAwehE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ColorRow.d.ts","sourceRoot":"","sources":["../../src/components/ColorRow.tsx"],"names":[],"mappings":"AAMA,OAAO,gBAAgB,CAAA;AAevB,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,wBAAgB,QAAQ,CAAC,EAAE,KAAe,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,aAAa,2CA4DnG"}
1
+ {"version":3,"file":"ColorRow.d.ts","sourceRoot":"","sources":["../../src/components/ColorRow.tsx"],"names":[],"mappings":"AAMA,OAAO,gBAAgB,CAAA;AAOvB,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,wBAAgB,QAAQ,CAAC,EAAE,KAAe,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,aAAa,2CA6DnG"}
@@ -1 +1 @@
1
- {"version":3,"file":"GradientPicker.d.ts","sourceRoot":"","sources":["../../src/components/GradientPicker.tsx"],"names":[],"mappings":"AAIA,OAAO,sBAAsB,CAAA;AAE7B,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,wEAAwE;IACxE,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,+BAA+B;IAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAA;IACzC,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAmDD,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,KAAK,SAAK,GAAG,MAAM,CAWzE;AAED,gDAAgD;AAChD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAmB9D;AAED,0EAA0E;AAC1E,eAAO,MAAM,sBAAsB,EAAE,YAAY,EAOhD,CAAA;AA+ED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAU,EAAE,EAAE,mBAAmB,2CAiHlF"}
1
+ {"version":3,"file":"GradientPicker.d.ts","sourceRoot":"","sources":["../../src/components/GradientPicker.tsx"],"names":[],"mappings":"AAIA,OAAO,sBAAsB,CAAA;AAE7B,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,wEAAwE;IACxE,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,+BAA+B;IAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAA;IACzC,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AA+CD,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,KAAK,SAAK,GAAG,MAAM,CAWzE;AAED,gDAAgD;AAChD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAmB9D;AAED,0EAA0E;AAC1E,eAAO,MAAM,sBAAsB,EAAE,YAAY,EAOhD,CAAA;AA2ED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAU,EAAE,EAAE,mBAAmB,2CAiHlF"}
@@ -1,10 +1,23 @@
1
1
  import { HTMLAttributes, ReactNode } from 'react';
2
2
  export type PanelProps = HTMLAttributes<HTMLDivElement> & {
3
3
  children: ReactNode;
4
+ /** When true, panel is fixed to top-left and floats above page content. */
5
+ floating?: boolean;
6
+ /** Controlled collapsed state. */
7
+ collapsed?: boolean;
8
+ /** Initial collapsed state when uncontrolled. */
9
+ defaultCollapsed?: boolean;
10
+ /** Fires when the collapsed state changes (controlled or uncontrolled). */
11
+ onCollapsedChange?: (nextCollapsed: boolean) => void;
12
+ /** aria-label for the toggle button. */
13
+ collapseAriaLabel?: string;
4
14
  };
5
15
  /**
6
- * Default shell for configurator blocks: black surface, 24px radius, 16px padding,
7
- * column flex anchored to the start (top).
16
+ * Black configurator card that morphs between an expanded shell and a 32×32 icon.
17
+ *
18
+ * The same `<section>` element resizes in place: width/height/padding/border-radius
19
+ * animate via Motion, content is clipped via `overflow: hidden` on the shell.
20
+ * No `layout` prop — that would scale via transforms and distort the rectangle.
8
21
  */
9
- export declare function Panel({ children, className, ...rest }: PanelProps): import("react/jsx-runtime").JSX.Element;
22
+ export declare function Panel({ children, className, floating, collapsed: collapsedProp, defaultCollapsed, onCollapsedChange, collapseAriaLabel, style: externalStyle, ...domRest }: PanelProps): import("react/jsx-runtime").JSX.Element;
10
23
  //# sourceMappingURL=Panel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Panel.d.ts","sourceRoot":"","sources":["../../src/components/Panel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtD,OAAO,aAAa,CAAA;AAEpB,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IACxD,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAA;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,UAAU,2CASjE"}
1
+ {"version":3,"file":"Panel.d.ts","sourceRoot":"","sources":["../../src/components/Panel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,cAAc,EAGnB,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AAEd,OAAO,aAAa,CAAA;AAEpB,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IACxD,QAAQ,EAAE,SAAS,CAAA;IACnB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kCAAkC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,OAAO,KAAK,IAAI,CAAA;IACpD,wCAAwC;IACxC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B,CAAA;AAoED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,EACpB,QAAQ,EACR,SAAS,EACT,QAAe,EACf,SAAS,EAAE,aAAa,EACxB,gBAAwB,EACxB,iBAAiB,EACjB,iBAAkC,EAClC,KAAK,EAAE,aAAa,EACpB,GAAG,OAAO,EACX,EAAE,UAAU,2CAmZZ"}
@@ -1 +1 @@
1
- {"version":3,"file":"SliderRow.d.ts","sourceRoot":"","sources":["../../src/components/SliderRow.tsx"],"names":[],"mappings":"AAQA,OAAO,iBAAiB,CAAA;AAuDxB,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAC/B,mFAAmF;IACnF,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAgDD,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,GAAG,EACH,GAAG,EACH,IAAI,EACJ,QAAQ,EACR,GAAG,EACH,QAAQ,EAAE,YAAY,GACvB,EAAE,cAAc,2CA8bhB"}
1
+ {"version":3,"file":"SliderRow.d.ts","sourceRoot":"","sources":["../../src/components/SliderRow.tsx"],"names":[],"mappings":"AAQA,OAAO,iBAAiB,CAAA;AAuDxB,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAC/B,mFAAmF;IACnF,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAgDD,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,GAAG,EACH,GAAG,EACH,IAAI,EACJ,QAAQ,EACR,GAAG,EACH,QAAQ,EAAE,YAAY,GACvB,EAAE,cAAc,2CAkchB"}
package/dist/index.css CHANGED
@@ -43,8 +43,15 @@
43
43
  --aporia-ui-font-size: 14px;
44
44
  --aporia-ui-line-height: 1.25;
45
45
 
46
- /* Default panel width cap (matches the package demo). Override per app if needed. */
47
- --aporia-panel-max-width: 360px;
46
+ /* Panel geometry defaults from the current Figma shell.
47
+ * Collapsed size (32×32) is hardcoded in `Panel.tsx` so Motion can animate
48
+ * to concrete pixel values; max-width remains overridable via this token. */
49
+ --aporia-panel-max-width: 280px;
50
+ --aporia-panel-offset-top: 40px;
51
+ --aporia-panel-offset-left: 40px;
52
+ --aporia-panel-offset-right: 40px;
53
+ --aporia-panel-offset-bottom: 40px;
54
+ --aporia-panel-z-index: 1000;
48
55
 
49
56
  /* Ticks (base color × layer opacity ≈ dark appearance) */
50
57
  --slider-tick: rgba(255, 255, 255, 0.32);
@@ -80,38 +87,159 @@
80
87
  --slider-debug-dom-value: rgba(80, 180, 255, 0.95);
81
88
  --slider-debug-dom-shadow: rgba(0, 0, 0, 0.35);
82
89
  }
83
- /* Shell for grouped controls: solid black card, generous radius, inset padding. */
90
+ /*
91
+ * Aporia Panel — black card that morphs between expanded and a 32×32 icon.
92
+ *
93
+ * Motion drives: height, border-radius, padding, gap.
94
+ * CSS drives: width / max-width (handles % → px transitions natively).
95
+ * `overflow: hidden` clips content during the resize so we never see ragged edges.
96
+ */
84
97
 
85
98
  .aporiaPanel {
99
+ position: relative;
86
100
  box-sizing: border-box;
87
101
  width: 100%;
88
102
  max-width: min(var(--aporia-panel-max-width), 100%);
89
103
  min-width: 0;
90
- /* Hug content: avoid stretching to fill a flex/grid parent’s unused vertical space. */
91
104
  flex: 0 0 auto;
92
- height: auto;
93
- min-height: 0;
94
- max-height: none;
95
105
  align-self: stretch;
96
- /* Typography + metrics: see `aporia-surfaces.css` (imported after components). */
97
- /* Always read as the black configurator card, independent of host `color` / light UI. */
98
106
  color: var(--slider-text);
99
107
  color-scheme: dark;
100
108
  background-color: #000000;
101
- border-radius: 24px;
102
- padding: 16px;
109
+ overflow: visible;
110
+ display: flex;
111
+ flex-direction: column;
112
+ align-items: stretch;
113
+ justify-content: flex-start;
114
+ transition:
115
+ width 0.28s cubic-bezier(0.77, 0, 0.175, 1),
116
+ max-width 0.28s cubic-bezier(0.77, 0, 0.175, 1);
103
117
  box-shadow:
104
118
  0 162px 45px 0 rgba(0, 0, 0, 0),
105
119
  0 103px 41px 0 rgba(0, 0, 0, 0.01),
106
120
  0 58px 35px 0 rgba(0, 0, 0, 0.05),
107
121
  0 26px 26px 0 rgba(0, 0, 0, 0.08),
108
122
  0 6px 14px 0 rgba(0, 0, 0, 0.09);
123
+ }
124
+
125
+ .aporiaPanel[data-floating='true'] {
126
+ position: fixed;
127
+ z-index: var(--aporia-panel-z-index, 1000);
128
+ }
129
+
130
+ .aporiaPanel[data-collapsed='true'] {
131
+ width: 32px;
132
+ max-width: 32px;
133
+ cursor: pointer;
134
+ touch-action: none;
135
+ overflow: hidden;
136
+ }
137
+
138
+ .aporiaPanelSnapHint {
139
+ position: fixed;
140
+ width: 32px;
141
+ height: 32px;
142
+ border-radius: 12px;
143
+ background: rgba(128, 128, 128, 1);
144
+ pointer-events: none;
145
+ }
146
+
147
+ /* Header row holds the logo toggle (and any future title / actions). */
148
+ .aporiaPanelHeader {
149
+ display: flex;
150
+ align-items: center;
151
+ justify-content: flex-start;
152
+ flex: 0 0 auto;
153
+ min-height: 22px;
154
+ width: 100%;
155
+ }
156
+
157
+ .aporiaPanelToggle {
158
+ width: 22px;
159
+ height: 22px;
160
+ padding: 0;
161
+ margin: 0;
162
+ border: none;
163
+ border-radius: 6px;
164
+ background: transparent;
165
+ color: rgba(255, 255, 255, 0.55);
166
+ display: inline-flex;
167
+ align-items: center;
168
+ justify-content: center;
169
+ cursor: pointer;
170
+ /* Hover/press only — never animate width/height (Motion owns size). */
171
+ transition:
172
+ color 0.18s cubic-bezier(0.23, 1, 0.32, 1),
173
+ background-color 0.18s cubic-bezier(0.23, 1, 0.32, 1),
174
+ transform 0.14s cubic-bezier(0.23, 1, 0.32, 1);
175
+ }
176
+
177
+ .aporiaPanelToggle:active {
178
+ transform: scale(0.97);
179
+ }
180
+
181
+ .aporiaPanelToggle:focus-visible {
182
+ outline: 2px solid rgba(255, 255, 255, 0.4);
183
+ outline-offset: 2px;
184
+ }
185
+
186
+ .aporiaPanel[data-collapsed='true'] .aporiaPanelToggle {
187
+ color: #ffffff;
188
+ pointer-events: none;
189
+ }
190
+
191
+ .aporiaPanelLogoGlyph {
192
+ width: 22px;
193
+ height: 22px;
194
+ display: block;
195
+ }
196
+
197
+ /*
198
+ * Body holds Category blocks. It stays in flow at full opacity; on collapse
199
+ * we fade it out fast (so content disappears before the shell finishes shrinking).
200
+ * On expand we delay the fade-in so content appears after the shell has grown.
201
+ */
202
+ .aporiaPanelBody {
203
+ /* Let slider overdrag render into panel side padding before clipping. */
204
+ --aporia-panel-overdrag-bleed: 16px;
205
+ display: flex;
206
+ flex-direction: column;
207
+ align-items: stretch;
208
+ flex: 1 1 auto;
209
+ min-height: 0;
210
+ min-width: 0;
211
+ width: calc(100% + var(--aporia-panel-overdrag-bleed) * 2);
212
+ margin-left: calc(var(--aporia-panel-overdrag-bleed) * -1);
213
+ margin-right: calc(var(--aporia-panel-overdrag-bleed) * -1);
214
+ padding-left: var(--aporia-panel-overdrag-bleed);
215
+ padding-right: var(--aporia-panel-overdrag-bleed);
216
+ box-sizing: border-box;
217
+ margin-top: 16px;
218
+ opacity: 1;
219
+ /* Keep vertical scrolling, clip X at the panel edge (not row edge). */
220
+ overflow-x: hidden;
221
+ overflow-y: auto;
222
+ scrollbar-gutter: stable both-edges;
223
+ }
224
+
225
+ .aporiaPanelBodyContent {
109
226
  display: flex;
110
227
  flex-direction: column;
111
228
  gap: 8px;
112
229
  align-items: stretch;
113
- justify-content: flex-start;
114
- align-content: flex-start;
230
+ min-width: 0;
231
+ }
232
+
233
+ .aporiaPanel[data-collapsed='true'] .aporiaPanelBody {
234
+ pointer-events: none;
235
+ }
236
+
237
+ @media (prefers-reduced-motion: reduce) {
238
+ .aporiaPanel,
239
+ .aporiaPanelToggle,
240
+ .aporiaPanelBody {
241
+ transition-duration: 0.01ms;
242
+ }
115
243
  }
116
244
  .category {
117
245
  display: flex;
@@ -156,11 +284,22 @@
156
284
  color: var(--color-muted);
157
285
  cursor: pointer;
158
286
  border-radius: 6px;
287
+ transform: scale(1);
288
+ transition:
289
+ transform 140ms cubic-bezier(0.23, 1, 0.32, 1),
290
+ color 140ms cubic-bezier(0.23, 1, 0.32, 1),
291
+ background-color 140ms cubic-bezier(0.23, 1, 0.32, 1);
159
292
  }
160
293
 
161
- .categoryChevronBtn:hover {
162
- color: var(--slider-text-muted);
163
- background: rgba(255, 255, 255, 0.06);
294
+ @media (hover: hover) and (pointer: fine) {
295
+ .categoryChevronBtn:hover {
296
+ color: var(--slider-text-muted);
297
+ background: rgba(255, 255, 255, 0.06);
298
+ }
299
+ }
300
+
301
+ .categoryChevronBtn:active {
302
+ transform: scale(0.97);
164
303
  }
165
304
 
166
305
  .categoryChevronBtn:focus-visible {
@@ -170,11 +309,11 @@
170
309
 
171
310
  .categoryChevronIcon {
172
311
  display: block;
173
- width: 12px;
174
- height: 12px;
312
+ width: 14px;
313
+ height: 14px;
175
314
  transform: rotate(0deg);
176
315
  transform-origin: 50% 50%;
177
- transition: transform 0.15s ease-out;
316
+ transition: transform 180ms cubic-bezier(0.23, 1, 0.32, 1);
178
317
  }
179
318
 
180
319
  .categoryChevronIcon[data-collapsed="true"] {
@@ -196,7 +335,11 @@
196
335
  display: flex;
197
336
  align-items: center;
198
337
  justify-content: center;
199
- transition: opacity 0.15s ease-out;
338
+ transform: scale(1);
339
+ transition:
340
+ transform 140ms cubic-bezier(0.23, 1, 0.32, 1),
341
+ opacity 140ms cubic-bezier(0.23, 1, 0.32, 1),
342
+ background-color 140ms cubic-bezier(0.23, 1, 0.32, 1);
200
343
  }
201
344
 
202
345
  .categoryDisabledDot::after {
@@ -207,13 +350,24 @@
207
350
  background: rgba(255, 255, 255, 0.85);
208
351
  flex-shrink: 0;
209
352
  transition:
210
- transform 0.15s ease-out,
211
- background-color 0.15s ease-out;
353
+ transform 140ms cubic-bezier(0.23, 1, 0.32, 1),
354
+ background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),
355
+ opacity 140ms cubic-bezier(0.23, 1, 0.32, 1);
212
356
  }
213
357
 
214
- .categoryDisabledDot:hover::after {
215
- background: #ffffff;
216
- transform: scale(1.15);
358
+ @media (hover: hover) and (pointer: fine) {
359
+ .categoryDisabledDot:hover::after {
360
+ background: #ffffff;
361
+ transform: scale(1.15);
362
+ }
363
+ }
364
+
365
+ .categoryDisabledDot:active {
366
+ transform: scale(0.97);
367
+ }
368
+
369
+ .categoryDisabledDot:active::after {
370
+ transform: scale(1.05);
217
371
  }
218
372
 
219
373
  .categoryDisabledDot:focus-visible {
@@ -225,6 +379,15 @@
225
379
  opacity: 0.35;
226
380
  }
227
381
 
382
+ @media (prefers-reduced-motion: reduce) {
383
+ .categoryChevronBtn,
384
+ .categoryChevronIcon,
385
+ .categoryDisabledDot,
386
+ .categoryDisabledDot::after {
387
+ transition-duration: 0ms;
388
+ }
389
+ }
390
+
228
391
  .categoryTitle {
229
392
  margin: 0;
230
393
  flex: 1;
@@ -241,6 +404,19 @@
241
404
 
242
405
  .categoryBody {
243
406
  min-width: 0;
407
+ /*
408
+ * Overdrag fix: `overflow-x: visible` + `overflow-y: hidden` gets coerced and can
409
+ * clip SliderRow too early. Keep overflow visible, then clip only vertically via
410
+ * clip-path while allowing a small horizontal bleed.
411
+ */
412
+ --aporia-category-overdrag-bleed: 16px;
413
+ overflow: visible;
414
+ clip-path: inset(
415
+ 0
416
+ calc(var(--aporia-category-overdrag-bleed) * -1)
417
+ 0
418
+ calc(var(--aporia-category-overdrag-bleed) * -1)
419
+ );
244
420
  }
245
421
 
246
422
  /* Padding lives inside the height animation so it never springs on its own (8px + Panel gap = 16px between categories). */