Skip to content

Commit

Permalink
add global banner to docs
Browse files Browse the repository at this point in the history
  • Loading branch information
FarazPatankar committed Sep 25, 2023
1 parent 014feba commit a700570
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 6 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"theme-custom-properties": "^1.0.0",
"tinykeys": "1.4.0",
"twin.macro": "^3.1.0",
"use-local-storage-state": "^19.1.0",
"uuid": "^9.0.0"
},
"devDependencies": {
Expand Down
11 changes: 8 additions & 3 deletions src/components/Banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface Props {
icon?: React.ComponentType;
hideIcon?: boolean;
className?: string;
textContainerStyles?: TwStyle;
}

const containerStyles: Record<BannerVariant, TwStyle> = {
Expand Down Expand Up @@ -57,6 +58,7 @@ const defaultIcons: Record<BannerVariant, React.ComponentType | null> = {
export const Banner: React.FC<PropsWithChildren<Props>> = ({
children,
hideIcon,
textContainerStyles,
...props
}) => {
const variant = props.variant ?? defaultVariant;
Expand All @@ -75,9 +77,12 @@ export const Banner: React.FC<PropsWithChildren<Props>> = ({
<Icon tw="mx-1" icon={icon} css={[iconStyles[variant]]} />
)}
<div
css={{
"> p": tw`my-2`,
}}
css={[
{
"> p": tw`my-2`,
},
textContainerStyles,
]}
>
{children}
</div>
Expand Down
32 changes: 32 additions & 0 deletions src/components/GlobalBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useGlobalBanners } from "@/hooks/useGlobalBanners";
import { Banner } from "./Banner";
import { X } from "react-feather";
import tw from "twin.macro";

export const GlobalBanners = () => {
const { currentBanner, dismissGlobalBanner } = useGlobalBanners();

if (currentBanner == null) return null;

return (
<Banner
variant={currentBanner.variant}
tw="rounded-none"
textContainerStyles={tw`relative w-full flex justify-center`}
>
<p>{currentBanner.message}</p>

<button
type="button"
title="Dismiss"
css={[
tw`absolute top-0 right-0`,
tw`focus:outline-none text-gray-500 hover:text-gray-700`,
]}
onClick={() => dismissGlobalBanner(currentBanner.id)}
>
<X tw="h-5 w-5" />
</button>
</Banner>
);
};
98 changes: 98 additions & 0 deletions src/hooks/useGlobalBanners.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { BannerVariant } from "@/components/Banner";
import { Link } from "@/components/Link";
import { useMemo } from "react";
import useLocalStorageState from "use-local-storage-state";
import tw from "twin.macro";

export interface GlobalBanner {
id: string;
message: string | React.ReactElement;
variant?: BannerVariant;
}

const LaunchWeekBanner = ({
linkText,
isFirstStop,
isLastStop,
}: {
linkText: string;
isFirstStop?: boolean;
isLastStop?: boolean;
}) => (
<>
<span role="img">🚅</span>{" "}
<span>
<strong>Launch Week 01</strong> is now{" "}
{isFirstStop ? "boarding" : "in service"}.{" "}
{isFirstStop ? "First" : isLastStop ? "Last" : "Next"} stop:{" "}
<Link href="https://railway.app/launch-week-01" tw="underline">
{linkText}
</Link>
!
</span>
</>
);

const GLOBAL_BANNERS_KEY = "@railway/globalBanners";
const useGlobalBannersLocalStorage = () =>
useLocalStorageState<Record<string, boolean>>(GLOBAL_BANNERS_KEY, {
defaultValue: {},
});

export const allGlobalBanners: GlobalBanner[] = [
// Day 1
{
id: "launch-week-day-1",
message: <LaunchWeekBanner linkText="Regions" isFirstStop />,
},
// Day 2
// {
// id: "launch-week-day-2",
// message: <LaunchWeekBanner linkText="NO SPOILERS" />,
// },
// Day 3
// {
// id: "launch-week-day-3",
// message: <LaunchWeekBanner linkText="NO SPOILERS" />,
// },
// Day 4
// {
// id: "launch-week-day-4",
// message: <LaunchWeekBanner linkText="NO SPOILERS" />,
// },
// Day 5
// {
// id: "launch-week-day-5",
// message: <LaunchWeekBanner linkText="NO SPOILERS" isLastStop />,
// },
];

export const useGlobalBanners = () => {
const [viewedGlobalBanners, setViewedGlobalBanners] =
useGlobalBannersLocalStorage();

const dismissGlobalBanner = (id: string) => {
setViewedGlobalBanners(currentBanners => ({
...currentBanners,
[id]: true,
}));
};

// Oldest banner that should be visible
const currentBanner = useMemo(() => {
const viewedBanners = Object.entries(viewedGlobalBanners)
.filter(([, viewed]) => viewed)
.map(([id]) => id);

const unviewedBanners = allGlobalBanners.filter(
banner => !viewedBanners.includes(banner.id),
);

return unviewedBanners[0] ?? null;
}, [allGlobalBanners, viewedGlobalBanners]);

return {
currentBanner,
dismissGlobalBanner,
};
};
5 changes: 2 additions & 3 deletions src/layouts/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { MobileNav, Nav } from "../components/Nav";
import { Props as SEOProps, SEO } from "../components/SEO";
import { Sidebar } from "../components/Sidebar";
import { Background } from "../pages";
import { GlobalBanners } from "@/components/GlobalBanner";

export interface Props {
seo?: SEOProps;
Expand All @@ -31,10 +32,9 @@ export const Page: React.FC<PropsWithChildren<Props>> = props => {
return (
<>
<SEO {...props.seo} />

<GlobalBanners />
<div tw="min-h-screen relative flex">
<Sidebar />

<div tw="flex flex-col flex-1 max-w-[100vw] overflow-x-hidden">
<Background />

Expand All @@ -47,7 +47,6 @@ export const Page: React.FC<PropsWithChildren<Props>> = props => {
</main>
</div>
</div>

<Modal
title="Search Docs"
isOpen={isSearchOpen}
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5158,6 +5158,11 @@ update-browserslist-db@^1.0.10:
escalade "^3.1.1"
picocolors "^1.0.0"

use-local-storage-state@^19.1.0:
version "19.1.0"
resolved "https://registry.yarnpkg.com/use-local-storage-state/-/use-local-storage-state-19.1.0.tgz#9424981fd95dd37d253aad982f0a959ef5542fe2"
integrity sha512-3Ea6uRtRaSwpZYD9maZPKoEEGRuHmVA7zGrV/Uh9s5NTj9K1x/MB4IOQoywjUesQyhXmJq6bqjC5cAqlsXoOTw==

use-sync-external-store@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
Expand Down

0 comments on commit a700570

Please sign in to comment.