Skip to content

Commit b01aaae

Browse files
avivkellercnaples79
andcommitted
feat: inline copy feedback for code blocks
Co-Authored-By: cnaples79 <cnaples79@gmail.com>
1 parent 68c4421 commit b01aaae

File tree

18 files changed

+39
-299
lines changed

18 files changed

+39
-299
lines changed

apps/site/components/Common/CodeBox.tsx

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
'use client';
22

3+
import {
4+
DocumentDuplicateIcon,
5+
CodeBracketIcon,
6+
} from '@heroicons/react/24/outline';
37
import BaseCodeBox from '@node-core/ui-components/Common/BaseCodeBox';
48
import { useTranslations } from 'next-intl';
59

@@ -11,28 +15,30 @@ import type { FC, PropsWithChildren } from 'react';
1115
type CodeBoxProps = {
1216
language: string;
1317
className?: string;
14-
showCopyButton?: boolean;
1518
};
1619

1720
const CodeBox: FC<PropsWithChildren<CodeBoxProps>> = props => {
1821
const [copied, copyToClipboard] = useCopyToClipboard();
1922
const t = useTranslations();
2023

21-
const onCopy = (text: string) => {
22-
copyToClipboard(text);
23-
};
24-
2524
return (
2625
<BaseCodeBox
2726
as={Link}
28-
onCopy={onCopy}
29-
copied={copied}
27+
onCopy={copyToClipboard}
28+
buttonContent={
29+
copied ? (
30+
<>
31+
<DocumentDuplicateIcon className="size-4" />
32+
{t('components.common.codebox.copied')}
33+
</>
34+
) : (
35+
<>
36+
<CodeBracketIcon className="size-4" />
37+
{t('components.common.codebox.copy')}
38+
</>
39+
)
40+
}
3041
{...props}
31-
buttonText={
32-
copied
33-
? t('components.common.codebox.copied')
34-
: t('components.common.codebox.copy')
35-
}
3642
/>
3743
);
3844
};

apps/site/components/MDX/CodeBox/index.tsx

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,17 @@ import { getLanguageDisplayName } from '@node-core/rehype-shiki';
22

33
import CodeBox from '#site/components/Common/CodeBox';
44

5-
import type { FC, PropsWithChildren } from 'react';
5+
import type { FC, HTMLAttributes } from 'react';
66

