Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(www): add copy button to code snippets #15834

Merged
merged 28 commits into from
Jul 19, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d9905de
feat(www): add standalone pre component with copy functionality
DSchau Jul 17, 2019
ed4801a
chore: make it vaguely appealing
DSchau Jul 17, 2019
246eb4f
chore: make even prettier
DSchau Jul 17, 2019
d5068a8
chore: keep iterating
DSchau Jul 17, 2019
b8bb626
chore: make it work nicely again
DSchau Jul 17, 2019
b63020c
chore: get syntax highlighting working; todo line highlighting
DSchau Jul 17, 2019
bcaf18a
feat: improve accessibility (not done!)
DSchau Jul 17, 2019
16d3cbe
feat: add screenreader text
DSchau Jul 17, 2019
5755947
chore: swap to name
DSchau Jul 17, 2019
d4f06ee
chore: add missing status
DSchau Jul 17, 2019
a6fe77e
feat: get line highlighting mostly working
DSchau Jul 18, 2019
2ea5c81
feat: get hide directive working too
DSchau Jul 18, 2019
253eef5
feat: iron out highlights and use correct aria-role
DSchau Jul 18, 2019
a8eff91
chore: iron-out hide
DSchau Jul 18, 2019
083c71f
feat: add support for braces in language
DSchau Jul 18, 2019
1919a03
style: implement flo's new design
DSchau Jul 19, 2019
d37f914
test: get tests passing
DSchau Jul 19, 2019
fc095b7
Merge branch 'master' of github.com:gatsbyjs/gatsby into www/copy
DSchau Jul 19, 2019
e05e395
chore: restore monospace stack
DSchau Jul 19, 2019
7db21a8
feat: get {} working again
DSchau Jul 19, 2019
82ec189
chore: make sure to trim
DSchau Jul 19, 2019
e1feaea
chore: add some tests
DSchau Jul 19, 2019
e08c990
test: finish tests
DSchau Jul 19, 2019
d86d8a4
test: more of 'em of course
DSchau Jul 19, 2019
45d92a4
chore: more fixes
DSchau Jul 19, 2019
7a89649
test: more tests; and calling this done!
DSchau Jul 19, 2019
1742d2b
chore: tiny fix
DSchau Jul 19, 2019
1be3da0
chore: add back missing autolink headers
DSchau Jul 19, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions www/gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ module.exports = {
gatsbyRemarkPlugins: [
`gatsby-remark-graphviz`,
`gatsby-remark-embed-video`,
`gatsby-remark-code-titles`,
{
resolve: `gatsby-remark-images`,
options: {
Expand All @@ -136,8 +135,6 @@ module.exports = {
wrapperStyle: `margin-bottom: 1.5rem`,
},
},
`gatsby-remark-autolink-headers`,
`gatsby-remark-prismjs`,
`gatsby-remark-copy-linked-files`,
`gatsby-remark-smartypants`,
],
Expand Down
1 change: 1 addition & 0 deletions www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"mitt": "^1.1.3",
"mousetrap": "^1.6.1",
"parse-github-url": "^1.0.2",
"prism-react-renderer": "^0.1.7",
"prismjs": "^1.14.0",
"qs": "^6.5.2",
"query-string": "^6.1.0",
Expand Down
78 changes: 78 additions & 0 deletions www/src/components/copy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React, { useState } from "react"
import PropTypes from "prop-types"

import {
space,
fonts,
fontSizes,
colors,
radii,
lineHeights,
letterSpacings,
} from "../utils/presets"

const copyToClipboard = content => {
const el = document.createElement(`textarea`)
el.value = content
el.setAttribute(`readonly`, ``)
el.style.position = `absolute`
el.style.left = `-9999px`
document.body.appendChild(el)
el.select()
document.execCommand(`copy`)
document.body.removeChild(el)
}

const delay = duration => new Promise(resolve => setTimeout(resolve, duration))

function Copy({ content, duration = 2500, trim = false }) {
const [text, setText] = useState(`Copy`)

return (
<button
aria-label={
text === `Copy`
? `Copy text to clipboard`
: `Text has been copied to clipboard`
}
css={{
background: colors.text.header,
borderRadius: `0 0 ${radii[2]}px ${radii[2]}px`,
color: `#ddd`,
fontSize: fontSizes[0],
fontFamily: fonts.monospace,
letterSpacing: letterSpacings.tracked,
lineHeight: lineHeights.solid,
padding: `${space[1]} ${space[2]}`,
position: `absolute`,
right: space[6],
textAlign: `right`,
textTransform: `uppercase`,
top: `0`,
}}
onClick={async () => {
copyToClipboard(trim ? content.trim() : content)

setText(`Copied`)

await delay(duration)

setText(`Copy`)
}}
>
{text}
</button>
)
}

Copy.propTypes = {
content: PropTypes.string.isRequired,
duration: PropTypes.number,
trim: PropTypes.bool,
}

Copy.defaultProps = {
duration: 2500,
}

export default Copy
51 changes: 51 additions & 0 deletions www/src/components/pre.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from "react"
import Highlight, { defaultProps } from "prism-react-renderer"

import Copy from "./copy"
import { space } from "../utils/presets"

const getParams = (name = ``) => {
const [lang, params = ``] = name.split(`:`)
return [lang.split(`language-`).pop()].concat(
params.split(`&`).reduce((merged, param) => {
const [key, value] = param.split(`=`)
merged[key] = value
return merged
}, {})
)
}

export default ({ children }) => {
const [language, { title = `` }] = getParams(children.props.className)
const content = children.props.children
return (
<Highlight
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: we’ll probably want to pass our custom Prism theme as a theme here — will do just that!

{...defaultProps}
code={content}
language={language}
theme={undefined}
>
{({ tokens, getLineProps, getTokenProps }) => (
<div className="gatsby-highlight">
<div className="gatsby-highlight-header">
{title && (
<div className="gatsby-code-title" css={{ paddingTop: space[4] }}>
{title}
</div>
)}
<Copy content={content} />
</div>
<pre className={`language-${language}`}>
{tokens.map((line, i) => (
<div key={i} {...getLineProps({ line, key: i })}>
{line.map((token, key) => (
<span key={key} {...getTokenProps({ token, key })} />
))}
</div>
))}
</pre>
</div>
)}
</Highlight>
)
}
19 changes: 9 additions & 10 deletions www/src/utils/typography.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,12 @@ const _options = {
position: `relative`,
WebkitOverflowScrolling: `touch`,
},
".gatsby-highlight pre[class*='language-']": {
".gatsby-highlight pre[class^='language-']": {
backgroundColor: `transparent`,
border: 0,
padding: `${space[6]} 0`,
WebkitOverflowScrolling: `touch`,
},
".gatsby-highlight pre[class*='language-']::before": {
".gatsby-highlight pre[class^='language-']::before": {
background: `#ddd`,
borderRadius: `0 0 ${radii[2]}px ${radii[2]}px`,
color: colors.text.header,
Expand All @@ -105,7 +104,7 @@ const _options = {
lineHeight: lineHeights.solid,
padding: `${space[1]} ${space[2]}`,
position: `absolute`,
right: space[6],
left: space[6],
textAlign: `right`,
textTransform: `uppercase`,
top: `0`,
Expand Down Expand Up @@ -261,7 +260,7 @@ const _options = {
marginTop: space[9],
marginBottom: 0,
},
".gatsby-highlight, .gatsby-code-title, .post-body .gatsby-resp-image-link": {
".gatsby-highlight, .post-body .gatsby-resp-image-link": {
marginLeft: `-${space[6]}`,
marginRight: `-${space[6]}`,
},
Expand All @@ -271,23 +270,23 @@ const _options = {
},
// gatsby-remark-code-titles styles
// https://www.gatsbyjs.org/packages/gatsby-remark-code-titles/
".gatsby-code-title": {
".gatsby-highlight-header": {
background: colors.code.bg,
borderBottom: `1px solid ${colors.code.border}`,
color: colors.code.text,
padding: `${space[5]} ${space[6]} ${space[4]}`,
fontSize: fontSizes[0],
},
[mediaQueries.md]: {
".gatsby-highlight, .gatsby-resp-image-link, .gatsby-code-title": {
".gatsby-highlight, .gatsby-resp-image-link, .gatsby-highlight-header": {
marginLeft: 0,
marginRight: 0,
borderRadius: `${radii[2]}px`,
},
".gatsby-code-title": {
".gatsby-highlight-header": {
borderRadius: `${radii[2]}px ${radii[2]}px 0 0`,
},
".gatsby-code-title + .gatsby-highlight": {
".gatsby-highlight-header + .gatsby-highlight": {
borderRadius: `0 0 ${radii[2]}px ${radii[2]}px`,
},
},
Expand All @@ -302,7 +301,7 @@ const _options = {
border: `none`,
},
[mediaQueries.lg]: {
".gatsby-highlight, .post-body .gatsby-resp-image-link, .gatsby-code-title": {
".gatsby-highlight, .post-body .gatsby-resp-image-link": {
marginLeft: `-${space[6]}`,
marginRight: `-${space[6]}`,
},
Expand Down
2 changes: 2 additions & 0 deletions www/wrap-root-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import GuideList from "./src/components/guide-list.js"
import HubspotForm from "./src/components/hubspot-form"
import Pullquote from "./src/components/shared/pullquote"
import DateChart from "./src/components/chart"
import Pre from "./src/components/pre"

const components = {
GuideList,
HubspotForm,
DateChart,
Pullquote,
pre: Pre,
}

export default ({ element }) => (
Expand Down