@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/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.2.4",
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,2 @@
1
+ export { Panel } from "./Panel";
2
+ export type { PanelProps } from "./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&rsquo;t load data
178
+ </span>
179
+ <span className="text-caption text-muted">
180
+ We weren&rsquo;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";