Skip to content

Commit 73a6807

Browse files
authored
REFACTOR: Move warning banner into ui-components (#887)
1 parent 8efb3c3 commit 73a6807

File tree

8 files changed

+152
-51
lines changed

8 files changed

+152
-51
lines changed

biome.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@
8080
},
8181
"linter": {
8282
"enabled": true
83+
},
84+
"parser": {
85+
"cssModules": true
8386
}
8487
}
8588
}

packages/frontend/src/page/document_page.css

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,3 @@
1-
.warning-banner {
2-
display: flex;
3-
align-items: center;
4-
flex-wrap: wrap;
5-
gap: 0.75rem;
6-
background-color: var(--warning-bg, #fff3cd);
7-
border: 1px solid var(--warning-border, #ffc107);
8-
color: var(--warning-text, #856404);
9-
padding: 1rem 1.25rem;
10-
margin-bottom: 1rem;
11-
border-radius: 0.375rem;
12-
font-size: 0.9375rem;
13-
line-height: 1.5;
14-
}
15-
16-
.warning-banner > .lucide-icon {
17-
flex-shrink: 0;
18-
min-width: 20px;
19-
}
20-
21-
.warning-banner-content {
22-
flex: 1;
23-
min-width: 200px;
24-
}
25-
26-
.warning-banner .button {
27-
margin: 0;
28-
flex-shrink: 0;
29-
white-space: nowrap;
30-
}
31-
321
.document-head {
332
display: flex;
343
flex-direction: row;

packages/frontend/src/page/document_page.tsx

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { useNavigate, useParams } from "@solidjs/router";
33
import ChevronsRight from "lucide-solid/icons/chevrons-right";
44
import Maximize2 from "lucide-solid/icons/maximize-2";
55
import RotateCcw from "lucide-solid/icons/rotate-ccw";
6-
import TriangleAlert from "lucide-solid/icons/triangle-alert";
76
import {
87
createEffect,
98
createResource,
@@ -15,7 +14,13 @@ import {
1514
} from "solid-js";
1615
import invariant from "tiny-invariant";
1716

18-
import { Button, IconButton, InlineInput, ResizableHandle } from "catcolab-ui-components";
17+
import {
18+
Button,
19+
IconButton,
20+
InlineInput,
21+
ResizableHandle,
22+
WarningBanner,
23+
} from "catcolab-ui-components";
1924
import { getLiveAnalysis, type LiveAnalysisDoc } from "../analysis";
2025
import { AnalysisNotebookEditor } from "../analysis/analysis_editor";
2126
import { AnalysisInfo } from "../analysis/analysis_info";
@@ -262,22 +267,21 @@ export function DocumentPane(props: {
262267
return (
263268
<>
264269
<Show when={isDeleted()}>
265-
<div class="warning-banner">
266-
<TriangleAlert size={20} />
267-
<div class="warning-banner-content">
268-
<strong>Warning:</strong> This {props.doc.type} has been deleted and will
269-
not be listed in your documents.
270-
</div>
271-
<Button
272-
variant="utility"
273-
onClick={(e) => {
274-
e.preventDefault();
275-
handleRestore();
276-
}}
277-
>
278-
<RotateCcw size={16} /> Restore it
279-
</Button>
280-
</div>
270+
<WarningBanner
271+
actions={
272+
<Button
273+
variant="utility"
274+
onClick={(e) => {
275+
e.preventDefault();
276+
handleRestore();
277+
}}
278+
>
279+
<RotateCcw size={16} /> Restore it
280+
</Button>
281+
}
282+
>
283+
This {props.doc.type} has been deleted and will not be listed in your documents.
284+
</WarningBanner>
281285
</Show>
282286
<div class="notebook-container">
283287
<div class="document-head">

packages/ui-components/src/alert.stories.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from "storybook-solidjs-vite";
33
import { ErrorAlert, Note, Question, Warning } from "../src/alert";
44

55
const meta = {
6-
title: "Alert",
6+
title: "Messages/Alert",
77
} satisfies Meta<typeof Warning>;
88

99
export default meta;
@@ -26,7 +26,6 @@ export const Summary: Story = {
2626
</Question>
2727
</>
2828
),
29-
args: { title: "Alert" },
3029
// excluding from autodocs and dev seems to be the way to have this
3130
// component as the first thing in the docs and only there
3231
tags: ["!autodocs", "!dev"],

packages/ui-components/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ export * from "./resizable";
1414
export * from "./spinner";
1515
export * from "./text_input";
1616
export * from "./util/keyboard";
17+
export * from "./warning_banner";
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
.warningBanner {
2+
display: flex;
3+
align-items: center;
4+
flex-wrap: wrap;
5+
gap: 0.75rem;
6+
background-color: var(--warning-bg, #fff3cd);
7+
border: 1px solid var(--warning-border, #ffc107);
8+
color: var(--warning-text, #856404);
9+
padding: 1rem 1.25rem;
10+
margin-bottom: 1rem;
11+
border-radius: 0.375rem;
12+
font-size: 0.9375rem;
13+
line-height: 1.5;
14+
}
15+
16+
.warningBannerIcon {
17+
flex-shrink: 0;
18+
min-width: 20px;
19+
}
20+
21+
.warningBannerContent {
22+
flex: 1;
23+
min-width: 200px;
24+
}
25+
26+
.warningBannerActions :global(.button) {
27+
margin: 0;
28+
flex-shrink: 0;
29+
white-space: nowrap;
30+
}
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-solidjs-vite";
2+
3+
import { Button } from "./button";
4+
import { WarningBanner } from "./warning_banner";
5+
6+
const meta = {
7+
title: "Messages/Warning Banner",
8+
component: WarningBanner,
9+
} satisfies Meta<typeof WarningBanner>;
10+
11+
export default meta;
12+
type Story = StoryObj<typeof meta>;
13+
14+
export const Basic: Story = {
15+
render: () => (
16+
<WarningBanner>
17+
This is a warning message. Please review the action before proceeding.
18+
</WarningBanner>
19+
),
20+
// excluding from autodocs and dev seems to be the way to have this
21+
// component as the first thing in the docs and only there
22+
tags: ["!autodocs", "!dev"],
23+
};
24+
25+
export const WithAction: Story = {
26+
render: () => (
27+
<WarningBanner
28+
actions={
29+
<Button variant="utility" onClick={() => alert("Action clicked!")}>
30+
Take Action
31+
</Button>
32+
}
33+
>
34+
This document has been deleted and will not be listed in your documents.
35+
</WarningBanner>
36+
),
37+
};
38+
39+
export const WithMultipleActions: Story = {
40+
render: () => (
41+
<WarningBanner
42+
actions={
43+
<>
44+
<Button variant="utility" onClick={() => alert("Dismissed!")}>
45+
Dismiss
46+
</Button>
47+
<Button variant="utility" onClick={() => alert("Learn more clicked!")}>
48+
Learn More
49+
</Button>
50+
</>
51+
}
52+
>
53+
You have unsaved changes. Would you like to save them before leaving?
54+
</WarningBanner>
55+
),
56+
};
57+
58+
export const WithLongContent: Story = {
59+
render: () => (
60+
<WarningBanner>
61+
This banner contains a longer message to demonstrate how the component handles text
62+
wrapping. The content will wrap naturally and the icon and actions will stay aligned
63+
properly. This is useful for more detailed messages that require additional explanation
64+
or context for the user to understand the situation.
65+
</WarningBanner>
66+
),
67+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import TriangleAlert from "lucide-solid/icons/triangle-alert";
2+
import type { JSX } from "solid-js";
3+
4+
import styles from "./warning_banner.module.css";
5+
6+
/** Props for a warning banner component. */
7+
export type WarningBannerProps = {
8+
/** Main content of the banner. */
9+
children: JSX.Element;
10+
11+
/** Optional actions (e.g., buttons) to display on the right side. */
12+
actions?: JSX.Element;
13+
};
14+
15+
/** A warning banner component for displaying important warning messages with optional actions. */
16+
export function WarningBanner(props: WarningBannerProps) {
17+
return (
18+
<div class={styles.warningBanner}>
19+
<div class={styles.warningBannerIcon}>
20+
<TriangleAlert size={20} />
21+
</div>
22+
<div class={styles.warningBannerContent}>
23+
<strong>Warning:</strong> {props.children}
24+
</div>
25+
{props.actions && <div class={styles.warningBannerActions}>{props.actions}</div>}
26+
</div>
27+
);
28+
}

0 commit comments

Comments
 (0)