Skip to content

Commit 8a76647

Browse files
author
Brijesh Bittu
committed
Fix code copy
1 parent 2c8f334 commit 8a76647

File tree

11 files changed

+128
-26
lines changed

11 files changed

+128
-26
lines changed

docs/src/components/CodeBlock.pigment.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { t } from '@pigment-css/theme';
22
import { css, styled } from '@pigment-css/react-new';
33
import { applyText } from 'docs/utils/theme';
44

5-
export const Root = styled.div({
5+
export const Root = styled.figure({
66
backgroundColor: '$color.content',
77
border: `1px solid ${t('$color.gray.200')}`,
88
borderRadius: t('$radius.md'),

docs/src/components/CodeBlock.tsx

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import { CheckIcon } from 'docs/icons/CheckIcon';
66
import { CopyIcon } from 'docs/icons/CopyIcon';
77

88
import * as CodeBlock from './CodeBlock.pigment';
9-
import * as ScrollArea from './ScrollArea';
10-
import { GhostButton } from './GhostButton.pigment';
119
import { preContainer } from './CodeBlock.pigment';
10+
import * as ScrollArea from './ScrollArea';
11+
import { GhostButton } from './GhostButton';
1212

1313
const CodeBlockContext = React.createContext({ codeId: '', titleId: '' });
1414

@@ -27,25 +27,27 @@ export function Panel({ className, children, ...props }: React.ComponentPropsWit
2727
const { codeId, titleId } = React.useContext(CodeBlockContext);
2828
const [copyTimeout, setCopyTimeout] = React.useState<number>(0);
2929

30+
const handleCopy = React.useCallback(async () => {
31+
const code = document.getElementById(codeId)?.textContent;
32+
33+
if (code) {
34+
await copy(code);
35+
const newTimeout = window.setTimeout(() => {
36+
window.clearTimeout(newTimeout);
37+
setCopyTimeout(0);
38+
}, 2000);
39+
window.clearTimeout(copyTimeout);
40+
setCopyTimeout(newTimeout);
41+
}
42+
}, []);
43+
3044
return (
3145
<CodeBlock.Panel className={className} {...props}>
3246
<CodeBlock.PanelTitle id={titleId}>{children}</CodeBlock.PanelTitle>
3347
<GhostButton
3448
className={CodeBlock.ghostButtonStyle().className}
3549
aria-label="Copy code"
36-
onClick={async () => {
37-
const code = document.getElementById(codeId)?.textContent;
38-
39-
if (code) {
40-
await copy(code);
41-
const newTimeout = window.setTimeout(() => {
42-
window.clearTimeout(newTimeout);
43-
setCopyTimeout(0);
44-
}, 2000);
45-
window.clearTimeout(copyTimeout);
46-
setCopyTimeout(newTimeout);
47-
}
48-
}}
50+
onClick={handleCopy}
4951
>
5052
Copy
5153
<CodeBlock.CopyLabel>{copyTimeout ? <CheckIcon /> : <CopyIcon />}</CodeBlock.CopyLabel>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import clsx from 'clsx';
2+
import * as React from 'react';
3+
4+
import * as Styled from './GhostButton.pigment';
5+
6+
interface GhostButtonProps extends React.ComponentProps<'button'> {
7+
layout?: 'text' | 'icon';
8+
}
9+
10+
export function GhostButton({ className, layout = 'text', ...props }: GhostButtonProps) {
11+
return (
12+
<Styled.GhostButton
13+
data-layout={layout}
14+
type="button"
15+
className={clsx('GhostButton', className)}
16+
{...props}
17+
/>
18+
);
19+
}

docs/src/components/Link.pigment.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ export const linkStyle = css`
1414
border-radius: var(--radius-sm);
1515
}
1616
17+
&[data-autolink] {
18+
display: inline;
19+
}
20+
1721
@media (hover: hover) {
1822
&:hover {
1923
text-decoration-color: ${t('$color.blue')};

docs/src/content/overview/quick-start.mdx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export default defineConfig({
5959

6060
### Non React usage
6161

62-
```jsx
62+
```ts title="App.ts"
6363
import { css } from '@pigment-css/react';
6464

6565
const visuallyHidden = css({
@@ -87,9 +87,8 @@ const visuallyHidden2 = css`
8787
width: 1px;
8888
`;
8989

90-
function App() {
91-
return <div {...visuallyHidden()}>I am invisible</div>;
92-
}
90+
const element = document.getElemenyById('app');
91+
element.className = visuallyHidden().className;
9392
```
9493

9594
Which API signature to use is totally on the requirements. Somethings are easier with the tagged-template literal signature like copy-pasting css from other source (Figma for example) but it requires editor integration. For example, [vscode-styled-components](https://marketplace.visualstudio.com/items?itemName=styled-components.vscode-styled-components) extension needs to be installed to get completions and syntax highlighting in VSCode.

docs/src/icons/LinkIcon.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as React from 'react';
2+
3+
export function LinkIcon(props: React.ComponentProps<'svg'>) {
4+
return (
5+
<svg viewBox="0 0 16 16" aria-hidden {...props}>
6+
<path
7+
stroke="currentColor"
8+
d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"
9+
/>
10+
</svg>
11+
);
12+
}

docs/src/mdx-components.pigment.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
11
import { t } from '@pigment-css/theme';
22
import { styled } from '@pigment-css/react-new';
33

4-
import * as CodeBlockBase from './components/CodeBlock.pigment';
4+
import * as CodeBlockBase from './components/CodeBlock';
55
import { Code as CodeBase } from './components/Code.pigment';
66
import { Subtitle as SubtitleBase } from './components/Subtitle.pigment';
77
import { applyText, spacing } from './utils/theme';
8+
import { linkStyle } from './components/Link.pigment';
89

910
export const Heading = styled('h1')(({ theme }) => ({
11+
position: 'relative',
1012
textWrap: 'balance',
13+
[`.${linkStyle}`]: {
14+
position: 'absolute',
15+
visibility: 'hidden',
16+
left: -25,
17+
top: '50%',
18+
transform: 'translateY(-50%)',
19+
color: '$color.foreground',
20+
},
21+
'&:hover': {
22+
[`.${linkStyle}`]: {
23+
visibility: 'visible',
24+
},
25+
},
1126
variants: {
1227
lvl: {
1328
one: {

docs/src/mdx-components.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as Styled from './mdx-components.pigment';
66
import { Link } from './components/Link';
77
import { getChildrenText } from './utils/getChildrenText';
88
import { Changelog } from './components/Changelog';
9+
import { LinkIcon } from './icons/LinkIcon';
910

1011
export const mdxComponents: MDXComponents = {
1112
a: (props) => <Link {...props} />,
@@ -57,6 +58,10 @@ export const mdxComponents: MDXComponents = {
5758
return <meta {...props} />;
5859
},
5960
Changelog,
61+
LinkIcon: (props) => {
62+
console.log(props);
63+
return <LinkIcon width={16} />;
64+
},
6065
};
6166

6267
export const inlineMdxComponents: MDXComponents = {

docs/src/utils/mdx.ts renamed to docs/src/utils/mdx.tsx

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { rehypeSubtitle } from './rehype/rehypeSubtitle';
1515
import { rehypeInlineCode } from './rehype/rehypeInlineCode';
1616

1717
const theme: Theme = {
18-
name: 'base-ui',
18+
name: 'pigment-css',
1919
bg: 'var(--color-content)',
2020
fg: 'var(--syntax-default)',
2121
settings: [
@@ -331,16 +331,18 @@ const theme: Theme = {
331331
],
332332
};
333333

334-
const highlighter = createHighlighter({
334+
// @ts-expect-error Set highlighter on globalThis
335+
globalThis.highlighter ??= createHighlighter({
335336
themes: [theme],
336337
langs: ['tsx', 'jsx', 'css'],
337338
});
338339

339340
export async function renderMdx(mdxSource: string) {
340341
const prettyCodeOptions = {
341-
getHighlighter: async () => await highlighter,
342+
// @ts-expect-error Set highlighter on globalThis
343+
getHighlighter: async () => await globalThis.highlighter,
342344
grid: false,
343-
theme: 'base-ui',
345+
theme: 'pigment-css',
344346
defaultLang: 'tsx',
345347
};
346348
const { default: MDXContent } = await evaluate(mdxSource, {
@@ -349,7 +351,17 @@ export async function renderMdx(mdxSource: string) {
349351
rehypePlugins: [
350352
[rehypePrettyCode, prettyCodeOptions],
351353
rehypeSlug,
352-
rehyeAutolinkHeading,
354+
[
355+
rehyeAutolinkHeading,
356+
{
357+
properties: {
358+
'data-autolink': '',
359+
tabindex: -1,
360+
'aria-hidden': 'true',
361+
},
362+
},
363+
],
364+
// rehypeAutoLinkContent,
353365
rehypeExtractToc,
354366
rehypeSubtitle,
355367
rehypeInlineCode,
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { visitParents } from 'unist-util-visit-parents';
2+
import type { evaluate } from '@mdx-js/mdx';
3+
4+
export type Pluggable = Exclude<
5+
Parameters<typeof evaluate>[1]['rehypePlugins'],
6+
undefined | null
7+
>[number];
8+
9+
/**
10+
* Unwrap potential paragraphs inside `<Subtitle>`
11+
*/
12+
export const rehypeAutoLinkContent: Pluggable = () => {
13+
return (tree) => {
14+
visitParents(tree, (node) => {
15+
if (
16+
node.tagName === 'a' &&
17+
node.type === 'element' &&
18+
node.properties &&
19+
'data-autolink' in node.properties
20+
) {
21+
node.children = [
22+
{
23+
type: 'mdxJsxFlowElement',
24+
name: 'LinkIcon',
25+
data: { _mdxExplicitJsx: true },
26+
children: [],
27+
},
28+
];
29+
}
30+
});
31+
};
32+
};

0 commit comments

Comments
 (0)