aporia 0.2.1 → 0.2.6
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 -9
- package/dist/ThemeProvider.d.ts.map +1 -1
- package/dist/components/Category.d.ts.map +1 -1
- package/dist/components/SelectRow.d.ts +17 -0
- package/dist/components/SelectRow.d.ts.map +1 -0
- package/dist/components/SwatchPopover.d.ts +5 -2
- package/dist/components/SwatchPopover.d.ts.map +1 -1
- package/dist/{style.css → index.css} +424 -16
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +148 -12
- package/dist/index.js.map +1 -1
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -8,6 +8,18 @@ A collection of production-quality React components for building configurators -
|
|
|
8
8
|
npm install aporia
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
Import **`aporia/styles.css` once** in your app entry (for example `main.tsx`). If you use Tailwind or another global reset, import Aporia’s stylesheet **after** those layers so Aporia’s opinionated panel / popover typography and control chrome win predictable conflicts.
|
|
12
|
+
|
|
13
|
+
## Maintainers: package demo + consumer sandbox
|
|
14
|
+
|
|
15
|
+
If you keep a sibling app (for example `../aporia-test`) next to this repo:
|
|
16
|
+
|
|
17
|
+
1. **Canonical UI (this repo)** — `npm run dev` starts the **Vite demo** (`--mode demo`, default port **5178**). That is the reference layout: white page shell (`var(--color-page)`), `Panel` uses the default **360px** max width from `--aporia-panel-max-width`.
|
|
18
|
+
2. **NPM-style consumer** — in the sibling app, depend on `file:../aporia`, run `npm run dev` there (this workspace uses port **5173** for the consumer). After library changes, run `npm run sync-lib` inside the consumer to rebuild `aporia` and refresh the `file:` install.
|
|
19
|
+
3. **From the parent folder** — with both repos under the same parent directory, `npm run dev:package` and `npm run dev:consumer` run each app; `npm run sync:consumer` rebuilds the library and reinstalls into the consumer.
|
|
20
|
+
|
|
21
|
+
Publishing for end users: bump `version`, run `npm run build`, then `npm publish`. Consumers should use a normal semver range (for example `^0.2.6`) and `import 'aporia/styles.css'`. The `prepublishOnly` script runs `build` automatically on publish. Until you publish, sibling apps can use `file:../aporia` and `npm run sync-lib` after edits — **no publish required** for local reflection.
|
|
22
|
+
|
|
11
23
|
## Usage
|
|
12
24
|
|
|
13
25
|
The usual setup is a **Panel** with one or more **Category** blocks, each containing rows (`SliderRow`, `ColorRow`, etc.). The package default export is `Panel`, so you can import it as the default or by name.
|
|
@@ -46,13 +58,13 @@ function App() {
|
|
|
46
58
|
}
|
|
47
59
|
```
|
|
48
60
|
|
|
49
|
-
|
|
61
|
+
Use `Panel` (and usually `Category`) for any real configurator surface so spacing, typography, and the black card shell stay consistent. Rows still work as leaf nodes, but they are designed to live inside that shell.
|
|
50
62
|
|
|
51
63
|
## Components
|
|
52
64
|
|
|
53
65
|
### Panel
|
|
54
66
|
|
|
55
|
-
Rounded shell for a configurator: drop in `Category` sections and row components as children.
|
|
67
|
+
Rounded shell for a configurator: drop in `Category` sections and row components as children. By default the panel is **`width: 100%`** with **`max-width: min(360px, 100%)`** via the `:root` token **`--aporia-panel-max-width`** (override on `html` or a wrapper if you need a wider shell).
|
|
56
68
|
|
|
57
69
|
### Category
|
|
58
70
|
|
|
@@ -133,7 +145,9 @@ const stops = parseGradient(css) // Parse CSS gradient
|
|
|
133
145
|
|
|
134
146
|
## Theming
|
|
135
147
|
|
|
136
|
-
Aporia
|
|
148
|
+
Aporia ships a **dark** visual system: the **Panel** surface is always `#000000` with light text, and `color-scheme: dark` is scoped to the panel and floating pickers only so your host page (light theme, marketing site, etc.) is not forced into document-wide dark UA chrome. CSS variables remain on `:root` so portaled popovers still inherit them.
|
|
149
|
+
|
|
150
|
+
`ThemeProvider` is for **React context** (`useTheme`) only; it does not mutate `<html>` or set global `data-theme`.
|
|
137
151
|
|
|
138
152
|
```tsx
|
|
139
153
|
import { ThemeProvider, useTheme } from 'aporia'
|
|
@@ -146,15 +160,13 @@ function App() {
|
|
|
146
160
|
)
|
|
147
161
|
}
|
|
148
162
|
|
|
149
|
-
//
|
|
150
|
-
function
|
|
151
|
-
const { theme
|
|
152
|
-
return <
|
|
163
|
+
// `theme` is `'dark'` today; useful for future light mode without changing call sites.
|
|
164
|
+
function ThemeLabel() {
|
|
165
|
+
const { theme } = useTheme()
|
|
166
|
+
return <span>{theme}</span>
|
|
153
167
|
}
|
|
154
168
|
```
|
|
155
169
|
|
|
156
|
-
Keyboard shortcut: `Shift+T` toggles the theme.
|
|
157
|
-
|
|
158
170
|
## Peer Dependencies
|
|
159
171
|
|
|
160
172
|
Aporia requires these peer dependencies:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../src/ThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../src/ThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEjE,MAAM,MAAM,KAAK,GAAG,MAAM,CAAA;AAE1B,KAAK,iBAAiB,GAAG;IACvB,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAID,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAQlE;AAED,wBAAgB,QAAQ,sBAMvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Category.d.ts","sourceRoot":"","sources":["../../src/components/Category.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type SelectRowOption = {
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
};
|
|
5
|
+
export type SelectRowProps = {
|
|
6
|
+
label: string;
|
|
7
|
+
options: readonly SelectRowOption[];
|
|
8
|
+
/** Controlled value; `null` shows the placeholder. */
|
|
9
|
+
value: string | null;
|
|
10
|
+
onChange: (value: string) => void;
|
|
11
|
+
placeholder?: string;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
/** Optional form field name (hidden input). */
|
|
14
|
+
name?: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function SelectRow({ label, options, value, onChange, placeholder, disabled: disabledProp, name, }: SelectRowProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
//# sourceMappingURL=SelectRow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectRow.d.ts","sourceRoot":"","sources":["../../src/components/SelectRow.tsx"],"names":[],"mappings":"AAGA,OAAO,iBAAiB,CAAA;AAExB,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,SAAS,eAAe,EAAE,CAAA;IACnC,sDAAsD;IACtD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,OAAO,EACP,KAAK,EACL,QAAQ,EACR,WAAuB,EACvB,QAAQ,EAAE,YAAY,EACtB,IAAI,GACL,EAAE,cAAc,2CA8FhB"}
|
|
@@ -14,8 +14,11 @@ type SwatchPopoverProps = {
|
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
16
|
* Base UI Popover anchored to a swatch: opens below, aligned to the inline end (bottom-trailing in LTR).
|
|
17
|
-
*
|
|
18
|
-
* `modal=
|
|
17
|
+
*
|
|
18
|
+
* **Default `modal={false}`** matches Base UI and keeps pointer events on the document so nested
|
|
19
|
+
* portaled pickers (e.g. gradient editor → stop color) still receive clicks. Use `modal={true}`
|
|
20
|
+
* only when you want scroll lock + outside pointer blocking for a single-layer popover.
|
|
21
|
+
* Use `modal="trap-focus"` for focus trapping without scroll lock.
|
|
19
22
|
*/
|
|
20
23
|
export declare function SwatchPopover({ title, renderTrigger, children, modal, side, align, sideOffset, zIndex, }: SwatchPopoverProps): import("react/jsx-runtime").JSX.Element;
|
|
21
24
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SwatchPopover.d.ts","sourceRoot":"","sources":["../../src/components/SwatchPopover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,qBAAqB,CAAA;AAE5B,MAAM,MAAM,0BAA0B,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;AAEvE,KAAK,kBAAkB,GAAG;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,WAAW,CAAC,0BAA0B,CAAC,CAAA;IACtD,QAAQ,EAAE,SAAS,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACvC,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IACnD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED
|
|
1
|
+
{"version":3,"file":"SwatchPopover.d.ts","sourceRoot":"","sources":["../../src/components/SwatchPopover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,qBAAqB,CAAA;AAE5B,MAAM,MAAM,0BAA0B,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;AAEvE,KAAK,kBAAkB,GAAG;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,WAAW,CAAC,0BAA0B,CAAC,CAAA;IACtD,QAAQ,EAAE,SAAS,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACvC,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IACnD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,aAAa,EACb,QAAQ,EACR,KAAa,EACb,IAAe,EACf,KAAa,EACb,UAAc,EACd,MAAM,GACP,EAAE,kBAAkB,2CA2BpB"}
|
|
@@ -1,9 +1,102 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Theme tokens — dark mode only.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* Tokens live on :root so portaled popovers (mounted under <body>) still inherit variables.
|
|
7
|
+
* Do not set `color-scheme` here — that would affect the entire host document (scrollbars,
|
|
8
|
+
* native controls outside Aporia). `color-scheme: dark` is applied only on Panel and popups.
|
|
9
|
+
*/
|
|
10
|
+
:root {
|
|
11
|
+
/* App shell */
|
|
12
|
+
--color-page: #ffffff;
|
|
13
|
+
--color-text: rgba(255, 255, 255, 0.87);
|
|
14
|
+
--color-muted: rgba(255, 255, 255, 0.45);
|
|
15
|
+
|
|
16
|
+
/* Slider card (full pill) */
|
|
17
|
+
--slider-surface: rgba(255, 255, 255, 0.05);
|
|
18
|
+
--slider-surface-active: rgba(255, 255, 255, 0.08);
|
|
19
|
+
--slider-rim: rgba(255, 255, 255, 0.06);
|
|
20
|
+
|
|
21
|
+
/* Filled track (left portion) */
|
|
22
|
+
--slider-track: rgba(255, 255, 255, 0.11);
|
|
23
|
+
--slider-track-active: rgba(255, 255, 255, 0.18);
|
|
24
|
+
/* ButtonRow / pointer-down on track-like controls */
|
|
25
|
+
--slider-track-pressed: rgba(255, 255, 255, 0.26);
|
|
26
|
+
|
|
27
|
+
/* Thumb */
|
|
28
|
+
--slider-thumb: rgba(255, 255, 255, 0.7);
|
|
29
|
+
--slider-thumb-dragging: #ffffff;
|
|
30
|
+
|
|
31
|
+
/* Typography */
|
|
32
|
+
--slider-text-muted: rgba(255, 255, 255, 0.7);
|
|
33
|
+
--slider-text: #ffffff;
|
|
34
|
+
/*
|
|
35
|
+
* UI font for Panel, rows, and portaled UI (popover content inherits from :root,
|
|
36
|
+
* not from Panel — without a default, `inherit` resolves to the browser body font).
|
|
37
|
+
* Override anytime: html { --aporia-font-family: 'Inter', system-ui, sans-serif; }
|
|
38
|
+
*/
|
|
39
|
+
--aporia-font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
|
40
|
+
'Helvetica Neue', Arial, sans-serif;
|
|
41
|
+
|
|
42
|
+
/* Fixed UI rhythm (px): not tied to host `html { font-size: … }` / rem scaling). */
|
|
43
|
+
--aporia-ui-font-size: 14px;
|
|
44
|
+
--aporia-ui-line-height: 1.25;
|
|
45
|
+
|
|
46
|
+
/* Default panel width cap (matches the package demo). Override per app if needed. */
|
|
47
|
+
--aporia-panel-max-width: 360px;
|
|
48
|
+
|
|
49
|
+
/* Ticks (base color × layer opacity ≈ dark appearance) */
|
|
50
|
+
--slider-tick: rgba(255, 255, 255, 0.32);
|
|
51
|
+
--slider-tick-layer-opacity: 0.3;
|
|
52
|
+
|
|
53
|
+
/* Thumb opacity when row not hovered */
|
|
54
|
+
--slider-thumb-idle-opacity: 0;
|
|
55
|
+
|
|
56
|
+
/* Value field selection (same in both themes per spec) */
|
|
57
|
+
--slider-value-selection-bg: #ffffff;
|
|
58
|
+
--slider-value-selection-fg: #000000;
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
* Toggle inner thumb: must match how the *row* reads, but stay opaque — the ON
|
|
62
|
+
* track is solid white; semi-transparent --slider-surface would wash out and
|
|
63
|
+
* hide the thumb. These ≈ 5% / 8% white on black, same as the row visually.
|
|
64
|
+
*/
|
|
65
|
+
--toggle-thumb-row-bg: #0d0d0d;
|
|
66
|
+
--toggle-thumb-row-bg-hover: #141414;
|
|
67
|
+
|
|
68
|
+
/*
|
|
69
|
+
* Swatch popover: opaque fill so the panel reads on #000 (rows use translucent rgba).
|
|
70
|
+
* #0a0a0a matches Figma design spec.
|
|
71
|
+
*/
|
|
72
|
+
--swatch-popover-surface: #141414;
|
|
73
|
+
--swatch-popover-bg: #0a0a0a;
|
|
74
|
+
--swatch-popover-rim: rgba(255, 255, 255, 0.12);
|
|
75
|
+
|
|
76
|
+
/* Shift+D debug overlays */
|
|
77
|
+
--slider-debug-label-tint: rgba(255, 0, 160, 0.18);
|
|
78
|
+
--slider-debug-value-tint: rgba(255, 200, 0, 0.2);
|
|
79
|
+
--slider-debug-dom-label: rgba(0, 255, 140, 0.9);
|
|
80
|
+
--slider-debug-dom-value: rgba(80, 180, 255, 0.95);
|
|
81
|
+
--slider-debug-dom-shadow: rgba(0, 0, 0, 0.35);
|
|
82
|
+
}
|
|
1
83
|
/* Shell for grouped controls: solid black card, generous radius, inset padding. */
|
|
2
84
|
|
|
3
85
|
.aporiaPanel {
|
|
4
86
|
box-sizing: border-box;
|
|
5
87
|
width: 100%;
|
|
88
|
+
max-width: min(var(--aporia-panel-max-width), 100%);
|
|
6
89
|
min-width: 0;
|
|
90
|
+
/* Hug content: avoid stretching to fill a flex/grid parent’s unused vertical space. */
|
|
91
|
+
flex: 0 0 auto;
|
|
92
|
+
height: auto;
|
|
93
|
+
min-height: 0;
|
|
94
|
+
max-height: none;
|
|
95
|
+
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
|
+
color: var(--slider-text);
|
|
99
|
+
color-scheme: dark;
|
|
7
100
|
background-color: #000000;
|
|
8
101
|
border-radius: 24px;
|
|
9
102
|
padding: 16px;
|
|
@@ -15,6 +108,7 @@
|
|
|
15
108
|
0 6px 14px 0 rgba(0, 0, 0, 0.09);
|
|
16
109
|
display: flex;
|
|
17
110
|
flex-direction: column;
|
|
111
|
+
gap: 8px;
|
|
18
112
|
align-items: stretch;
|
|
19
113
|
justify-content: flex-start;
|
|
20
114
|
align-content: flex-start;
|
|
@@ -22,7 +116,8 @@
|
|
|
22
116
|
.category {
|
|
23
117
|
display: flex;
|
|
24
118
|
flex-direction: column;
|
|
25
|
-
|
|
119
|
+
/* Keep in sync with CATEGORY_STACK_GAP_PX in Category.tsx (motion cancels this when collapsed). */
|
|
120
|
+
gap: 8px;
|
|
26
121
|
min-width: 0;
|
|
27
122
|
}
|
|
28
123
|
|
|
@@ -134,6 +229,7 @@
|
|
|
134
229
|
margin: 0;
|
|
135
230
|
flex: 1;
|
|
136
231
|
min-width: 0;
|
|
232
|
+
font-family: var(--aporia-font-family);
|
|
137
233
|
font-size: 12px;
|
|
138
234
|
font-weight: 500;
|
|
139
235
|
letter-spacing: 0.08em;
|
|
@@ -145,15 +241,17 @@
|
|
|
145
241
|
|
|
146
242
|
.categoryBody {
|
|
147
243
|
min-width: 0;
|
|
148
|
-
padding-bottom: 4px;
|
|
149
244
|
}
|
|
150
245
|
|
|
151
|
-
/*
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
246
|
+
/* Padding lives inside the height animation so it never springs on its own (8px + Panel gap = 16px between categories). */
|
|
247
|
+
.categoryBodyInner {
|
|
248
|
+
min-width: 0;
|
|
249
|
+
padding-bottom: 8px;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/* Last category among siblings: no extra bottom inset (panel padding handles the card edge). */
|
|
253
|
+
.category:not(:has(~ .category)) .categoryBodyInner {
|
|
254
|
+
padding-bottom: 0;
|
|
157
255
|
}
|
|
158
256
|
|
|
159
257
|
.category[data-disabled="true"] .categoryBody {
|
|
@@ -380,6 +478,7 @@
|
|
|
380
478
|
position: absolute;
|
|
381
479
|
inset: 0;
|
|
382
480
|
right: auto;
|
|
481
|
+
z-index: 0;
|
|
383
482
|
background: var(--slider-track);
|
|
384
483
|
border-radius: 12px;
|
|
385
484
|
pointer-events: none;
|
|
@@ -562,6 +661,8 @@
|
|
|
562
661
|
flex-direction: column;
|
|
563
662
|
width: 190px;
|
|
564
663
|
box-sizing: border-box;
|
|
664
|
+
color-scheme: dark;
|
|
665
|
+
font-family: var(--aporia-font-family, inherit);
|
|
565
666
|
background: rgba(10, 10, 10, 0.8);
|
|
566
667
|
backdrop-filter: blur(20px);
|
|
567
668
|
border: 0.5px solid rgba(255, 255, 255, 0.06);
|
|
@@ -655,10 +756,6 @@
|
|
|
655
756
|
}
|
|
656
757
|
|
|
657
758
|
/* Hex value - uses ValueInput component */
|
|
658
|
-
.colorPickerHex {
|
|
659
|
-
font-family: 'SF Compact Rounded', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
660
|
-
}
|
|
661
|
-
|
|
662
759
|
.colorPickerHex .valueInputField {
|
|
663
760
|
width: 72px;
|
|
664
761
|
}
|
|
@@ -667,7 +764,6 @@
|
|
|
667
764
|
display: flex;
|
|
668
765
|
align-items: center;
|
|
669
766
|
gap: 10px;
|
|
670
|
-
font-family: 'SF Compact Rounded', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
671
767
|
font-size: 14px;
|
|
672
768
|
line-height: normal;
|
|
673
769
|
letter-spacing: 0.28px;
|
|
@@ -727,7 +823,6 @@
|
|
|
727
823
|
border-radius: 9px;
|
|
728
824
|
background: transparent;
|
|
729
825
|
color: rgba(255, 255, 255, 0.7);
|
|
730
|
-
font-family: 'SF Compact Rounded', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
731
826
|
font-size: 14px;
|
|
732
827
|
line-height: normal;
|
|
733
828
|
letter-spacing: 0.28px;
|
|
@@ -772,6 +867,8 @@
|
|
|
772
867
|
.swatchPopoverPopup {
|
|
773
868
|
position: relative;
|
|
774
869
|
z-index: 1;
|
|
870
|
+
color-scheme: dark;
|
|
871
|
+
font-family: var(--aporia-font-family, inherit);
|
|
775
872
|
min-width: 190px;
|
|
776
873
|
max-width: min(320px, calc(100vw - 24px));
|
|
777
874
|
padding: 0;
|
|
@@ -1043,9 +1140,14 @@
|
|
|
1043
1140
|
-moz-user-select: none;
|
|
1044
1141
|
-webkit-user-drag: none;
|
|
1045
1142
|
width: 100%;
|
|
1046
|
-
font:
|
|
1143
|
+
font-family: var(--aporia-font-family);
|
|
1144
|
+
font-size: var(--aporia-ui-font-size);
|
|
1145
|
+
font-weight: 400;
|
|
1146
|
+
font-style: normal;
|
|
1147
|
+
line-height: var(--aporia-ui-line-height);
|
|
1148
|
+
letter-spacing: normal;
|
|
1047
1149
|
text-align: left;
|
|
1048
|
-
color:
|
|
1150
|
+
color: var(--slider-text-muted);
|
|
1049
1151
|
}
|
|
1050
1152
|
|
|
1051
1153
|
.toggleCard:hover {
|
|
@@ -1135,11 +1237,263 @@
|
|
|
1135
1237
|
.toggleCard[data-on='true'] .toggleSwitch__thumb {
|
|
1136
1238
|
transform: translateX(6px);
|
|
1137
1239
|
}
|
|
1240
|
+
/* Trigger: same geometry as SliderRow; card fill matches .sliderCard (--slider-surface). */
|
|
1241
|
+
|
|
1242
|
+
.selectRowWrap {
|
|
1243
|
+
width: 100%;
|
|
1244
|
+
max-width: 100%;
|
|
1245
|
+
min-width: 0;
|
|
1246
|
+
position: relative;
|
|
1247
|
+
overflow: visible;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
.selectRowWrap[data-disabled="true"] {
|
|
1251
|
+
opacity: 0.45;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
.selectRowWrap[data-disabled="true"] .selectCard {
|
|
1255
|
+
pointer-events: none;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
.selectCard {
|
|
1259
|
+
position: relative;
|
|
1260
|
+
width: 100%;
|
|
1261
|
+
height: 37px;
|
|
1262
|
+
margin: 0;
|
|
1263
|
+
border: none;
|
|
1264
|
+
border-radius: 12px;
|
|
1265
|
+
background: var(--slider-surface);
|
|
1266
|
+
box-shadow: inset 0 0 0 0.5px var(--slider-rim);
|
|
1267
|
+
overflow: hidden;
|
|
1268
|
+
transition: background-color 0.2s ease-out;
|
|
1269
|
+
cursor: pointer;
|
|
1270
|
+
display: flex;
|
|
1271
|
+
align-items: center;
|
|
1272
|
+
padding: 10px 12px;
|
|
1273
|
+
box-sizing: border-box;
|
|
1274
|
+
font-family: var(--aporia-font-family);
|
|
1275
|
+
font-size: var(--aporia-ui-font-size);
|
|
1276
|
+
font-weight: 400;
|
|
1277
|
+
font-style: normal;
|
|
1278
|
+
line-height: var(--aporia-ui-line-height);
|
|
1279
|
+
letter-spacing: normal;
|
|
1280
|
+
text-align: left;
|
|
1281
|
+
color: var(--slider-text-muted);
|
|
1282
|
+
user-select: none;
|
|
1283
|
+
-webkit-user-select: none;
|
|
1284
|
+
-moz-user-select: none;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
.selectCard:hover:not(:disabled) {
|
|
1288
|
+
background: var(--slider-surface-active);
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
.selectCard:focus {
|
|
1292
|
+
outline: none;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
.selectCard:focus-visible {
|
|
1296
|
+
outline: 2px solid var(--slider-text-muted);
|
|
1297
|
+
outline-offset: 2px;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
.selectCard[data-popup-open="true"] {
|
|
1301
|
+
background: var(--slider-surface-active);
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
.selectCard:active:not(:disabled) {
|
|
1305
|
+
background: var(--slider-surface-active);
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
.selectLabel {
|
|
1309
|
+
position: relative;
|
|
1310
|
+
font-size: 14px;
|
|
1311
|
+
font-weight: 400;
|
|
1312
|
+
color: var(--slider-text-muted);
|
|
1313
|
+
letter-spacing: 0.28px;
|
|
1314
|
+
flex: 1;
|
|
1315
|
+
min-width: 0;
|
|
1316
|
+
z-index: 2;
|
|
1317
|
+
pointer-events: none;
|
|
1318
|
+
transition: color 0.2s ease-out;
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
.selectCard:hover:not(:disabled) .selectLabel,
|
|
1322
|
+
.selectCard[data-popup-open="true"] .selectLabel {
|
|
1323
|
+
color: var(--slider-text);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
.selectValueZone {
|
|
1327
|
+
position: absolute;
|
|
1328
|
+
top: 0;
|
|
1329
|
+
right: 0;
|
|
1330
|
+
height: 100%;
|
|
1331
|
+
z-index: 3;
|
|
1332
|
+
display: flex;
|
|
1333
|
+
align-items: center;
|
|
1334
|
+
justify-content: flex-end;
|
|
1335
|
+
gap: 6px;
|
|
1336
|
+
padding-right: 12px;
|
|
1337
|
+
min-width: 72px;
|
|
1338
|
+
max-width: 50%;
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
.selectValue {
|
|
1342
|
+
font-size: 14px;
|
|
1343
|
+
font-weight: 400;
|
|
1344
|
+
letter-spacing: 0.28px;
|
|
1345
|
+
color: var(--slider-text);
|
|
1346
|
+
white-space: nowrap;
|
|
1347
|
+
overflow: hidden;
|
|
1348
|
+
text-overflow: ellipsis;
|
|
1349
|
+
min-width: 0;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
.selectValue[data-placeholder] {
|
|
1353
|
+
color: var(--slider-text-muted);
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
.selectIcon {
|
|
1357
|
+
display: flex;
|
|
1358
|
+
flex-shrink: 0;
|
|
1359
|
+
color: var(--slider-text-muted);
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
.selectCard:hover:not(:disabled) .selectIcon,
|
|
1363
|
+
.selectCard[data-popup-open="true"] .selectIcon {
|
|
1364
|
+
color: var(--slider-text-muted);
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
.selectChevronSvg {
|
|
1368
|
+
display: block;
|
|
1369
|
+
transition: transform 0.2s ease-out;
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
/* Flip with React `menuOpen` (onOpenChange) so it tracks open immediately, not only after Base UI’s popup-open paint. */
|
|
1373
|
+
.selectCard[data-menu-open="true"] .selectChevronSvg {
|
|
1374
|
+
transform: rotate(180deg);
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
.selectPortal {
|
|
1378
|
+
position: relative;
|
|
1379
|
+
z-index: 200000;
|
|
1380
|
+
isolation: isolate;
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
.selectPositioner {
|
|
1384
|
+
z-index: 0;
|
|
1385
|
+
box-sizing: border-box;
|
|
1386
|
+
/* At least as wide as the row — set inline on portal as --select-anchor-width */
|
|
1387
|
+
min-width: var(--select-anchor-width, 0px);
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
/* Base UI scroll nudge controls (▲ / ▼) — hide even if present (siblings of popup in the portal). */
|
|
1391
|
+
.selectPortal [data-direction="up"],
|
|
1392
|
+
.selectPortal [data-direction="down"],
|
|
1393
|
+
.selectPositioner [data-direction="up"],
|
|
1394
|
+
.selectPositioner [data-direction="down"] {
|
|
1395
|
+
display: none !important;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
.selectPopup {
|
|
1399
|
+
box-sizing: border-box;
|
|
1400
|
+
width: 100%;
|
|
1401
|
+
min-width: 0;
|
|
1402
|
+
color-scheme: dark;
|
|
1403
|
+
font-family: var(--aporia-font-family, inherit);
|
|
1404
|
+
max-width: min(320px, calc(100vw - 24px));
|
|
1405
|
+
padding: 4px;
|
|
1406
|
+
border-radius: 12px;
|
|
1407
|
+
background: var(--swatch-popover-bg);
|
|
1408
|
+
box-shadow: inset 0 0 0 0.5px var(--swatch-popover-rim);
|
|
1409
|
+
color: var(--slider-text);
|
|
1410
|
+
outline: none;
|
|
1411
|
+
/* Popover-style motion; anchor to trailing edge (align end / SwatchPopover). */
|
|
1412
|
+
transform-origin: top right;
|
|
1413
|
+
opacity: 1;
|
|
1414
|
+
transform: translateY(0) scale(1);
|
|
1415
|
+
transition:
|
|
1416
|
+
opacity 0.2s ease-out,
|
|
1417
|
+
transform 0.22s cubic-bezier(0.16, 1, 0.3, 1);
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
.selectPopup[data-starting-style],
|
|
1421
|
+
.selectPopup[data-ending-style] {
|
|
1422
|
+
opacity: 0;
|
|
1423
|
+
transform: translateY(-6px) scale(0.97);
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
.selectList {
|
|
1427
|
+
display: flex;
|
|
1428
|
+
flex-direction: column;
|
|
1429
|
+
gap: 0;
|
|
1430
|
+
max-height: min(280px, 45vh);
|
|
1431
|
+
overflow-y: auto;
|
|
1432
|
+
padding: 0;
|
|
1433
|
+
min-width: 0;
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
.selectItem {
|
|
1437
|
+
position: relative;
|
|
1438
|
+
margin: 0;
|
|
1439
|
+
/* Match SliderRow card: 10px vertical padding + ~17px line = 37px (line-height caps text box). */
|
|
1440
|
+
height: 37px;
|
|
1441
|
+
box-sizing: border-box;
|
|
1442
|
+
padding: 10px 8px;
|
|
1443
|
+
border: none;
|
|
1444
|
+
border-radius: 8px;
|
|
1445
|
+
background: transparent;
|
|
1446
|
+
font-family: var(--aporia-font-family);
|
|
1447
|
+
font-size: var(--aporia-ui-font-size);
|
|
1448
|
+
font-weight: 400;
|
|
1449
|
+
font-style: normal;
|
|
1450
|
+
line-height: 17px;
|
|
1451
|
+
letter-spacing: 0.02em;
|
|
1452
|
+
color: rgba(255, 255, 255, 0.7);
|
|
1453
|
+
cursor: pointer;
|
|
1454
|
+
text-align: left;
|
|
1455
|
+
display: flex;
|
|
1456
|
+
align-items: center;
|
|
1457
|
+
width: 100%;
|
|
1458
|
+
transition:
|
|
1459
|
+
background-color 0.15s ease-out,
|
|
1460
|
+
color 0.15s ease-out;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
/* Selected / highlighted visuals: see `aporia-surfaces.css` (host `[role=option]` overrides). */
|
|
1464
|
+
|
|
1465
|
+
.selectItem[data-disabled] {
|
|
1466
|
+
opacity: 0.45;
|
|
1467
|
+
cursor: default;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
.selectItemText {
|
|
1471
|
+
flex: 1;
|
|
1472
|
+
min-width: 0;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1476
|
+
.selectPopup {
|
|
1477
|
+
transition-duration: 0.1s;
|
|
1478
|
+
transition-property: opacity;
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
.selectPopup[data-starting-style],
|
|
1482
|
+
.selectPopup[data-ending-style] {
|
|
1483
|
+
transform: none;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
.selectChevronSvg {
|
|
1487
|
+
transition: none;
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1138
1490
|
/* Container - exact Figma specs */
|
|
1139
1491
|
.gradientPicker {
|
|
1140
1492
|
display: flex;
|
|
1141
1493
|
flex-direction: column;
|
|
1142
1494
|
width: 190px;
|
|
1495
|
+
color-scheme: dark;
|
|
1496
|
+
font-family: var(--aporia-font-family, inherit);
|
|
1143
1497
|
background: #0a0a0a;
|
|
1144
1498
|
border: 1px solid rgba(255, 255, 255, 0.06);
|
|
1145
1499
|
border-radius: 12px;
|
|
@@ -1354,3 +1708,57 @@
|
|
|
1354
1708
|
outline: 2px solid var(--slider-text-muted);
|
|
1355
1709
|
outline-offset: 2px;
|
|
1356
1710
|
}
|
|
1711
|
+
/**
|
|
1712
|
+
* Host isolation: consumer apps often scale `rem`, reset `button`, or style generic
|
|
1713
|
+
* `[role="option"]` / `[type="range"]`. These rules sit after component CSS and restore
|
|
1714
|
+
* Aporia’s intended metrics on the panel and on portaled surfaces (not under `.aporiaPanel`).
|
|
1715
|
+
*/
|
|
1716
|
+
|
|
1717
|
+
.aporiaPanel,
|
|
1718
|
+
.swatchPopoverPopup,
|
|
1719
|
+
.selectPopup,
|
|
1720
|
+
.gradientPicker,
|
|
1721
|
+
.colorPicker {
|
|
1722
|
+
font-family: var(--aporia-font-family);
|
|
1723
|
+
font-size: var(--aporia-ui-font-size);
|
|
1724
|
+
font-weight: 400;
|
|
1725
|
+
font-style: normal;
|
|
1726
|
+
line-height: var(--aporia-ui-line-height);
|
|
1727
|
+
letter-spacing: normal;
|
|
1728
|
+
-webkit-font-smoothing: antialiased;
|
|
1729
|
+
-moz-osx-font-smoothing: grayscale;
|
|
1730
|
+
font-synthesis: none;
|
|
1731
|
+
text-rendering: optimizeLegibility;
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
/*
|
|
1735
|
+
* Do not style `input[type=range]` pseudo-elements here. WebKit paints the range control
|
|
1736
|
+
* above sibling divs (`.sliderTrack`, thumb); forcing `-webkit-appearance`/thumb sizing
|
|
1737
|
+
* hid the custom progress fill and card chrome in real apps (Tailwind + host resets).
|
|
1738
|
+
*/
|
|
1739
|
+
|
|
1740
|
+
/* Swatch triggers keep inline `background` / gradients vs global `button { background: none }`. */
|
|
1741
|
+
.aporiaPanel button.gradientSwatchBtn,
|
|
1742
|
+
.aporiaPanel button.colorSwatchBtn {
|
|
1743
|
+
appearance: none;
|
|
1744
|
+
-webkit-appearance: none;
|
|
1745
|
+
margin: 0;
|
|
1746
|
+
box-sizing: border-box;
|
|
1747
|
+
border-style: solid;
|
|
1748
|
+
border-width: 0;
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
/*
|
|
1752
|
+
* Select listbox: duplicate Base UI’s selected / highlighted visuals with higher
|
|
1753
|
+
* specificity than generic `[role="option"]` rules from host design systems.
|
|
1754
|
+
*/
|
|
1755
|
+
.selectPopup .selectList > .selectItem[role='option'][data-highlighted] {
|
|
1756
|
+
background-color: #141414 !important;
|
|
1757
|
+
color: #ffffff !important;
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
.selectPopup .selectList > .selectItem[role='option'][data-selected]:not([data-highlighted]),
|
|
1761
|
+
.selectPopup .selectList > .selectItem[role='option'][aria-selected='true']:not([data-highlighted]) {
|
|
1762
|
+
background-color: transparent !important;
|
|
1763
|
+
color: #ffffff !important;
|
|
1764
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export { ColorPicker } from './components/ColorPicker';
|
|
|
11
11
|
export type { ColorPickerProps } from './components/ColorPicker';
|
|
12
12
|
export { ToggleRow } from './components/ToggleRow';
|
|
13
13
|
export type { ToggleRowProps } from './components/ToggleRow';
|
|
14
|
+
export { SelectRow } from './components/SelectRow';
|
|
15
|
+
export type { SelectRowProps, SelectRowOption } from './components/SelectRow';
|
|
14
16
|
export { GradientRow } from './components/GradientRow';
|
|
15
17
|
export type { GradientRowProps } from './components/GradientRow';
|
|
16
18
|
export { GradientPicker, stopsToGradient, parseGradient, DEFAULT_GRADIENT_STOPS } from './components/GradientPicker';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,OAAO,aAAa,CAAA;AAGpB,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5D,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAEpD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAA;AAE1E,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAE5D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAEhE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAE5D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7E,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAEhE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACpH,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEpF,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,YAAY,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAA;AAG5E,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AACzD,YAAY,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAE5C,OAAO,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,MAAM,iCAAiC,CAAA;AAG1G,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAE7D,0FAA0F;AAC1F,OAAO,uBAAuB,CAAA"}
|