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

Conversation

DSchau
Copy link
Contributor

@DSchau DSchau commented Jul 17, 2019

Description

At a workshop yesterday, @KyleAMathews and I noticed that people tend to highlight the wrong lines, or lose a few lines when highlighting leading to strange errors and confusion. We can avoid this by introducing a copy functionality to our code snippets.

This PR does just that while also maintaining most of our other features, notably:

  1. Syntax highlighting
  2. Titles from the language (e.g. jsx:title=gatsby-config.js)
    • Note: we should make this component re-usable, and then we can pass a title as a JSX prop or something
  3. Language badges

A gif is worth lots of words, so it looks something like this:

copy-button

Also @fk would love your design eye — I think it looks OK but could certainly be improved :) Feel free to tweak anything!

Related Issues

Fixes #5030

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!

@sidharthachatterjee
Copy link
Contributor

Just stopping by to say that this is incredible @DSchau 💜

Copy link
Contributor

@gillkyle gillkyle left a comment

Choose a reason for hiding this comment

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

Oh @DSchau you glorious soul, this trophy is for you: 🏆

This is so awesome, this has been an open issue for ages, so glad someone just jumped in to hammer it out. I know @marcysutton had some concerns about accessibility but this is looking great to me! (her success criteria was here on the issue: #5030 (comment))

@DSchau
Copy link
Contributor Author

DSchau commented Jul 17, 2019

@marcysutton @gillkyle could use some assistance! Let me address what I’ve tried to improve re: accessibility, and then we can see if there’s room for improvement!

As a keyboard user, I should be able to reach and operate a copy button for each code example and see a visible focus style.

As a sighted user, I should see a graphic icon with adequate color contrast for each code example that is intuitive and clear that it will copy code to the clipboard.

I used the text Copy and Copied instead of an icon and toast widget? That OK?

As an assistive technology user, when navigating through the copy buttons I should hear unique button names like ${filename}: copy code to clipboard to know which file I’m copying to the clipboard.

Maybe done? I used the text you describe as the name attribute on the button and swap between them when the button is in copied state or not.

As a mouse user, clicking on the button should copy the adjacent code to the user’s clipboard in all major browsers.

As a keyboard or screen reader user, focusing on the button and hitting the ENTER or SPACE keys should copy the adjacent code to the clipboard in all major browsers.

As a sighted user, upon activating the button, I should see a visible “copied to clipboard!” toast notification.

I didn’t do this because we don’t really have a pattern for this — and it’s a bit out of scope for this PR. I can do this, but I’m thinking swapping the text could be enough? More I can do here?

As a user with limited mobility or a cognitive impairment, I should have time to read the toast notification before it is dismissed by only closing it when activating the close button.

5 seconds? More or less?

As a screen reader user, I should hear an announcement of ${filename} copied to clipboard after activating the button.

✅ I think. I stole your ScreenReaderText component!

@fk
Copy link
Contributor

fk commented Jul 17, 2019

<3 Will have a mock for this by tomorrow.

@gillkyle
Copy link
Contributor

I think swapping the text as a notification might actually simplify some of the accessibility concerns. I recall @marcysutton talking about how toast notifications can be difficult with focus though she'll certainly have a more definite opinion.

@DSchau
Copy link
Contributor Author

DSchau commented Jul 18, 2019

Woo-hoo! I wrote some relatively janky-ish code to add support for “directives” (i.e. highlight-start, highlight-end, hide-line, etc.), and the accessibility seems to be much approved — but still could use a once-over from someone a little more well-versed than myself.

Screen Shot 2019-07-18 at 12 34 48 PM

I think this is ready for a set of 👀 Still need that slick design tho @fk but no rush!

Longer term, we should probably open-source this as a separate package; I can imagine it being pretty useful in any MDX setup!

@marcysutton
Copy link
Contributor

(I thought I commented on this yesterday, but didn't hit send!)

Yay, that all sounds good to me! I'm so glad I wrote those success criteria. After user testing I actually agree that putting the "copied" text right on the button makes a lot of sense. I wouldn't worry about changing the design for that, but we might need to do a little more to make sure the "${filename} copied" message is announced in a screen reader. Thanks so much for working on this!

@KyleAMathews
Copy link
Contributor

Are we using the same code highlighting component as in gatsby-theme-blog?

@DSchau
Copy link
Contributor Author

DSchau commented Jul 18, 2019

@KyleAMathews nope. That one is theme-ui/prism, which is here

It is fairly similar, but we’re not using theme-ui (yet…) on .org, so I think it makes some sense to have a separate component here.

@fk
Copy link
Contributor

fk commented Jul 18, 2019

AFAIK the UI needs to support four different scenarios:

  • plain code blocks — no "language" label, no title
  • code blocks with just a title
  • code blocks with just a "language" label
  • code blocks with "language" label and title

I'm assuming we want to have a "Copy" button for every block of code.


  1. Just adding a "header" (like the one we show when there's a title) and always show the "Copy" button there would be the easiest, but also the most obstrusive solution, esp. when there's no title:

Code Block_ Language badge only

  1. This layout works well when we have title and language badge, but—and this is very nitpicky—I don't really like that the "Copy" button looks like it's associated with the filename:

Code Block_ Title, language badge

This might be the most common scenario in our docs, but let's take a look at some more, e.g. code block showing just one line of code.

  1. So here's another variant: Only show the "Copy" button when a user hovers the code block—but that would lock out touch(-only)-device users:

Code Block_ Language badge only, switch to _Copy_ button on hover

  1. We also could show the "Copy" button persistent though, like e.g. the Bootstrap docs do, and move the language badge to the left:

Code Block_ Language badge, persistent _Copy_ button a la getbootstrap com

This is not super-duper touch friendly though (irt the button size), but would probably be an acceptable tradeoff (assuming that the majority of our users are on a desktop-like device).

  1. So, finally, here's what I ended up with—persistent "Copy" button with slightly increased hozizontal padding; for code blocks with a title, we move the language badge around to be less distracting:

Code Block_ Final

If we'd want the "Copy" button to look more like a button, we could decrease the overall padding, and slightly increase the offset to the top and right:

Code Block_ Final, variant where the button shape is clearer

@fk
Copy link
Contributor

fk commented Jul 18, 2019

Here's a variant of the last approach, with (somewhat) consistent position for the language badge:

Code Block_ Final, variant where the language badge position is consistent

IMO that's a little too busy. We can make that work a little better if we ditch the "per-language" background color:

Code Block_ Final, variant where the language badge position is consistent, and we don't do colo

@DSchau
Copy link
Contributor Author

DSchau commented Jul 19, 2019

@fk implemented! 🙌

button

@DSchau DSchau marked this pull request as ready for review July 19, 2019 01:36
@DSchau DSchau requested a review from a team as a code owner July 19, 2019 01:36
@DSchau DSchau changed the title [WIP] feat(www): add copy button to code snippets feat(www): add copy button to code snippets Jul 19, 2019
@DSchau
Copy link
Contributor Author

DSchau commented Jul 19, 2019

This should be ready to go! 🚀

@marcysutton
Copy link
Contributor

marcysutton commented Jul 19, 2019

Wow, nice work @fk and @DSchau! I didn't get a chance to mention this earlier, but I'm wondering if users will look at "Copy" in text and assume it's not interactive, while the language badges with a background color look more like buttons (but they aren't). Does anyone else see that?

@DSchau
Copy link
Contributor Author

DSchau commented Jul 19, 2019

@marcysutton for sure! @fk and I were definitely inspired by Bootstrap here, but if we need it to be more button-y (that’s a word, trust me), we can do that too!

Copy link
Contributor

@sidharthachatterjee sidharthachatterjee left a comment

Choose a reason for hiding this comment

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

I think this is incredible and ready to ship so leaving this approval here! Not hitting the big green button just yet in case we want to handle this

but I'm wondering if users will look at "Copy" in text and assume it's not interactive

@DSchau
Copy link
Contributor Author

DSchau commented Jul 19, 2019

Going to merge! Thanks for the thoughtful review, comments, and design details everyone 🚀

@DSchau DSchau merged commit 6bd0109 into gatsbyjs:master Jul 19, 2019
@DSchau DSchau deleted the www/copy branch July 19, 2019 16:36
@marcysutton
Copy link
Contributor

Thanks for merging Dustin! We can follow up with tweaks and stuff...once it's deployed on the site I'll take a look and see if I have any recommendations to chat through with @fk. This is going to be so helpful for users!

@iamskok
Copy link

iamskok commented Jul 19, 2019

@DSchau You are killing it! Any plans to publish it as a separate package? I will update gatsby-remark-code-buttons README.md to link to this package.

@Blackglade
Copy link

Blackglade commented Jul 21, 2019

@DSchau How is this implemented? I can't seem to find documentation anywhere on how enable a copy button? I see the functionality on this page: https://www.gatsbyjs.org/docs/use-static-query/ but haven't been able to find what to do to use it

@DSchau
Copy link
Contributor Author

DSchau commented Jul 22, 2019

@iamskok definitely on the roadmap! What we’d probably like to do is enhance the theme-ui component to include these line highlighting changes, as well!

@Blackglade sorry — it’s in this PR? You should be able to check out the files changed to discover more?

As far as using it — click the button and it’ll copy to your clipboard!

@Blackglade
Copy link

@DSchau Oops my bad, I was under the impression that this was implemented as a default for all code blocks in Gatsby, but it seems you only did it specific to the GatsbyJS website. Would love to see a generalized plugin as @iamskok mentioned available for everyone!

NickyMeuleman added a commit to NickyMeuleman/gatsby-theme-nicky-blog-temp that referenced this pull request Jul 24, 2019
for a alternate, fully featured approach see gatsbyjs/gatsby#15834
johno pushed a commit to johno/gatsby that referenced this pull request Jul 29, 2019
* feat(www): add standalone pre component with copy functionality

* chore: make it vaguely appealing

* chore: make even prettier

* chore: keep iterating

* chore: make it work nicely again

* chore: get syntax highlighting working; todo line highlighting

* feat: improve accessibility (not done!)

* feat: add screenreader text

* chore: swap to name

* chore: add missing status

* feat: get line highlighting mostly working

* feat: get hide directive working too

* feat: iron out highlights and use correct aria-role

* chore: iron-out hide

* feat: add support for braces in language

* style: implement flo's new design

* test: get tests passing

* chore: restore monospace stack

* feat: get {} working again

* chore: make sure to trim

* chore: add some tests

* test: finish tests

* test: more of 'em of course

* chore: more fixes

* test: more tests; and calling this done!

* chore: tiny fix

* chore: add back missing autolink headers
children,
className = children.props ? children.props.className : ``,
}) => {
const [language, { title = `` }] = getParams(className)
Copy link
Contributor

@CanRau CanRau Jan 7, 2020

Choose a reason for hiding this comment

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

@DSchau I love it 😍 and plan to use some of that to add that nice copy feature to coding4.gaiama.org too 👍 🚀

By the way mdx passes additional space separated props as well so you could get the title from props.title if you pass the title like so

```js title=gatsby-config.js

instead of

```js:title=gatsby-config.js

then it won't end up in className and you wouldn't have to extract

Yet it's working as is and would be quite a pain to migrate all docs I guess 😅

Update: just realized this PR is quite old and my comment might've not worked back in the days ^^

Copy link
Contributor

Choose a reason for hiding this comment

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

FYI: i found your described behaviour here in the mdx docs:

https://mdxjs.com/guides/live-code#code-block-meta-string

Copy link
Contributor

Choose a reason for hiding this comment

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

Uh yeah thanks for the link that's where I know this from 😁🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Docs enhancement - add a copy button to code examples
10 participants