Skip to content

Commit 9b485dc

Browse files
committed
test(proprietary): cover the usage meter and the policy-enforcement overlay
MeterBar's three states are the reason it exists, so each gets a story rather than leaving the bar's fill to carry the meaning alone. The overlay covers each progress case and the accent tones a policy can carry.
1 parent 47d2b83 commit 9b485dc

2 files changed

Lines changed: 143 additions & 0 deletions

File tree

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import type { Meta, StoryObj } from "@storybook/react-vite";
2+
import { MeterBar } from "@app/billing/MeterBar";
3+
4+
/**
5+
* Usage against a cap. The three states are the point: FULL is healthy,
6+
* WARNED is approaching the cap, DEGRADED is over it — and each maps to a
7+
* status tone rather than relying on the bar's fill to carry the meaning.
8+
*/
9+
const meta: Meta<typeof MeterBar> = {
10+
title: "Proprietary/Billing/MeterBar",
11+
component: MeterBar,
12+
parameters: { layout: "padded" },
13+
args: {
14+
barLabel: "Documents used this period",
15+
figure: "1,240",
16+
capSuffix: " of 5,000",
17+
},
18+
};
19+
export default meta;
20+
21+
type Story = StoryObj<typeof MeterBar>;
22+
23+
/** Comfortably inside the cap. */
24+
export const Full: Story = {
25+
args: { state: "FULL", pct: 25, statusLabel: "Active" },
26+
};
27+
28+
/** Approaching the cap. */
29+
export const Warned: Story = {
30+
args: {
31+
state: "WARNED",
32+
pct: 86,
33+
figure: "4,300",
34+
statusLabel: "Approaching limit",
35+
},
36+
};
37+
38+
/** Over the cap — processing is degraded until the period rolls or the cap
39+
* is raised. */
40+
export const Degraded: Story = {
41+
args: {
42+
state: "DEGRADED",
43+
pct: 100,
44+
figure: "5,000",
45+
statusLabel: "Limit reached",
46+
meta: "Resets on 1 September",
47+
},
48+
};
49+
50+
/** Nothing used yet. */
51+
export const Empty: Story = {
52+
args: { state: "FULL", pct: 0, figure: "0" },
53+
};
54+
55+
/** Figure only, no bar — for a plan with no cap to draw against. */
56+
export const NoBar: Story = {
57+
args: {
58+
state: "FULL",
59+
pct: 0,
60+
figure: "18,402",
61+
capSuffix: " this period",
62+
showBar: false,
63+
statusLabel: "Unlimited",
64+
},
65+
};
66+
67+
/** With supporting meta beneath. */
68+
export const WithMeta: Story = {
69+
args: {
70+
state: "WARNED",
71+
pct: 72,
72+
figure: "3,600",
73+
statusLabel: "Approaching limit",
74+
meta: "Averaging 240 documents a day",
75+
},
76+
};
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import type { Meta, StoryObj } from "@storybook/react-vite";
2+
import { PolicyEnforcingOverlay } from "@app/components/shared/PolicyEnforcingOverlay";
3+
4+
/**
5+
* Shown over a document while a policy runs against it. It renders into its
6+
* nearest positioned ancestor, so the stories supply one — the same thing the
7+
* viewer and the thumbnail cards do.
8+
*
9+
* `accentVar` exists so the spinner matches the enforcing policy's own badge
10+
* rather than a fixed blue; the stories cover the tones a policy can carry.
11+
*/
12+
const meta: Meta<typeof PolicyEnforcingOverlay> = {
13+
title: "Proprietary/Shared/PolicyEnforcingOverlay",
14+
component: PolicyEnforcingOverlay,
15+
parameters: { layout: "padded" },
16+
args: { enforcing: true },
17+
decorators: [
18+
(Story) => (
19+
<div
20+
style={{
21+
position: "relative",
22+
width: 420,
23+
height: 280,
24+
border: "1px solid var(--c-border)",
25+
borderRadius: 8,
26+
background: "var(--c-surface)",
27+
overflow: "hidden",
28+
}}
29+
>
30+
<div style={{ padding: "1rem", color: "var(--c-text-muted)" }}>
31+
Document content sits beneath the overlay.
32+
</div>
33+
<Story />
34+
</div>
35+
),
36+
],
37+
};
38+
export default meta;
39+
40+
type Story = StoryObj<typeof PolicyEnforcingOverlay>;
41+
42+
/** Running, with no step counts to report. */
43+
export const Indeterminate: Story = {};
44+
45+
/** Part-way through a run that reports progress. */
46+
export const WithProgress: Story = { args: { progress: 45 } };
47+
48+
/** Nearly done. */
49+
export const AlmostComplete: Story = { args: { progress: 92 } };
50+
51+
/** Dismissable — the × only appears when a handler is given. */
52+
export const Dismissable: Story = {
53+
args: { progress: 30, onDismiss: () => {} },
54+
};
55+
56+
/** Tinted to the enforcing policy's accent. */
57+
export const SecurityAccent: Story = {
58+
args: { progress: 60, accentVar: "var(--c-danger-solid)" },
59+
};
60+
61+
/** A different policy tone. */
62+
export const WarningAccent: Story = {
63+
args: { progress: 60, accentVar: "var(--c-warning-solid)" },
64+
};
65+
66+
/** Not enforcing — the overlay renders nothing, leaving the document clear. */
67+
export const NotEnforcing: Story = { args: { enforcing: false } };

0 commit comments

Comments
 (0)