Skip to content

Commit 80a2296

Browse files
kubeclaude
andcommitted
FE-43: Add switchable background to filter stories
Default background is now the scrollable ExampleArticle with a sticky glass overlay. A "background" radio control lets you switch to the checkerboard pattern. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 12b3814 commit 80a2296

4 files changed

Lines changed: 73 additions & 28 deletions

File tree

libs/@hashintel/refractive/stories/filters/filter-obb.stories.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import {
1414
type SharedFilterProps,
1515
} from "../helpers";
1616

17-
const FilterOBBStory = (props: SharedFilterProps) => (
18-
<FilterShowcase>
17+
const FilterOBBStory = ({ background, ...props }: SharedFilterProps) => (
18+
<FilterShowcase background={background}>
1919
{(id) => <FilterOBB id={id} scaleRatio={1} pixelRatio={6} {...props} />}
2020
</FilterShowcase>
2121
);

libs/@hashintel/refractive/stories/filters/filter-polar.stories.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ type FilterPolarStoryProps = Omit<
1919
"specularOpacity" | "specularAngle"
2020
>;
2121

22-
const FilterPolarStory = (props: FilterPolarStoryProps) => (
23-
<FilterShowcase>
22+
const FilterPolarStory = ({ background, ...props }: FilterPolarStoryProps) => (
23+
<FilterShowcase background={background}>
2424
{(id) => <FilterPolar id={id} pixelRatio={6} {...props} />}
2525
</FilterShowcase>
2626
);

libs/@hashintel/refractive/stories/filters/filter.stories.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import {
1414
type SharedFilterProps,
1515
} from "../helpers";
1616

17-
const FilterStory = (props: SharedFilterProps) => (
18-
<FilterShowcase>
17+
const FilterStory = ({ background, ...props }: SharedFilterProps) => (
18+
<FilterShowcase background={background}>
1919
{(id) => (
2020
<Filter
2121
id={id}

libs/@hashintel/refractive/stories/helpers.tsx

Lines changed: 67 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import { useId } from "react";
22

33
import type { SurfaceFnDef } from "../src/helpers/surface-equations";
44
import { convex } from "../src/helpers/surface-equations";
5+
import { ExampleArticle } from "./example-article";
6+
7+
export type BackgroundType = "article" | "checkerboard";
58

69
export type SharedFilterProps = {
710
blur: number;
@@ -12,6 +15,7 @@ export type SharedFilterProps = {
1215
specularOpacity: number;
1316
specularAngle: number;
1417
bezelHeightFn: SurfaceFnDef;
18+
background: BackgroundType;
1519
};
1620

1721
export const defaultFilterArgs: SharedFilterProps = {
@@ -23,6 +27,7 @@ export const defaultFilterArgs: SharedFilterProps = {
2327
specularOpacity: 0.9,
2428
specularAngle: 2,
2529
bezelHeightFn: convex,
30+
background: "article",
2631
};
2732

2833
export const filterArgTypes = {
@@ -44,48 +49,88 @@ export const filterArgTypes = {
4449
control: { type: "range" as const, min: 0, max: 6.28, step: 0.01 },
4550
},
4651
bezelHeightFn: { table: { disable: true } },
52+
background: {
53+
control: { type: "inline-radio" as const },
54+
options: ["article", "checkerboard"],
55+
},
4756
};
4857

4958
/**
50-
* Wrapper that renders a filter + a div with that filter applied, over a colorful background.
59+
* Glass pane that applies an SVG backdrop-filter.
60+
* `children` should render the <Filter> / <FilterOBB> SVG element.
5161
*/
52-
export const FilterShowcase: React.FC<{
53-
children: (id: string) => React.ReactNode;
54-
}> = ({ children }) => {
55-
const filterId = useId();
56-
57-
return (
62+
const GlassPane: React.FC<{
63+
filterId: string;
64+
children: React.ReactNode;
65+
}> = ({ filterId, children }) => (
66+
<>
67+
{children}
5868
<div
5969
style={{
60-
position: "relative",
61-
width: "100%",
62-
height: "100vh",
63-
background:
64-
"repeating-conic-gradient(#e66465 0% 25%, #9198e5 0% 50%) 0 / 40px 40px",
70+
width: 400,
71+
height: 300,
72+
backdropFilter: `url(#${filterId})`,
73+
borderRadius: 20,
74+
backgroundColor: "rgba(255, 255, 255, 0.15)",
6575
display: "flex",
6676
alignItems: "center",
6777
justifyContent: "center",
78+
fontSize: 18,
79+
fontWeight: 600,
80+
color: "#333",
6881
}}
6982
>
70-
{children(filterId)}
83+
Refractive Glass
84+
</div>
85+
</>
86+
);
87+
88+
/**
89+
* Wrapper that renders a filter + a div with that filter applied, over a selectable background.
90+
*/
91+
export const FilterShowcase: React.FC<{
92+
background?: BackgroundType;
93+
children: (id: string) => React.ReactNode;
94+
}> = ({ background = "article", children }) => {
95+
const filterId = useId();
96+
97+
const glass = <GlassPane filterId={filterId}>{children(filterId)}</GlassPane>;
7198

99+
if (background === "checkerboard") {
100+
return (
72101
<div
73102
style={{
74-
width: 400,
75-
height: 300,
76-
backdropFilter: `url(#${filterId})`,
77-
borderRadius: 20,
78-
backgroundColor: "rgba(255, 255, 255, 0.15)",
103+
position: "relative",
104+
width: "100%",
105+
height: "100vh",
106+
background:
107+
"repeating-conic-gradient(#e66465 0% 25%, #9198e5 0% 50%) 0 / 40px 40px",
79108
display: "flex",
80109
alignItems: "center",
81110
justifyContent: "center",
82-
fontSize: 18,
83-
fontWeight: 600,
84-
color: "#333",
85111
}}
86112
>
87-
Refractive Glass
113+
{glass}
114+
</div>
115+
);
116+
}
117+
118+
return (
119+
<div style={{ position: "relative" }}>
120+
<div
121+
style={{
122+
position: "sticky",
123+
top: "50%",
124+
transform: "translateY(-50%)",
125+
display: "flex",
126+
justifyContent: "center",
127+
zIndex: 1,
128+
pointerEvents: "none",
129+
}}
130+
>
131+
<div style={{ pointerEvents: "auto" }}>{glass}</div>
88132
</div>
133+
<ExampleArticle />
89134
</div>
90135
);
91136
};

0 commit comments

Comments
 (0)