Skip to content

Commit

Permalink
Feature/hop-73 - Documentation of Icon Component (#106)
Browse files Browse the repository at this point in the history
Co-authored-by: Francis Thibault <[email protected]>
  • Loading branch information
fraincs and Francis Thibault authored Dec 1, 2023
1 parent 9c965b4 commit 6308efe
Show file tree
Hide file tree
Showing 46 changed files with 2,194 additions and 1,378 deletions.
4 changes: 3 additions & 1 deletion apps/docs/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
"Table": true,
"TypographyTable": true,
"Tabs": true,
"TableSection": true
"TableSection": true,
"Switcher": true,
"IconSpecTable": true
}
}
40 changes: 40 additions & 0 deletions apps/docs/app/icons/[...slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { notFound } from "next/navigation";
import { allIcons } from "contentlayer/generated";

import Aside from "@/components/ui/aside/Aside.tsx";
import Mdx from "@/components/ui/mdx/Mdx.tsx";
import getSectionLinks from "@/utils/getSectionLinks.ts";

interface PageProps {
params: {
slug: string[];
};
}

export async function generateStaticParams() {
return allIcons.map(({ slug, section }) => ({
slug: [section, slug]
}));
}

export default function TokenPage({ params }: PageProps) {
const [ section, type ] = params.slug;
const designToken = allIcons.find(icon => icon.slug === type && icon.section === section);

if (!designToken) {
notFound();
}

const sectionLinks = getSectionLinks(designToken);

return (
<div className="hd-container">
<Aside title="On this page" links={sectionLinks} />
<main>
<article key={designToken._id}>
<Mdx code={designToken.body.code} />
</article>
</main>
</div>
);
}
32 changes: 32 additions & 0 deletions apps/docs/app/icons/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"use client";

import { allIcons } from "contentlayer/generated";
import { useSelectedLayoutSegment } from "next/navigation";
import Sidebar from "@/components/ui/sidebar/Sidebar";
import SubHeader from "@/components/ui/subHeader/SubHeader";
import useSidebarState from "@/hooks/useSidebarState";
import getSectionLinks from "@/utils/getSectionLinks";

export default function TokenLayout({ children }: { children: React.ReactNode }) {
const { isOpen, toggleOpenState } = useSidebarState(false);
const selectedLayoutSegment = useSelectedLayoutSegment();
const [section, type] = selectedLayoutSegment?.split("/") ?? ["", ""];

const pageContent = allIcons.find(icon => icon.slug === type && icon.section === section);

if (!pageContent) {
return null;
}

const sectionLinks = getSectionLinks(pageContent);

return (
<>
<SubHeader toggleOpenState={toggleOpenState} links={sectionLinks} />
<div className="hd-wrapper hd-flex">
<Sidebar data={allIcons} isOpen={isOpen} onClose={toggleOpenState} />
{children}
</div>
</>
);
}
6 changes: 6 additions & 0 deletions apps/docs/app/layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,9 @@ article ul {
line-height: 1.5rem;
padding-left: 1rem;
}

article p a,
article li a {
color: var(--hd-color-accent-text);
text-decoration: underline;
}
48 changes: 11 additions & 37 deletions apps/docs/components/copyButton/CopyButton.tsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,37 @@
"use client";

import clsx from "clsx";
import React from "react";
import React, { type ReactNode } from "react";

import { Button } from "react-aria-components";

import "./copyButton.css";

interface CopyButtonProps {
text: string;
size?: "small" | "medium";
isInlined?: boolean;
className?: string;
children?: ReactNode;
onCopy?: () => void;
isCopied: boolean;
setIsCopied: React.Dispatch<React.SetStateAction<boolean>>;
}

const CopyButton = ({ text, size = "medium", isInlined = false, className }: CopyButtonProps) => {
const [isCopied, setIsCopied] = React.useState(false);
const CopyButton = ({ text, className, children, onCopy, isCopied, setIsCopied }: CopyButtonProps) => {
const classes = clsx("hd-copy-button", className);

const copy = async () => {
await navigator.clipboard.writeText(text);
setIsCopied(true);
onCopy?.();

setTimeout(() => {
setIsCopied(false);
}, 5000);
};

const classes = clsx("hd-copy-button", {
[`hd-copy-button--${size}`]: size !== "medium",
"hd-copy-button--inlined": isInlined
}, className);

return (
<Button isDisabled={isCopied} onPress={copy} className={classes}>
{isCopied ?
<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="m5 11.75 5 5 9-9.5"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
></path>
</svg>
:
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
/* eslint-disable-next-line max-len */
d="M13.3333 6H7.33333C6.59695 6 6 6.59695 6 7.33333V13.3333C6 14.0697 6.59695 14.6667 7.33333 14.6667H13.3333C14.0697 14.6667 14.6667 14.0697 14.6667 13.3333V7.33333C14.6667 6.59695 14.0697 6 13.3333 6Z"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
/* eslint-disable-next-line max-len */
d="M3.33337 9.99992H2.66671C2.31309 9.99992 1.97395 9.85944 1.7239 9.60939C1.47385 9.35935 1.33337 9.02021 1.33337 8.66659V2.66659C1.33337 2.31296 1.47385 1.97382 1.7239 1.72378C1.97395 1.47373 2.31309 1.33325 2.66671 1.33325H8.66671C9.02033 1.33325 9.35947 1.47373 9.60952 1.72378C9.85956 1.97382 10 2.31296 10 2.66659V3.33325"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
}
<Button isDisabled={isCopied} onPress={copy} className={classes} aria-label="Copy">
{children}
</Button>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.hd-codeblock-copy-button {
aspect-ratio: 1/1;
border-radius: var(--hd-space-05);
width: var(--hd-space-4);
color: var(--hd-neutral-20)
}

.hd-codeblock-copy-button:not([disabled]):hover {
background-color: var(--hd-neutral-50);
}

.hd-codeblock-copy-button__icon {
stroke: currentcolor;
}

.hd-codeblock-copy-button:not([disabled]):hover .hd-codeblock-copy-button__icon {
stroke: var(--hd-neutral-900);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";
import CopyButton from "../CopyButton";
import cx from "classnames";

import "./CodeBlockCopyButton.css";

interface CodeBlockCopyButtonProps {
text: string;
className?: string;
}

const CodeBlockCopyButton = ({ text, className }: CodeBlockCopyButtonProps) => {
const [isCopied, setIsCopied] = React.useState(false);

const classes = cx("hd-codeblock-copy-button", className);

const CopiedSvg = <svg width="24" height="24" className="hd-codeblock-copy-button__icon" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="m5 11.75 5 5 9-9.5" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"></path></svg>;
// eslint-disable-next-line max-len
const CopySvg = <svg width="16" height="16"className="hd-codeblock-copy-button__icon" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.3333 6H7.33333C6.59695 6 6 6.59695 6 7.33333V13.3333C6 14.0697 6.59695 14.6667 7.33333 14.6667H13.3333C14.0697 14.6667 14.6667 14.0697 14.6667 13.3333V7.33333C14.6667 6.59695 14.0697 6 13.3333 6Z" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" /><path d="M3.33337 9.99992H2.66671C2.31309 9.99992 1.97395 9.85944 1.7239 9.60939C1.47385 9.35935 1.33337 9.02021 1.33337 8.66659V2.66659C1.33337 2.31296 1.47385 1.97382 1.7239 1.72378C1.97395 1.47373 2.31309 1.33325 2.66671 1.33325H8.66671C9.02033 1.33325 9.35947 1.47373 9.60952 1.72378C9.85956 1.97382 10 2.31296 10 2.66659V3.33325" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" /></svg>;

return (
<CopyButton
className={classes}
text={text}
isCopied={isCopied}
setIsCopied={setIsCopied}
>
{isCopied ? CopiedSvg : CopySvg}
</CopyButton>
);
};

export default CodeBlockCopyButton;
26 changes: 1 addition & 25 deletions apps/docs/components/copyButton/copyButton.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,10 @@
justify-content: center;
background-color: transparent;
border: none;
stroke: var(--hd-icon-button-color);
aspect-ratio: 1/1;
width: var(--hd-space-4);
border-radius: var(--hd-space-1);
cursor: pointer;
}

.hd-copy-button[disabled] {
.hd-copy-button[disabled]:hover {
cursor: not-allowed;
}

.hd-copy-button:not([disabled]):hover {
background-color: var(--hd-color-neutral-surface-weak);
}

.hd-copy-button--small {
border-radius: var(--hd-space-05);
width: var(--hd-space-3);
}

.hd-copy-button--inlined {
background: var(--hd-color-neutral-surface);
}

.hd-copy-button--on-dark {
stroke: var(--hd-neutral-20);
}

.hd-copy-button--on-dark:hover {
stroke: var(--hd-neutral-900);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.hd-inline-copy-button {
aspect-ratio: 1/1;
background: var(--hd-color-neutral-surface);
border-radius: var(--hd-space-05);
width: var(--hd-space-3);
}

.hd-inline-copy-button:not([disabled]):hover {
background-color: var(--hd-color-neutral-surface-weak);
}

.hd-inline-copy-button__icon {
stroke: var(--hd-icon-button-color);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";
import CopyButton from "../CopyButton";
import cx from "classnames";

import "./InlineCopyButton.css";

interface InlineCopyButtonProps {
text: string;
className?: string;
}

const InlineCopyButton = ({ text, className }: InlineCopyButtonProps) => {
const [isCopied, setIsCopied] = React.useState(false);

const classes = cx("hd-inline-copy-button", className);

const CopiedSvg = <svg width="24" height="24" className="hd-codeblock-copy-button__icon" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="m5 11.75 5 5 9-9.5" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"></path></svg>;
// eslint-disable-next-line max-len
const CopySvg = <svg width="16" height="16"className="hd-codeblock-copy-button__icon" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.3333 6H7.33333C6.59695 6 6 6.59695 6 7.33333V13.3333C6 14.0697 6.59695 14.6667 7.33333 14.6667H13.3333C14.0697 14.6667 14.6667 14.0697 14.6667 13.3333V7.33333C14.6667 6.59695 14.0697 6 13.3333 6Z" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" /><path d="M3.33337 9.99992H2.66671C2.31309 9.99992 1.97395 9.85944 1.7239 9.60939C1.47385 9.35935 1.33337 9.02021 1.33337 8.66659V2.66659C1.33337 2.31296 1.47385 1.97382 1.7239 1.72378C1.97395 1.47373 2.31309 1.33325 2.66671 1.33325H8.66671C9.02033 1.33325 9.35947 1.47373 9.60952 1.72378C9.85956 1.97382 10 2.31296 10 2.66659V3.33325" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" /></svg>;

return (
<CopyButton
className={classes}
text={text}
isCopied={isCopied}
setIsCopied={setIsCopied}
>
{isCopied ? CopiedSvg : CopySvg}
</CopyButton>
);
};

export default InlineCopyButton;
64 changes: 64 additions & 0 deletions apps/docs/components/iconTable/IconItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"use client";

import React from "react";
import CopyButton from "@/components/copyButton/CopyButton.tsx";
import * as IconLibrary from "@hopper-ui/icons";

import "./iconItem.css";

export interface IconItemProps {
name: typeof IconLibrary.iconNames[number];
size: "sm" | "md" | "lg";
type: "react" | "svg";
}

function toKebabCase(str: string) {
return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
}

const IconItem: React.FC<IconItemProps> = ({ name, type, size }) => {
const [isCopied, setIsCopied] = React.useState(false);

const getIconNumericSize = (iconSize: IconItemProps["size"]) => {
switch (iconSize) {
case "sm":
return "16";
case "md":
return "24";
case "lg":
return "32";
default:
return "24";
}
};

const formattedName = name.replace("Icon", "");
const copyString = type === "react"
? size !== "md"
? `<${name} size="${size}" />`
: `<${name} />`
: `${toKebabCase(formattedName).toLowerCase()}-${getIconNumericSize(size)}.svg`;

const Component = IconLibrary[name];

return (
<>
<div className="hd-icon-item">
<div className="hd-icon-item-content">
<CopyButton className="hd-icon-item-copy" text={copyString} isCopied={isCopied} setIsCopied={setIsCopied}>
{isCopied ? <span className="hd-icon-item__copy-status">Copied!</span> :
<span className="hd-icon-item__icon">
<Component size={size} />
</span>
}
</CopyButton>
<div className="hd-icon-item__title">
{formattedName}
</div>
</div>
</div>
</>
);
};

export default IconItem;
Loading

0 comments on commit 6308efe

Please sign in to comment.