diff --git a/apps/docs/components/copyButton/CopyButton.stories.tsx b/apps/docs/components/copyButton/CopyButton.stories.tsx index a6844c606..88ef8dbea 100644 --- a/apps/docs/components/copyButton/CopyButton.stories.tsx +++ b/apps/docs/components/copyButton/CopyButton.stories.tsx @@ -1,4 +1,3 @@ -import { useState } from "react"; import type { Meta, StoryObj } from "@storybook/react"; import CopyButton from "./CopyButton"; @@ -13,15 +12,21 @@ type Story = StoryObj; export const Default: Story = { args: { - text: "this text can be copied in 1 click", + text: "this text can be copied in 1 click", children: "this text can be copied in 1 click" }, - render: (args) => { - const [isCopied, setIsCopied] = useState(false); - return ( - - {isCopied ? Copied! : args.children} - - ) - } +}; + +export const Inline: Story = { + args: { + ...Default.args, + variant: "inline" + }, +}; + +export const Ghost: Story = { + args: { + ...Default.args, + variant: "ghost" + }, }; diff --git a/apps/docs/components/copyButton/CopyButton.tsx b/apps/docs/components/copyButton/CopyButton.tsx index 629a66b67..9162b8817 100644 --- a/apps/docs/components/copyButton/CopyButton.tsx +++ b/apps/docs/components/copyButton/CopyButton.tsx @@ -1,37 +1,61 @@ "use client"; +import React from "react"; import clsx from "clsx"; -import React, { type ReactNode } from "react"; import { Button } from "react-aria-components"; import "./copyButton.css"; interface CopyButtonProps { + variant?: "default" | "inline" | "ghost"; text: string; className?: string; - children?: ReactNode; onCopy?: () => void; - isCopied: boolean; - setIsCopied: React.Dispatch>; + copyMessage?: string; } -const CopyButton = ({ text, className, children, onCopy, isCopied, setIsCopied }: CopyButtonProps) => { - const classes = clsx("hd-copy-button", className); +const CopiedSvg = ; +// eslint-disable-next-line max-len +const CopySvg = ; + +const CopyButton = ( + { text, className, children, onCopy, variant = "default", copyMessage = "Copied!", ...rest }: React.PropsWithChildren) => { + const [isCopied, setIsCopied] = React.useState(false); + + const classes = clsx("hd-copy-button", { + [`hd-copy-button--${variant}`]: variant !== "default", + }, className); const copy = async () => { await navigator.clipboard.writeText(text); setIsCopied(true); onCopy?.(); - setTimeout(() => { + const timer = setTimeout(() => { setIsCopied(false); }, 5000); + + return () => { + clearTimeout(timer); + }; }; + const status = ( + variant === "ghost" + ? {copyMessage} + : CopiedSvg + ); + + const content = ( + variant === "ghost" + ? children + : CopySvg + ); + return ( - ); }; diff --git a/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.css b/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.css deleted file mode 100644 index d61b6e25d..000000000 --- a/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.css +++ /dev/null @@ -1,13 +0,0 @@ -.hd-codeblock-copy-button { - aspect-ratio: 1/1; - border-radius: var(--hd-space-05); - width: var(--hd-space-4); -} - -.hd-codeblock-copy-button:not([disabled]):hover { - background-color: var(--hd-color-neutral-surface-weak); -} - -.hd-codeblock-copy-button__icon { - stroke: currentcolor; -} diff --git a/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.stories.tsx b/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.stories.tsx deleted file mode 100644 index d47991b8e..000000000 --- a/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.stories.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; - -import CodeBlockCopyButton from "./CodeBlockCopyButton"; - -const meta: Meta = { - title: "Component/Copy/CodeBlockButton", - component: CodeBlockCopyButton -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: { - text: "this text can be copied in 1 click", - } -}; diff --git a/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.tsx b/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.tsx deleted file mode 100644 index e034ab8aa..000000000 --- a/apps/docs/components/copyButton/codeblockCopyButton/CodeBlockCopyButton.tsx +++ /dev/null @@ -1,33 +0,0 @@ -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 = ; - // eslint-disable-next-line max-len - const CopySvg = ; - - return ( - - {isCopied ? CopiedSvg : CopySvg} - - ); -}; - -export default CodeBlockCopyButton; diff --git a/apps/docs/components/copyButton/copyButton.css b/apps/docs/components/copyButton/copyButton.css index 971e55320..993404d15 100644 --- a/apps/docs/components/copyButton/copyButton.css +++ b/apps/docs/components/copyButton/copyButton.css @@ -1,13 +1,36 @@ .hd-copy-button { + cursor: pointer; display: flex; align-items: center; justify-content: center; - background-color: transparent; border: none; - border-radius: var(--hd-space-1); - cursor: pointer; + aspect-ratio: 1/1; + border-radius: var(--hd-space-05); + width: var(--hd-space-4); + background-color: transparent; +} + +.hd-copy-button:not([disabled]):hover { + background-color: var(--hd-color-neutral-surface-weak); +} + +.hd-copy-button__icon { + stroke: currentcolor; } .hd-copy-button[disabled]:hover { cursor: not-allowed; } + +.hd-copy-button--inline { + width: var(--hd-space-3); +} + +.hd-copy-button--ghost { + aspect-ratio: unset; + width: auto; +} + +.hd-copy-button--ghost:not([disabled]):hover { + background-color: transparent; +} diff --git a/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.css b/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.css deleted file mode 100644 index 20f4e94cb..000000000 --- a/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.css +++ /dev/null @@ -1,14 +0,0 @@ -.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); -} diff --git a/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.stories.stories.tsx b/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.stories.stories.tsx deleted file mode 100644 index 8d6e668f2..000000000 --- a/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.stories.stories.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; - -import InlineCopyButton from "./InlineCopyButton"; - -const meta: Meta = { - title: "Component/Copy/InlineButton", - component: InlineCopyButton -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: { - text: "this text can be copied in 1 click", - } -}; diff --git a/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.tsx b/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.tsx deleted file mode 100644 index 5fed0fe91..000000000 --- a/apps/docs/components/copyButton/inlineCopyButton/InlineCopyButton.tsx +++ /dev/null @@ -1,33 +0,0 @@ -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 = ; - // eslint-disable-next-line max-len - const CopySvg = ; - - return ( - - {isCopied ? CopiedSvg : CopySvg} - - ); -}; - -export default InlineCopyButton; diff --git a/apps/docs/components/iconTable/IconItem.tsx b/apps/docs/components/iconTable/IconItem.tsx index ea1e3e773..8754cb62b 100644 --- a/apps/docs/components/iconTable/IconItem.tsx +++ b/apps/docs/components/iconTable/IconItem.tsx @@ -17,7 +17,6 @@ function toKebabCase(str: string) { } const IconItem: React.FC = ({ name, type, size }) => { - const [isCopied, setIsCopied] = React.useState(false); const getIconNumericSize = (iconSize: IconItemProps["size"]) => { switch (iconSize) { @@ -45,14 +44,12 @@ const IconItem: React.FC = ({ name, type, size }) => { <>
- - {isCopied ? Copied! : - - - - } - -
+ + + + + +
{formattedName}
diff --git a/apps/docs/components/iconTable/iconItem.css b/apps/docs/components/iconTable/iconItem.css index 626419840..c879e42af 100644 --- a/apps/docs/components/iconTable/iconItem.css +++ b/apps/docs/components/iconTable/iconItem.css @@ -14,25 +14,18 @@ flex-direction: column; } -.hd-icon-item__icon { - align-items: center; - border-radius: var(--hd-space-1); - display: flex; - height: 3rem; - justify-content: center; - transition: opacity 0.2s ease-in-out; +.hd-icon-item__icon, +.hd-icon-item-copy { + aspect-ratio: 1; width: 3rem; } -.hd-icon-item__copy-status { +.hd-icon-item__icon { align-items: center; - color: var(--hd-color-accent-text); + border-radius: var(--hd-space-1); display: flex; - font-size: 0.875rem; - height: 3rem; justify-content: center; transition: opacity 0.2s ease-in-out; - width: 3rem; } .hd-icon-item-copy:not([disabled]):hover { diff --git a/apps/docs/components/ui/code/Code.tsx b/apps/docs/components/ui/code/Code.tsx index 32b1e803c..02fa50cd3 100644 --- a/apps/docs/components/ui/code/Code.tsx +++ b/apps/docs/components/ui/code/Code.tsx @@ -1,5 +1,6 @@ import React from "react"; -import InlineCopyButton from "@/components/copyButton/inlineCopyButton/InlineCopyButton"; +import CopyButton from "@/components/copyButton/CopyButton"; + import "./code.css"; interface CodeProps { @@ -11,7 +12,7 @@ const Code: React.FC = ({ children, value }) => { return (
{children} - +
); }; diff --git a/apps/docs/components/ui/pre/Pre.stories.tsx b/apps/docs/components/ui/pre/Pre.stories.tsx index a8a055f47..7dd5f78e2 100644 --- a/apps/docs/components/ui/pre/Pre.stories.tsx +++ b/apps/docs/components/ui/pre/Pre.stories.tsx @@ -18,3 +18,11 @@ export const Default: Story = { children: const foo = 'bar'; } } + +export const WithoutTitle: Story = { + args: { + raw: "const foo = 'bar';", + "data-language": "tsx", + children: const foo = 'bar'; + } +} diff --git a/apps/docs/components/ui/pre/Pre.tsx b/apps/docs/components/ui/pre/Pre.tsx index c656488cd..2e1f13a81 100644 --- a/apps/docs/components/ui/pre/Pre.tsx +++ b/apps/docs/components/ui/pre/Pre.tsx @@ -4,7 +4,7 @@ import React from "react"; import type { HTMLAttributes } from "react"; import cx from "classnames"; -import CodeBlockCopyButton from "@/components/copyButton/codeblockCopyButton/CodeBlockCopyButton"; +import CopyButton from "@/components/copyButton/CopyButton.tsx"; import LangIcon from "@/components/ui/pre/langIcon/LangIcon"; import "./pre.css"; @@ -23,24 +23,30 @@ const Pre = ({ children, title, "data-language": dataLanguage, raw, ...props }: const classes = cx("hd-pre", preClasses); + const langContent = dataLanguage && ( + + + + ) + + const titleContent = {title} + const copyButton = raw && + return (
             {title &&
                 
- {dataLanguage && ( - - - ) - } - {title} + {langContent} + {titleContent}
- {raw && } + {copyButton}
}
{children}
+ {!title &&
{copyButton}
}
); }; diff --git a/apps/docs/components/ui/pre/pre.css b/apps/docs/components/ui/pre/pre.css index d23d60eb9..4496d6b08 100644 --- a/apps/docs/components/ui/pre/pre.css +++ b/apps/docs/components/ui/pre/pre.css @@ -7,10 +7,24 @@ background-color: var(--hd-color-white-surface); } +.hd-pre--no-title { + display: flex; + align-items: stretch; +} + +.hd-pre--no-title .hd-pre__code { + margin-right: auto; +} + .hd-pre--no-title code { align-content: center; } +.hd-pre--no-title .hd-pre__action { + padding-inline: var(--hd-space-1); + margin-block: auto; +} + /* pre HEADER */ .hd-pre-header { display: flex;