Skip to content

Commit 4949078

Browse files
committed
WIP
1 parent 7ed8026 commit 4949078

File tree

12 files changed

+344
-23
lines changed

12 files changed

+344
-23
lines changed

astro.config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export default defineConfig({
108108
"https://github.com/cloudflare/cloudflare-docs/edit/production/",
109109
},
110110
components: {
111+
Banner: "./src/components/overrides/Banner.astro",
111112
Footer: "./src/components/overrides/Footer.astro",
112113
Head: "./src/components/overrides/Head.astro",
113114
Header: "./src/components/overrides/Header.astro",

package-lock.json

+59
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@
4141
"@expressive-code/plugin-collapsible-sections": "0.41.2",
4242
"@floating-ui/react": "0.27.7",
4343
"@iarna/toml": "2.2.5",
44+
"@lottiefiles/dotlottie-react": "0.13.5",
4445
"@marsidev/react-turnstile": "1.1.0",
46+
"@nanostores/react": "1.0.0",
4547
"@octokit/webhooks-types": "7.6.1",
4648
"@stoplight/json-schema-tree": "4.0.0",
4749
"@tailwindcss/postcss": "4.1.4",
@@ -82,6 +84,7 @@
8284
"mdast-util-mdx-expression": "2.0.1",
8385
"mermaid": "11.6.0",
8486
"micromark-extension-mdxjs": "3.0.0",
87+
"nanostores": "1.0.1",
8588
"node-html-parser": "7.0.1",
8689
"openapi-types": "12.1.3",
8790
"parse-duration": "2.1.4",

patches/@astrojs+starlight+0.34.1.patch

+21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
diff --git a/node_modules/@astrojs/starlight/components/SidebarSublist.astro b/node_modules/@astrojs/starlight/components/SidebarSublist.astro
2+
index a027f56..7e372d7 100644
3+
--- a/node_modules/@astrojs/starlight/components/SidebarSublist.astro
4+
+++ b/node_modules/@astrojs/starlight/components/SidebarSublist.astro
5+
@@ -4,6 +4,7 @@ import type { SidebarEntry } from '../utils/routing/types';
6+
import Icon from '../user-components/Icon.astro';
7+
import Badge from '../user-components/Badge.astro';
8+
import SidebarRestorePoint from './SidebarRestorePoint.astro';
9+
+import SidebarIcon from "~/components/SidebarIcon.astro"
10+
11+
interface Props {
12+
sublist: SidebarEntry[];
13+
@@ -24,7 +25,7 @@ const { sublist, nested } = Astro.props;
14+
class:list={[{ large: !nested }, entry.attrs.class]}
15+
{...entry.attrs}
16+
>
17+
- <span>{entry.label}</span>
18+
+ <span>{entry.icon && <SidebarIcon {...entry.icon} />}{entry.label}</span>
19+
{entry.badge && (
20+
<Badge
21+
variant={entry.badge.variant}
122
diff --git a/node_modules/@astrojs/starlight/user-components/Tabs.astro b/node_modules/@astrojs/starlight/user-components/Tabs.astro
223
index 6d173df..61eed80 100644
324
--- a/node_modules/@astrojs/starlight/user-components/Tabs.astro

src/components/Dismissible.tsx

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { useEffect, useState, type CSSProperties } from "react";
2+
3+
import { map } from "nanostores";
4+
import { useStore } from "@nanostores/react";
5+
6+
const dismissedMap = map<Record<string, boolean>>({});
7+
export const isDismissed = (id: string) => dismissedMap.get()[id];
8+
export const setIsDismissed = (id: string, value: boolean) =>
9+
dismissedMap.setKey(id, value);
10+
11+
const loadInitialValue = (id: string) => {
12+
if (typeof localStorage === "undefined") return false;
13+
14+
const dismissValue = localStorage.getItem(`dismisser-${id}`);
15+
16+
if (dismissValue) {
17+
if (new Date(dismissValue) > new Date()) {
18+
return true;
19+
} else {
20+
localStorage.removeItem(`dismisser-${id}`);
21+
}
22+
}
23+
24+
return false;
25+
};
26+
27+
export const useDismissible = (id: string) => {
28+
const store = useStore(dismissedMap);
29+
30+
return {
31+
isDismissed: store[id],
32+
dismiss: (days: number) => {
33+
setIsDismissed(id, true);
34+
localStorage.setItem(
35+
`dismisser-${id}`,
36+
new Date(Date.now() + days * 24 * 60 * 60 * 1000).toISOString(),
37+
);
38+
},
39+
};
40+
};
41+
42+
export const Dismisser = ({
43+
id,
44+
days,
45+
children,
46+
}: {
47+
id: string;
48+
days: number;
49+
children: React.ReactNode;
50+
}) => {
51+
const { dismiss } = useDismissible(id);
52+
53+
return (
54+
<span
55+
onClick={() => {
56+
dismiss(days);
57+
}}
58+
>
59+
{children}
60+
</span>
61+
);
62+
};
63+
64+
export const Dismissible = ({
65+
id,
66+
defaultDisplay,
67+
children,
68+
}: {
69+
id: string;
70+
defaultDisplay?: CSSProperties["display"];
71+
children: React.ReactNode;
72+
}) => {
73+
const [loaded, setLoaded] = useState(false);
74+
const store = useStore(dismissedMap);
75+
76+
useEffect(() => {
77+
setIsDismissed(id, loadInitialValue(id));
78+
setLoaded(true);
79+
}, []);
80+
81+
return (
82+
<span
83+
style={{
84+
display: !loaded ? defaultDisplay : store[id] ? "none" : undefined,
85+
}}
86+
>
87+
{children}
88+
</span>
89+
);
90+
};

src/components/SidebarIcon.astro

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
import { z } from "astro:schema";
3+
import { SidebarIconSchema } from "~/schemas/types/sidebar";
4+
import { DotLottieWorkerReact } from "@lottiefiles/dotlottie-react";
5+
6+
type Props = z.infer<typeof props>;
7+
8+
const props = SidebarIconSchema();
9+
10+
let iconProps = props.parse(Astro.props);
11+
12+
// https://angel-rs.github.io/css-color-filter-generator/
13+
const filter =
14+
iconProps?.color === "primary"
15+
? "brightness(0) saturate(100%) invert(60%) sepia(90%) saturate(2312%) hue-rotate(347deg) brightness(99%) contrast(95%)" // --orange-accent-200
16+
: undefined;
17+
---
18+
19+
{
20+
iconProps?.lottieLink && (
21+
<DotLottieWorkerReact
22+
style={{
23+
filter,
24+
height: "17px", // if someone smarter than me can make this properly text height, please go for it
25+
width: "auto",
26+
float: "left",
27+
}}
28+
src={iconProps.lottieLink}
29+
loop
30+
autoplay
31+
client:load
32+
/>
33+
)
34+
}

src/components/overrides/Banner.astro

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
import { Dismissible, Dismisser } from "../Dismissible";
3+
4+
const { banner } = Astro.locals.starlightRoute.entry.data;
5+
---
6+
7+
{
8+
(() => {
9+
if (!banner) return;
10+
11+
if (banner.dismissible_id) {
12+
return (
13+
<Dismissible
14+
id={banner.dismissible_id}
15+
defaultDisplay="none"
16+
client:load
17+
>
18+
<div class={`sl-banner relative ${banner.type}`}>
19+
<span set:html={banner.content} />
20+
<Dismisser id={banner.dismissible_id} days={7} client:load>
21+
<span class="absolute top-0 right-0 bottom-0 px-4 py-3">
22+
<svg
23+
class="h-6 w-6 fill-current"
24+
role="button"
25+
xmlns="http://www.w3.org/2000/svg"
26+
viewBox="0 0 20 20"
27+
>
28+
<title>Close</title>
29+
<path d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z" />
30+
</svg>
31+
</span>
32+
</Dismisser>
33+
</div>
34+
</Dismissible>
35+
);
36+
}
37+
38+
return (
39+
<div class={`sl-banner relative ${banner.type}`}>
40+
<span set:html={banner.content} />
41+
</div>
42+
);
43+
})()
44+
}
45+
46+
<style>
47+
@layer starlight.core {
48+
.sl-banner {
49+
--__sl-banner-text: var(
50+
--sl-color-banner-text,
51+
var(--sl-color-text-invert)
52+
);
53+
padding: var(--sl-nav-pad-y) var(--sl-nav-pad-x);
54+
background-color: var(--sl-color-banner-bg, var(--sl-color-bg-accent));
55+
color: var(--__sl-banner-text);
56+
line-height: var(--sl-line-height-headings);
57+
text-align: center;
58+
text-wrap: balance;
59+
box-shadow: var(--sl-shadow-sm);
60+
}
61+
.sl-banner :global(a) {
62+
color: var(--sl-color-banner-text-accent);
63+
}
64+
65+
.tip {
66+
--sl-color-banner-text-accent: var(--sl-color-purple-high);
67+
background-color: var(--sl-color-purple-low);
68+
--__sl-banner-text: var(--sl-color-white);
69+
}
70+
}
71+
</style>

0 commit comments

Comments
 (0)