@designa8/vibedesign-stripe-deepseek-85ea 0.2.4 → 0.3.0
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 +1 -1
- package/dist/index.cjs +909 -852
- package/dist/index.js +911 -854
- package/dist/styles.css +5 -0
- package/package.json +6 -1
- package/src/atoms/Icon/icons.data.ts +1 -0
- package/src/atoms/Panel/Panel.tsx +102 -0
- package/src/atoms/Panel/index.ts +2 -0
- package/src/atoms/Panel/preview.tsx +196 -0
- package/src/index.ts +1 -0
package/dist/styles.css
CHANGED
|
@@ -3804,6 +3804,11 @@
|
|
|
3804
3804
|
width: calc(var(--spacing) * 64);
|
|
3805
3805
|
}
|
|
3806
3806
|
}
|
|
3807
|
+
.lg\:grid-cols-2 {
|
|
3808
|
+
@media (width >= 1024px) {
|
|
3809
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3807
3812
|
.lg\:grid-cols-4 {
|
|
3808
3813
|
@media (width >= 1024px) {
|
|
3809
3814
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@designa8/vibedesign-stripe-deepseek-85ea",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Complete design system \"My Project stripe-deepseek\" generated by Atoms Design.",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -324,6 +324,11 @@
|
|
|
324
324
|
"kind": "Molecule",
|
|
325
325
|
"description": null
|
|
326
326
|
},
|
|
327
|
+
{
|
|
328
|
+
"name": "Panel",
|
|
329
|
+
"kind": "Molecule",
|
|
330
|
+
"description": null
|
|
331
|
+
},
|
|
327
332
|
{
|
|
328
333
|
"name": "PaymentRoutingCanvas",
|
|
329
334
|
"kind": "Organism",
|
|
@@ -94,6 +94,7 @@ export const ICON_REGISTRY = {
|
|
|
94
94
|
"euro": { viewBox: "0 0 24 24", nodes: [{ tag: "path", d: "M4 10h12" }, { tag: "path", d: "M4 14h9" }, { tag: "path", d: "M19 6a7.7 7.7 0 0 0-5.2-2A7.9 7.9 0 0 0 6 12c0 4.4 3.5 8 7.8 8 2 0 3.8-.8 5.2-2" }] },
|
|
95
95
|
"square": { viewBox: "0 0 24 24", nodes: [{ tag: "rect", width: "18", height: "18", x: "3", y: "3", rx: "2" }] },
|
|
96
96
|
"eye-off": { viewBox: "0 0 24 24", nodes: [{ tag: "path", d: "M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49" }, { tag: "path", d: "M14.084 14.158a3 3 0 0 1-4.242-4.242" }, { tag: "path", d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143" }, { tag: "path", d: "m2 2 20 20" }] },
|
|
97
|
+
"chart-column": { viewBox: "0 0 24 24", nodes: [{ tag: "path", d: "M3 3v16a2 2 0 0 0 2 2h16" }, { tag: "path", d: "M18 17V9" }, { tag: "path", d: "M13 17V5" }, { tag: "path", d: "M8 17v-3" }] },
|
|
97
98
|
} as const;
|
|
98
99
|
|
|
99
100
|
export type IconName = keyof typeof ICON_REGISTRY;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
const cn = (...values: Array<string | false | null | undefined>) =>
|
|
4
|
+
values.filter(Boolean).join(" ");
|
|
5
|
+
|
|
6
|
+
export interface PanelProps
|
|
7
|
+
extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
|
|
8
|
+
/** The panel's heading. Rendered as an `<h2>` by default. */
|
|
9
|
+
title: React.ReactNode;
|
|
10
|
+
/**
|
|
11
|
+
* Right-aligned caption in the header — a quiet count or timestamp such as
|
|
12
|
+
* "3 accounts" or "Updated 9:41". Never emphasised, never a badge.
|
|
13
|
+
*/
|
|
14
|
+
meta?: React.ReactNode;
|
|
15
|
+
/**
|
|
16
|
+
* Controls pinned to the right of the header, after the meta caption — a
|
|
17
|
+
* segmented range toggle, an icon button, a link. The panel adds no chrome
|
|
18
|
+
* around them.
|
|
19
|
+
*/
|
|
20
|
+
actions?: React.ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* Heading rank, so the panel nests correctly under the page's `<h1>`.
|
|
23
|
+
* `2` renders `<h2>` (default), `3` renders `<h3>`.
|
|
24
|
+
*/
|
|
25
|
+
headingLevel?: 2 | 3;
|
|
26
|
+
/** Panel body. Laid out as a column with a `md` gap between children. */
|
|
27
|
+
children?: React.ReactNode;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A titled section surface: one calm card that carries a heading, an optional
|
|
32
|
+
* right-aligned caption, an optional actions slot, and a body the caller fills
|
|
33
|
+
* with rows, charts, or tasks.
|
|
34
|
+
*
|
|
35
|
+
* The surface owns the only stroke (one hairline), the radius, and the soft card
|
|
36
|
+
* shadow, and it clips whatever the caller drops inside so a full-bleed child
|
|
37
|
+
* cannot poke through the corners. It is a container, not a control: no hover
|
|
38
|
+
* lift, no press scale, no focus ring, no cursor change — every interactive
|
|
39
|
+
* affordance belongs to a child that can actually be pressed.
|
|
40
|
+
*
|
|
41
|
+
* Every colour, radius, spacing step, and type role is a token utility, so the
|
|
42
|
+
* whole surface repaints under `[data-theme="dark"]`.
|
|
43
|
+
*/
|
|
44
|
+
export const Panel = React.forwardRef<HTMLElement, PanelProps>(
|
|
45
|
+
(
|
|
46
|
+
{
|
|
47
|
+
title,
|
|
48
|
+
meta,
|
|
49
|
+
actions,
|
|
50
|
+
headingLevel = 2,
|
|
51
|
+
id,
|
|
52
|
+
children,
|
|
53
|
+
className,
|
|
54
|
+
...rest
|
|
55
|
+
},
|
|
56
|
+
ref,
|
|
57
|
+
) => {
|
|
58
|
+
const generatedId = React.useId();
|
|
59
|
+
const baseId = id ?? generatedId;
|
|
60
|
+
const titleId = `${baseId}-title`;
|
|
61
|
+
const Heading = (headingLevel === 3 ? "h3" : "h2") as "h2" | "h3";
|
|
62
|
+
const hasTrailing = Boolean(meta) || Boolean(actions);
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<section
|
|
66
|
+
ref={ref}
|
|
67
|
+
id={id}
|
|
68
|
+
aria-labelledby={titleId}
|
|
69
|
+
className={cn(
|
|
70
|
+
"w-full min-w-0 overflow-hidden rounded-xl border border-hairline",
|
|
71
|
+
"bg-surface p-xl shadow-card",
|
|
72
|
+
className,
|
|
73
|
+
)}
|
|
74
|
+
{...rest}
|
|
75
|
+
>
|
|
76
|
+
<div className="mb-lg flex min-w-0 flex-wrap items-center justify-between gap-x-md gap-y-sm">
|
|
77
|
+
<Heading
|
|
78
|
+
id={titleId}
|
|
79
|
+
className="min-w-0 truncate text-heading-sm text-ink"
|
|
80
|
+
>
|
|
81
|
+
{title}
|
|
82
|
+
</Heading>
|
|
83
|
+
|
|
84
|
+
{hasTrailing ? (
|
|
85
|
+
<div className="ml-auto flex shrink-0 items-center gap-md">
|
|
86
|
+
{meta ? (
|
|
87
|
+
<span className="whitespace-nowrap text-caption text-muted">
|
|
88
|
+
{meta}
|
|
89
|
+
</span>
|
|
90
|
+
) : null}
|
|
91
|
+
{actions}
|
|
92
|
+
</div>
|
|
93
|
+
) : null}
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<div className="flex min-w-0 flex-col gap-md">{children}</div>
|
|
97
|
+
</section>
|
|
98
|
+
);
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
Panel.displayName = "Panel";
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Panel } from "./Panel";
|
|
3
|
+
import { Button } from "../Button";
|
|
4
|
+
import { ButtonGroup } from "../ButtonGroup";
|
|
5
|
+
import { Badge } from "../Badge";
|
|
6
|
+
import { Checkbox } from "../Checkbox";
|
|
7
|
+
import { Icon } from "../Icon";
|
|
8
|
+
import { CashFlowChart } from "../CashFlowChart";
|
|
9
|
+
|
|
10
|
+
const accounts = [
|
|
11
|
+
{
|
|
12
|
+
icon: "wallet",
|
|
13
|
+
name: "Atlas Commerce",
|
|
14
|
+
kind: "Business account",
|
|
15
|
+
amount: "$24,800.00",
|
|
16
|
+
delta: "+6.2%",
|
|
17
|
+
tone: "success" as const,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
icon: "layers",
|
|
21
|
+
name: "Nimbus Pay",
|
|
22
|
+
kind: "Payment account",
|
|
23
|
+
amount: "$8,420.50",
|
|
24
|
+
delta: "−2.4%",
|
|
25
|
+
tone: "error" as const,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
icon: "building",
|
|
29
|
+
name: "Vertex Bank",
|
|
30
|
+
kind: "Settlement account",
|
|
31
|
+
amount: "$102,309.00",
|
|
32
|
+
delta: "+3.8%",
|
|
33
|
+
tone: "success" as const,
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const cashFlow = [
|
|
38
|
+
{ label: "Jan", moneyIn: 61000, moneyOut: 42000 },
|
|
39
|
+
{ label: "Feb", moneyIn: 82000, moneyOut: 57000 },
|
|
40
|
+
{ label: "Mar", moneyIn: 74000, moneyOut: 51000 },
|
|
41
|
+
{ label: "Apr", moneyIn: 91000, moneyOut: 63000 },
|
|
42
|
+
{ label: "May", moneyIn: 113000, moneyOut: 71000 },
|
|
43
|
+
{ label: "Jun", moneyIn: 121000, moneyOut: 78000 },
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
const tasks = [
|
|
47
|
+
{ id: "payouts", label: "Review pending payouts", due: "Today" },
|
|
48
|
+
{ id: "confirm", label: "Confirm new account", due: "Jun 28" },
|
|
49
|
+
{ id: "routing", label: "Update routing rules", due: "Jun 30" },
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
export default function PanelPreview() {
|
|
53
|
+
const [range, setRange] = React.useState("3m");
|
|
54
|
+
const [checked, setChecked] = React.useState<Record<string, boolean>>({
|
|
55
|
+
payouts: false,
|
|
56
|
+
confirm: true,
|
|
57
|
+
routing: false,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const done = Object.values(checked).filter(Boolean).length;
|
|
61
|
+
const open = tasks.length - done;
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<div className="w-full max-w-5xl mx-auto p-lg">
|
|
65
|
+
<div className="grid grid-cols-1 gap-lg lg:grid-cols-2">
|
|
66
|
+
{/* Header with a caption, a segmented range toggle, and a list body. */}
|
|
67
|
+
<Panel
|
|
68
|
+
title="Accounts"
|
|
69
|
+
meta="3 accounts"
|
|
70
|
+
actions={
|
|
71
|
+
<div className="w-40">
|
|
72
|
+
<ButtonGroup
|
|
73
|
+
label="Accounts range"
|
|
74
|
+
size="sm"
|
|
75
|
+
value={range}
|
|
76
|
+
onValueChange={setRange}
|
|
77
|
+
options={[
|
|
78
|
+
{ value: "1m", label: "1M" },
|
|
79
|
+
{ value: "3m", label: "3M" },
|
|
80
|
+
{ value: "1y", label: "1Y" },
|
|
81
|
+
]}
|
|
82
|
+
/>
|
|
83
|
+
</div>
|
|
84
|
+
}
|
|
85
|
+
>
|
|
86
|
+
{accounts.map((account) => (
|
|
87
|
+
<div
|
|
88
|
+
key={account.name}
|
|
89
|
+
className="flex min-w-0 items-center justify-between gap-md rounded-lg border border-hairline bg-canvas px-md py-sm transition-colors duration-150 ease-out hover:border-hairline-strong hover:bg-surface-soft"
|
|
90
|
+
>
|
|
91
|
+
<div className="flex min-w-0 items-center gap-md">
|
|
92
|
+
<span className="flex size-10 shrink-0 items-center justify-center rounded-md bg-primary-subdued text-primary-on-subdued">
|
|
93
|
+
<Icon name={account.icon} size={18} />
|
|
94
|
+
</span>
|
|
95
|
+
<span className="flex min-w-0 flex-col">
|
|
96
|
+
<span className="truncate text-body-md text-ink">
|
|
97
|
+
{account.name}
|
|
98
|
+
</span>
|
|
99
|
+
<span className="truncate text-caption text-muted">
|
|
100
|
+
{account.kind}
|
|
101
|
+
</span>
|
|
102
|
+
</span>
|
|
103
|
+
</div>
|
|
104
|
+
<span className="flex shrink-0 items-center gap-sm">
|
|
105
|
+
<span className="text-body-tabular text-ink">
|
|
106
|
+
{account.amount}
|
|
107
|
+
</span>
|
|
108
|
+
<Badge
|
|
109
|
+
variant="soft"
|
|
110
|
+
tone={account.tone}
|
|
111
|
+
size="sm"
|
|
112
|
+
showDot={false}
|
|
113
|
+
>
|
|
114
|
+
{account.delta}
|
|
115
|
+
</Badge>
|
|
116
|
+
</span>
|
|
117
|
+
</div>
|
|
118
|
+
))}
|
|
119
|
+
</Panel>
|
|
120
|
+
|
|
121
|
+
{/* Caption on the right, a data body with its own legend. */}
|
|
122
|
+
<Panel title="Cash flow" meta="Updated 9:41">
|
|
123
|
+
<CashFlowChart points={cashFlow} />
|
|
124
|
+
</Panel>
|
|
125
|
+
|
|
126
|
+
{/* Live checkbox body — the caption follows the checked count. */}
|
|
127
|
+
<Panel title="Tasks" meta={`${open} open`}>
|
|
128
|
+
{tasks.map((task) => (
|
|
129
|
+
<div
|
|
130
|
+
key={task.id}
|
|
131
|
+
className="flex min-w-0 items-center justify-between gap-md rounded-lg border border-hairline bg-canvas px-md py-xs transition-colors duration-150 ease-out hover:border-hairline-strong"
|
|
132
|
+
>
|
|
133
|
+
<Checkbox
|
|
134
|
+
chrome="bare"
|
|
135
|
+
size="sm"
|
|
136
|
+
label={task.label}
|
|
137
|
+
checked={checked[task.id]}
|
|
138
|
+
onChange={(next) =>
|
|
139
|
+
setChecked((prev) => ({ ...prev, [task.id]: next }))
|
|
140
|
+
}
|
|
141
|
+
/>
|
|
142
|
+
<Badge variant="soft" tone="neutral" size="sm" showDot={false}>
|
|
143
|
+
{task.due}
|
|
144
|
+
</Badge>
|
|
145
|
+
</div>
|
|
146
|
+
))}
|
|
147
|
+
</Panel>
|
|
148
|
+
|
|
149
|
+
{/* Empty body: muted centred copy and one quiet action. */}
|
|
150
|
+
<Panel title="Insights" headingLevel={3}>
|
|
151
|
+
<div className="flex flex-col items-center gap-md py-xxl text-center">
|
|
152
|
+
<span className="flex size-12 items-center justify-center rounded-lg bg-primary-subdued text-primary-on-subdued">
|
|
153
|
+
<Icon name="chart-column" size={20} />
|
|
154
|
+
</span>
|
|
155
|
+
<span className="flex flex-col gap-xs">
|
|
156
|
+
<span className="text-body-md text-ink">No insights yet</span>
|
|
157
|
+
<span className="text-caption text-muted">
|
|
158
|
+
Run an analysis to see trends and opportunities.
|
|
159
|
+
</span>
|
|
160
|
+
</span>
|
|
161
|
+
<Button variant="outline-brand" size="sm">
|
|
162
|
+
Run analysis
|
|
163
|
+
</Button>
|
|
164
|
+
</div>
|
|
165
|
+
</Panel>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
{/* Error body: the surface stays calm, the callout carries the tone. */}
|
|
169
|
+
<div className="mt-lg">
|
|
170
|
+
<Panel title="Data sync" meta="Last attempt 9:41" headingLevel={3}>
|
|
171
|
+
<div className="flex flex-col items-center gap-md rounded-lg bg-semantic-error-soft p-lg text-center">
|
|
172
|
+
<span className="flex size-10 items-center justify-center rounded-full bg-canvas text-semantic-error">
|
|
173
|
+
<Icon name="triangle" size={18} />
|
|
174
|
+
</span>
|
|
175
|
+
<span className="flex flex-col gap-xs">
|
|
176
|
+
<span className="text-body-md text-semantic-error">
|
|
177
|
+
Couldn’t load data
|
|
178
|
+
</span>
|
|
179
|
+
<span className="text-caption text-muted">
|
|
180
|
+
We weren’t able to fetch the latest information. Please try
|
|
181
|
+
again.
|
|
182
|
+
</span>
|
|
183
|
+
</span>
|
|
184
|
+
<Button
|
|
185
|
+
variant="outline-brand"
|
|
186
|
+
size="sm"
|
|
187
|
+
leadingIcon={<Icon name="refresh-cw" size={16} />}
|
|
188
|
+
>
|
|
189
|
+
Try again
|
|
190
|
+
</Button>
|
|
191
|
+
</div>
|
|
192
|
+
</Panel>
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
);
|
|
196
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -58,6 +58,7 @@ export * from "./atoms/NavigationMenuMobile";
|
|
|
58
58
|
export * from "./atoms/NodeConfigPanel";
|
|
59
59
|
export * from "./atoms/NotificationFeed";
|
|
60
60
|
export * from "./atoms/Pagination";
|
|
61
|
+
export * from "./atoms/Panel";
|
|
61
62
|
export * from "./atoms/PaymentRoutingCanvas";
|
|
62
63
|
export * from "./atoms/PricingTable";
|
|
63
64
|
export * from "./atoms/PricingTableDesktop";
|