7-
type CodeBoxProps = { className?: string; showCopyButton?: string };
8-
9-
const MDXCodeBox: FC<PropsWithChildren<CodeBoxProps>> = ({
7+
const MDXCodeBox: FC<HTMLAttributes<HTMLElement>> = ({
108
children: code,
119
className,
12-
showCopyButton,
1310
}) => {
1411
const matches = className?.match(/language-(?<language>[a-zA-Z]+)/);
1512
const language = matches?.groups?.language ?? '';
1613

1714
return (
18-
<CodeBox
19-
language={getLanguageDisplayName(language)}
20-
showCopyButton={showCopyButton ? showCopyButton === 'true' : undefined}
21-
className={className}
22-
>
15+
<CodeBox language={getLanguageDisplayName(language)} className={className}>
2316
{code}
2417
</CodeBox>
2518
);

apps/site/layouts/Base.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
1-
'use client';
2-
3-
import { NotificationProvider } from '@node-core/ui-components/Providers/NotificationProvider';
4-
51
import { NavigationStateProvider } from '#site/providers/navigationStateProvider';
62

73
import type { FC, PropsWithChildren } from 'react';
84

95
import styles from './layouts.module.css';
106

117
const BaseLayout: FC<PropsWithChildren> = ({ children }) => (
12-
<NotificationProvider>
13-
<NavigationStateProvider>
14-
<div className={styles.baseLayout}>{children}</div>
15-
</NavigationStateProvider>
16-
</NotificationProvider>
8+
<NavigationStateProvider>
9+
<div className={styles.baseLayout}>{children}</div>
10+
</NavigationStateProvider>
1711
);
1812

1913
export default BaseLayout;

apps/site/next.config.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ const nextConfig = {
7171
'@radix-ui/react-label',
7272
'@radix-ui/react-select',
7373
'@radix-ui/react-tabs',
74-
'@radix-ui/react-toast',
7574
'@radix-ui/react-tooltip',
7675
'@radix-ui/react-avatar',
7776
'@orama/highlight',

packages/rehype-shiki/src/plugin.mjs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -181,15 +181,6 @@ export default async function rehypeShikiji(options) {
181181
codeLanguage
182182
);
183183

184-
// Adds a Copy Button to the CodeBox if requested as an additional parameter
185-
// And avoids setting the property (overriding) if undefined or invalid value
186-
if (
187-
meta.showCopyButton &&
188-
['true', 'false'].includes(meta.showCopyButton)
189-
) {
190-
children[0].properties.showCopyButton = meta.showCopyButton;
191-
}
192-
193184
// Replaces the <pre> element with the updated one
194185
parent.children.splice(index, 1, ...children);
195186
});

packages/ui-components/.storybook/preview.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { withThemeByDataAttribute } from '@storybook/addon-themes';
22

3-
import { NotificationProvider } from '#ui/Providers/NotificationProvider';
4-
53
import type { Preview, ReactRenderer } from '@storybook/react-webpack5';
64

75
import { STORYBOOK_MODES, STORYBOOK_SIZES } from './constants';
@@ -17,11 +15,6 @@ const preview: Preview = {
1715
},
1816

1917
decorators: [
20-
Story => (
21-
<NotificationProvider>
22-
<Story />
23-
</NotificationProvider>
24-
),
2518
withThemeByDataAttribute<ReactRenderer>({
2619
themes: { light: '', dark: 'dark' },
2720
defaultTheme: 'light',

packages/ui-components/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@node-core/ui-components",
3-
"version": "1.4.2",
3+
"version": "1.5.0",
44
"type": "module",
55
"exports": {
66
"./*": [
@@ -44,7 +44,6 @@
4444
"@radix-ui/react-select": "~2.2.6",
4545
"@radix-ui/react-separator": "~1.1.8",
4646
"@radix-ui/react-tabs": "~1.1.13",
47-
"@radix-ui/react-toast": "~1.2.15",
4847
"@radix-ui/react-tooltip": "~1.2.8",
4948
"@tailwindcss/postcss": "~4.1.17",
5049
"@vcarl/remark-headings": "~0.1.0",

packages/ui-components/src/Common/BaseCodeBox/index.module.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,3 @@
7878
}
7979
}
8080
}
81-
82-
.icon {
83-
@apply size-4;
84-
}

packages/ui-components/src/Common/BaseCodeBox/index.stories.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,10 @@ server.listen(port, hostname, () => {
2020
console.log(\`Server running at http://\${hostname}:\${port}/\`);
2121
});`;
2222

23-
const args = {
24-
language: 'JavaScript (CJS)',
25-
children: <code>{content}</code>,
26-
};
27-
2823
export const Default: Story = {
29-
args,
30-
};
31-
32-
export const WithCopyButton: Story = {
3324
args: {
34-
...args,
35-
showCopyButton: true,
25+
language: 'JavaScript (CJS)',
26+
children: <code>{content}</code>,
3627
},
3728
};
3829

packages/ui-components/src/Common/BaseCodeBox/index.tsx

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
'use client';
22

3-
import { DocumentDuplicateIcon } from '@heroicons/react/24/outline';
43
import classNames from 'classnames';
54
import { Fragment, isValidElement, useRef } from 'react';
6-
import { CheckIcon } from '@heroicons/react/24/outline';
75

86
import BaseButton from '#ui/Common/BaseButton';
97

108
import type { LinkLike } from '#ui/types';
11-
import type { FC, PropsWithChildren, ReactElement } from 'react';
9+
import type { FC, PropsWithChildren, ReactElement, ReactNode } from 'react';
1210

1311
import styles from './index.module.css';
1412

@@ -70,8 +68,7 @@ type CodeBoxProps = {
7068
className?: string;
7169
onCopy: (text: string) => void;
7270
as?: LinkLike;
73-
buttonText: string;
74-
showCopyButton?: boolean;
71+
buttonContent: ReactNode;
7572
copied?: boolean;
7673
};
7774

@@ -80,10 +77,8 @@ const BaseCodeBox: FC<PropsWithChildren<CodeBoxProps>> = ({
8077
language,
8178
className,
8279
onCopy,
83-
buttonText,
80+
buttonContent,
8481
as = 'a',
85-
showCopyButton = true,
86-
copied = false,
8782
}: PropsWithChildren<CodeBoxProps>) => {
8883
const containerRef = useRef<HTMLPreElement>(null);
8984

@@ -106,21 +101,14 @@ const BaseCodeBox: FC<PropsWithChildren<CodeBoxProps>> = ({
106101
{language && (
107102
<div className={styles.footer}>
108103
<span className={styles.language}>{language}</span>
109-
{showCopyButton && (
110-
<BaseButton
111-
as={as}
112-
className={styles.action}
113-
kind="neutral"
114-
onClick={handleCopy}
115-
>
116-
{copied ? (
117-
<CheckIcon className={styles.icon} />
118-
) : (
119-
<DocumentDuplicateIcon className={styles.icon} />
120-
)}
121-
{buttonText}
122-
</BaseButton>
123-
)}
104+
<BaseButton
105+
as={as}
106+
className={styles.action}
107+
kind="neutral"
108+
onClick={handleCopy}
109+
>
110+
{buttonContent}
111+
</BaseButton>
124112
</div>
125113
)}
126114
</div>

0 commit comments

Comments
 (0)