Skip to content

Commit

Permalink
feat: react router breadcrumbs (#777)
Browse files Browse the repository at this point in the history
Signed-off-by: hxtree <[email protected]>
  • Loading branch information
hxtree authored Dec 25, 2023
1 parent 5bdf476 commit 2428d86
Show file tree
Hide file tree
Showing 99 changed files with 520 additions and 358 deletions.
2 changes: 1 addition & 1 deletion clients/admin-client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ function App() {
return (
<>
<Router/>
<PageFooter siteOwner="Cats Cradle" links={[{label: 'Example', url: 'okay'}]}/>
<PageFooter siteOwner="Cats Cradle" links={[]}/>
</>
);
}
Expand Down
38 changes: 38 additions & 0 deletions clients/admin-client/src/components/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { FC } from "react";
import { Link } from "react-router-dom";
import { useBreadcrumbs } from "./useBreadcrumbs";

type TBreadCrumbs = {
title?: string;
};

export const BreadCrumbs: FC<TBreadCrumbs> = ({ title }) => {
const crumbs = useBreadcrumbs();

const lastCrumb = crumbs[crumbs.length - 1];
if(lastCrumb.url === "/"){
return;
}

return (
<nav className="container mt-2 mb-2" aria-label="breadcrumb">
<ol className="breadcrumb">
{crumbs.map((crumb, index) =>
index !== crumbs.length - 1 ? (
<li className="breadcrumb-item active" aria-current="page" key={index}>
<Link to={crumb.url}>
{crumb.title}
</Link>
</li>
) : (
<li className="breadcrumb-item active" aria-current="page" key={index}>
<span >
{title ? title : crumb.title}
</span>
</li>
)
)}
</ol>
</nav>
);
};
12 changes: 6 additions & 6 deletions clients/admin-client/src/components/DiceAnalyzer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,13 @@ export const DiceAnalyzer = (props: DiceAnalyzerProps) => {

return (
<>
<Grid container spacing={2}>
{errorMsg && errorMsg?.length > 0 && (
<Alert role="alert" severity="error">
{errorMsg}
</Alert>
)}
{errorMsg && errorMsg?.length > 0 && (
<Alert className="mb-5" role="alert" severity="error">
{errorMsg}
</Alert>
)}

<Grid container spacing={2}>
<Grid item>
<Stack>
<Box component="form">
Expand Down
6 changes: 3 additions & 3 deletions clients/admin-client/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// import { Button } from '@cats-cradle/design-system';
// import { SetStateAction, useState } from 'react';
import { AppBar, Button } from '@cats-cradle/design-system/dist/main';
import { Outlet, NavLink } from 'react-router-dom';
import { NavLink } from 'react-router-dom';


const Header = () => {
Expand All @@ -25,7 +25,8 @@ const Header = () => {
return (
<>
<AppBar
topRightSlot={<>Customer Service | <Button href="/login" color="inherit" size="small">Login</Button></>}
siteTitle='Game Masters Portal'
topRightSlot={<><Button href="/login" color="secondary" size="small">Login</Button></>}
>
<ul className="navbar-nav me-auto">
{menuItems && menuItems.map(
Expand All @@ -39,7 +40,6 @@ const Header = () => {
))}
</ul>
</AppBar>
<Outlet/>
</>
)
};
Expand Down
29 changes: 29 additions & 0 deletions clients/admin-client/src/components/useBreadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useMatches } from "react-router-dom";

type TCrumb = {
url: string;
title: string;
};

const isCrumb = (obj: unknown): obj is TCrumb => {
if (typeof obj === "object" && obj !== null) {
return "url" in obj && "title" in obj;
}
return false;
};

export const useBreadcrumbs = () => {
const matches = useMatches();

let crumbs: TCrumb[] = [];

if (matches) {
matches.map((match) => {
if (isCrumb(match.handle)) {
crumbs = [...crumbs, match.handle]
}
});
}

return crumbs;
};
13 changes: 12 additions & 1 deletion clients/admin-client/src/pages/home.page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { Button, Link } from '@cats-cradle/design-system/dist/main';

export default function HomePage() {
return (
<main className="container">
<h1>Game Master Portal</h1>
<h1>Cats Cradle</h1>
<h2>Latest</h2>
<h3>Archetypes</h3>
<p>
Attention, game masters! Introducing our latest tool designed exclusively for you.
Dive into the world of character archetypes with ease.
Uncover diverse options, check out base stats, and seamlessly explore backstories—all in one place.
No-frills, just a straightforward way to look at the data. Raise a <Link href='https://github.com/hxtree/cats-cradle/pulls'>pull request</Link> to suggest changes.
</p>
<Button href="/archetypes" color="secondary">Try It!</Button>
</main>
);
}
70 changes: 59 additions & 11 deletions clients/admin-client/src/routing/Router.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,69 @@
import '@cats-cradle/design-system/dist/assets/style.css';
import { Route, createBrowserRouter, createRoutesFromElements, RouterProvider } from 'react-router-dom';
import Header from "../components/Header";
import { Link, createBrowserRouter, RouterProvider } from 'react-router-dom';
import DicePage from "../pages/dice.page";
import ArchetypesPage from "../pages/archetypes.page";
import CharacterSheetsPage from '../pages/character-sheets.page';
import HomePage from '../pages/home.page';
import { Outlet} from 'react-router-dom';
import { BreadCrumbs } from '../components/Breadcrumbs';
import Header from "../components/Header";

export const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<Header />}>
<Route index element={<HomePage />} />
<Route path="dice-analyzer" element={<DicePage />} />
<Route path="character-sheets" element={<CharacterSheetsPage />} />
<Route path="archetypes" element={<ArchetypesPage />} />
</Route>
const Root = () => {
return (
<>
<Header/>
<BreadCrumbs/>
<Outlet/>
</>
)
)
}

const router = createBrowserRouter([
{
path: "/",
element: <Root />,
handle: {
title: 'Home',
url: '/',
crumb: () => <Link to="/">Home</Link>,
},
children: [
{
index: true,
element: <HomePage />,
},
{
path: "/character-sheets",
element: <CharacterSheetsPage />,
handle: {
title: 'Character Sheets',
url: '/character-sheets',
crumb: () => <Link to="/character-sheets">Character Sheets</Link>,
}
},
{
path: "/dice-analyzer",
element: <DicePage />,
handle: {
title: 'Dice Analyzer',
url: '/dice-analyzer',
crumb: () => <Link to="/dice-analyzer">Dice Analyzer</Link>,
}
},
{
path: "/archetypes",
element: <ArchetypesPage />,
handle:{
title: 'Archetypes',
url: '/archetypes',
crumb: () => <Link to="/archetypes">Archetypes</Link>,
}
},


],
},
]);

export const Router = () => {
return (
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import React from 'react';
import { CircularProgress } from '@mui/material';
import './style.module.scss';
import Spinner from '../Spinner/Spinner';

export enum ButtonColor {
'primary' = 'primary',
'secondary' = 'secondary',
'inherit' = 'inherit'
}
import './style.module.scss';

export enum ButtonSize {
'small' = 'small',
Expand All @@ -23,7 +16,7 @@ export enum ButtonVariant {
export type ButtonProps = {
loading?: boolean;
children: React.ReactNode;
color?: keyof typeof ButtonColor;
color?:'primary'|'secondary'|'success'|'danger'|'warning'|'info'|'light'|'dark';
variant?: keyof typeof ButtonVariant;
selected?: boolean;
size?: keyof typeof ButtonSize;
Expand All @@ -33,7 +26,7 @@ export type ButtonProps = {
testId?: string;
}

export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>((props: ButtonProps, ref) => {
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>((props: ButtonProps, ref): JSX.Element => {
const { disabled, testId, href, loading, color, children, variant, selected, size, onClick } = props;

const classNames: string[] = ['button'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,49 +14,56 @@
box-shadow: none;
&.button-disabled {
opacity: 0.5;
border: 3px solid $color-white !important;
background-color: $color-gray !important;
color: $color-black !important;
cursor: not-allowed;
}
&.button-primary {
border: 3px solid $color-primary;
background-color: $color-primary;
color: $color-white;
&:focus, &.button-selected {
outline-color: $color-berkeley-blue;
outline-color: $color-primary;
}
&.button-loading {
color: transparent;
> .spinner-border {
color: $color-white;
}
}
}
&.button-secondary {
border: 3px solid $color-secondary;
border: 3px solid $color-primary;
background-color: $color-white;
color: $color-secondary;
color: $color-primary;
&:focus, &.button-selected {
outline-color: $color-secondary;
outline-color: $color-primary;
}
&.button-loading {
color: transparent;
> .spinner-border {
color: $color-primary !important;
}
}
}
&.button-inherit, &.button-loading {
&.button-inherit {
border: 3px solid $color-primary;
background-color: $color-white;
color: $color-primary;
&:focus, &.button-selected {
outline-color: $color-berkeley-blue;
outline-color: $color-primary;
}
&.button-loading {
color: transparent;
> .spinner-border {
color: $color-primary;
}
}
}

&.button-loading {
border: 3px solid $color-gray;
background-color: $color-gray;
color: transparent;
position: relative;
&:focus, &.button-selected {
outline-color: $color-gray;
}
> .spinner {
> .spinner-border {
position: absolute;
top: calc(50% - 0.5rem);
left: calc(50% - 0.5rem);
color: $color-white;
}
}
&:focus, &.button-selected {
Expand All @@ -74,7 +81,7 @@
}
&.button-normal, &.button-medium {
font-size: 1rem;
padding: 15px 30px 10px 30px;
padding: 15px 25px 10px 25px;
}
&.button-large {
font-size: 1.4rem;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Typography } from '../Typography/Typography';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faGithub, faYoutube, faXTwitter, IconDefinition } from '@fortawesome/free-brands-svg-icons';
import { IconButton } from '@mui/material';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export type SpinnerProps = {
color:'primary'|'secondary'|'success'|'danger'|'warning'|'info'|'light'|'dark'
size?: 'small'
color:'primary'|'secondary'|'success'|'danger'|'warning'|'info'|'light'|'dark';
size?: 'small'|'medium'|'large';
}

export const Spinner = (props: SpinnerProps): JSX.Element => {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 2428d86

Please sign in to comment.