Skip to content

Commit

Permalink
Ft/block-width-components (#25)
Browse files Browse the repository at this point in the history
* feat: refactor the advanced resources and basic resources and case study components

* feat: add good styling

* feat: add case study detail highlight

* chore: cleanup & add seo details

---------

Co-authored-by: Yannick Musafiri <musayann@gmail.com>
  • Loading branch information
kareraolivier and musayann authored Apr 15, 2024
1 parent 2cdcd9d commit 85c1f60
Show file tree
Hide file tree
Showing 18 changed files with 312 additions and 178 deletions.
6 changes: 6 additions & 0 deletions next-seo.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { NextSeoProps } from "next-seo"
export default {
title: "CoDesignSytemsMap",
description:
"A map of design systems and their components, patterns, and tools.",
} as NextSeoProps
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"gsap": "^3.12.5",
"lodash.groupby": "^4.6.0",
"next": "14.1.0",
"next-seo": "^6.5.0",
"react": "^18",
"react-archer": "^4.3.0",
"react-dom": "^18",
Expand Down
38 changes: 24 additions & 14 deletions src/components/Block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,37 @@ interface Props {
title: string;
description?: string;
entries: Entries;
singleBlock?: boolean;
minifiedHeader?: boolean;
}
const Block = ({
title,
description,
entries,
}: Props) => {
const Block = ({ title, description, entries, minifiedHeader }: Props) => {
const colSpan = useMemo(() => {
if (entries?.length >= 24) return 8
if (entries?.length >= 18) return 7
return entries?.length > MAX_COL_SPAN ? MAX_COL_SPAN : MIN_COL_SPAN
}, [entries])
const rowSpan = useMemo(() => Math.ceil(entries?.length / colSpan), [entries, colSpan])
const blockHeight = useMemo(() => Math.ceil(rowSpan / MAX_COL_SPAN), [rowSpan])
if (entries?.length >= 24) return 8;
if (entries?.length >= 18) return 7;
return entries?.length > MAX_COL_SPAN ? MAX_COL_SPAN : MIN_COL_SPAN;
}, [entries]);
const rowSpan = useMemo(
() => Math.ceil(entries?.length / colSpan),
[entries, colSpan]
);
const blockHeight = useMemo(
() => Math.ceil(rowSpan / MAX_COL_SPAN),
[rowSpan]
);
return (
<div
className={`col-span-${colSpan} row-span-${rowSpan} p-8 bg-gray-100 border-2 border-dashed border-gray-400 `}
>
<Header title={title} description={description} />
<Header
title={title}
description={description}
minified={minifiedHeader}
/>
<div className="m-auto">
<CardCanvas data={entries} blockHeight={blockHeight} columns={colSpan} />
<CardCanvas
data={entries}
blockHeight={blockHeight}
columns={colSpan}
/>
</div>
</div>
);
Expand Down
51 changes: 30 additions & 21 deletions src/components/Group.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
import { Group } from "@/types/interfaces";
import Block from "./Block";

const AdvancedResources = ({ data }: { data: Group }) => {
return (
<div>
<h3 className="text-gray-600 font-semibold text-center text-2xl my-10">
{data.title != "NO GROUP" && data.title}
</h3>
<div className="flex justify-center w-full">
<div className={`p-4 grid grid-cols-8 grid-flow-col justify-center gap-3 text-sm w-full`}>
{data.blocks.map((block, i) => {
return (
<Block
key={`${data.title}-${block.title}-${i}`}
title={block.title}
description={block.description}
entries={block.entries}
/>
);
})}
</div>
</div>
const AdvancedResources = ({
data,
minifiedHeader
}: {
data: Group;
minifiedHeader?: boolean;
}) => {
return (
<>
<h3 className="text-gray-600 font-semibold text-center text-2xl my-10">
{data.title != "NO GROUP" && data.title}
</h3>
<div className="flex w-full">
<div
className={`p-4 grid grid-cols-8 grid-flow-col justify-center gap-3 text-sm w-full`}
>
{data.blocks.map((block, i) => {
return (
<Block
key={`${data.title}-${block.title}-${i}`}
title={block.title}
description={block.description}
entries={block.entries}
minifiedHeader={minifiedHeader}
/>
);
})}
</div>
);
</div>
</>
);
};

export default AdvancedResources;
57 changes: 57 additions & 0 deletions src/components/HightlightCaseStudyDetails.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from "react";
import ArrowDown from "./icons/ArrowDown";

interface Props {
levels: string[];
technologies: string[];
}

const buttonBlock = (entries: string[], title: string, style: string) => (
<div>
<h1 className="text-center text-gray-500 text-xl font-bold mb-3">
{title}
</h1>

<div className="flex flex-col gap-2 p-4 h-72 overflow-y-auto">
{entries.map((element, index) => (
<button
key={index}
className={`border border-gray-500 p-4 rounded-lg ${style}`}
>
{element}
</button>
))}
</div>
</div>
);

const HightlightCaseStudyDetails = ({ levels, technologies }: Props) => {
return (
<div className="flex items-center flex-col">
<ArrowDown />
<h1 className="text-center text-gray-500 text-xl font-bold mb-3 ">
Hightlight Case Study Details
</h1>
<div className="bg-gray-200 rounded-2xl flex gap-2 py-4 px-8 border border-gray-500">
<div className="p-4">
<div>
{buttonBlock(
levels,
"Case Study Implementation Level",
"bg-black-900 text-white"
)}
</div>
</div>
<div className="p-4">
{buttonBlock(
technologies,
"Case Study Technology",
"bg-white text-black"
)}
</div>
</div>
</div>
);
};

export default HightlightCaseStudyDetails;
28 changes: 16 additions & 12 deletions src/components/cards/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,24 @@ import ReactFlow from "reactflow";
import "reactflow/dist/style.css";
import { NodeCard } from "./Node";

const CONTAINER_HEIGHT = 600;
const CONTAINER_WIDTH = 800;
const CONTAINER_HEIGHT = 800;
const CONTAINER_WIDTH = 1000;
const SINGLE_BLOCK_WIDTH = 3000;

const NodeTypes = {
coDesign: NodeCard,
};

const CardCanvas = ({ data, blockHeight }: any) => {
const initialEdges = useMemo(()=> parseEdges(data), [data])
const initialNodes = useMemo(()=> parseNodes(data, {
width: CONTAINER_WIDTH,
height: CONTAINER_HEIGHT,
}), [data]);
const CardCanvas = ({ data, blockHeight, columns }: any) => {
const initialEdges = useMemo(() => parseEdges(data), [data]);
const initialNodes = useMemo(
() =>
parseNodes(data, {
width: columns > 5 ? SINGLE_BLOCK_WIDTH : CONTAINER_WIDTH,
height: CONTAINER_HEIGHT,
}),
[data]
);

const [nodes, setNodes] = useState<any[]>(initialNodes);
const [edges, setEdges] = useState<any[]>(initialEdges);
Expand All @@ -25,10 +30,10 @@ const CardCanvas = ({ data, blockHeight }: any) => {
<div
style={{
height: `${blockHeight * 20}rem`,
width: "100%",
width: "auto",
position: "relative",
zIndex: 20,
margin: 0,
marginTop: 10,
padding: 0,
}}
className="flex justify-center"
Expand All @@ -46,8 +51,7 @@ const CardCanvas = ({ data, blockHeight }: any) => {
draggable={false}
preventScrolling={false}
onInit={(instance) => setTimeout(() => instance.fitView(), 100)}
>
</ReactFlow>
></ReactFlow>
</div>
);
};
Expand Down
13 changes: 7 additions & 6 deletions src/components/cards/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import React from "react";
interface Props {
isToolsBlock?: boolean;
minified?: boolean;
title: string;
description?: string;
}

const HeaderCard = ({ isToolsBlock, title, description }: Props) => {
if (isToolsBlock === true)
const HeaderCard = ({ minified, title, description }: Props) => {
if (minified)
return <h1 className="m-2 text-lg font-semibold">{title}</h1>;

return (
<div className="bg-yellow-200 flex justify-center px-5 py-5 w-4/5">
<h3 className="text-2xl font-semibold w-1/3-">{title}</h3>
<div className="bg-yellow-200 flex justify-between gap-4 px-5 py-5 w-4/5">
<h3 className="text-2xl md:w-1/2 font-semibold">{title}</h3>
<p
className="text-sm w-1/2- text-center"
className="text-sm md:w-1/2 text-center"
dangerouslySetInnerHTML={{ __html: description || "" }}
></p>
</div>
Expand Down
77 changes: 41 additions & 36 deletions src/components/cards/Node.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,54 @@
import { Handle, Position } from "reactflow";
import "reactflow/dist/style.css";
import Star from "@/components/icons/Star";
import classNames from "classnames";
import { getColorByAccess } from "@/utils/helpers";
import { getBgColor, getColorByAccess } from "@/utils/helpers";
import Link from "next/link";

export function NodeCard({ data, id, isToolsBlock = false }: any) {
id = data.Key;
const level = Array.isArray(data.PARSED_MANUAL_TAGS?.CO_DESIGN_LEVEL)
? data.PARSED_MANUAL_TAGS?.CO_DESIGN_LEVEL[0]
: data.PARSED_MANUAL_TAGS?.CO_DESIGN_LEVEL;
const bgColor = classNames({
"bg-level-primary-0 border-level-secondary-0": level == 0,
"bg-level-primary-1 border-level-secondary-1": level == 1,
"bg-level-primary-2 border-level-secondary-2": level == 2,
"bg-level-primary-3 border-level-secondary-3": level == 3,
});
const dataAccess = data.PARSED_MANUAL_TAGS.ACCESS;
export function NodeCard({ data }: any) {
const bgColor = getBgColor(data);
const dataAccess = data?.PARSED_MANUAL_TAGS?.ACCESS?.[0];
const starColor = getColorByAccess(dataAccess);
const summary = data.Notes?.replace(/<[^>]*>?/gm, '');
const summary = data.Notes?.replace(/<[^>]*>?/gm, "");

return (
<div className="group cursor-pointer">
<Handle type="target" position={Position.Top} id={id} />
<div
className={`py-4 px-2 text-xs w-52 rounded-md border-solid border-2 hover:border-4 box-content hover:relative hover:border-purple-500 ${bgColor}`}
>
<div className="relative ">
<p className="z-10">{data.Title}</p>
{dataAccess === "Institutional Access" ||
dataAccess === "Paid Service" ||
dataAccess === "Open Source" ? (
<div className="absolute -bottom-5 -right-5">
<Star color={starColor} />
<Handle type="target" position={Position.Top} id={data.Key} />
<Link href={data?.Url} target="_blank">
<div
className={`py-4 px-2 text-xs w-52 rounded-md border-solid border-2 hover:border-4 box-content hover:relative hover:border-purple-500 ${bgColor}`}
>
<div className="relative">
<p className="z-10">{data.Title}</p>
<p className="z-10">{data.Author}</p>
{(dataAccess === "Institutional Access" ||
dataAccess === "Paid Service" ||
dataAccess === "Open Source") && (
<div className="absolute -bottom-9 -right-7">
<Star color={starColor} />
</div>
)}
<div className="absolute hidden group-hover:block bg-white border p-4 mt-2 z-20">
<p>
<strong>Author</strong>: {data.Author}
</p>
{summary && (
<div>
<strong>Summary</strong>: {summary}
</div>
)}
<p>
<strong>Title</strong>: {data.Title}
</p>
<p>
<strong>Tags</strong>: {data.Manual_Tags}
</p>
</div>
) : (
""
)}
<div className="absolute hidden group-hover:block bg-white border p-4 mt-2 z-20">
<p><strong>Author</strong>: {data.Author}</p>
{summary && (<div><strong>Summary</strong>: {summary}</div>)}
<p><strong>Title</strong>: {data.Title}</p>
<p><strong>Tags</strong>: {data.Manual_Tags}</p>
</div>
</div>
</div>
<Handle type="source" position={Position.Bottom} id={id} />
</Link>

<Handle type="source" position={Position.Bottom} id={data.Key} />
</div>
);
}
13579;
2 changes: 1 addition & 1 deletion src/data/case-studies/levels.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import output from "../../../public/data.json";

const rawLevels = output.map((data) => data?.PARSED_MANUAL_TAGS['CASE STUDY THEME']).flat().filter((theme) => theme) as string[]
const rawLevels = output.map((data) => data?.PARSED_MANUAL_TAGS['CASE STUDY LEVEL']).flat().filter((theme) => theme) as string[]

export const levels = Array.from(new Set(rawLevels));
7 changes: 5 additions & 2 deletions src/data/case-studies/technologies.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import output from "../../../public/data.json";

const rawTechnlogies = output.map((data) => data?.PARSED_MANUAL_TAGS['CASE STUDY TECH']).flat().filter((theme) => theme) as string[]
const rawTechnlogies = output
.map((data) => data?.PARSED_MANUAL_TAGS["CASE STUDY TECH"])
.flat()
.filter((theme) => theme) as string[];

export const technlogies = Array.from(new Set(rawTechnlogies));
export const technologies = Array.from(new Set(rawTechnlogies));
Loading

0 comments on commit 85c1f60

Please sign in to comment.