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

Conversation

@DSchau
Copy link
Contributor

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

@DSchau DSchau added the status: WIP label Jul 17, 2019

const [language, { title = `` }] = getParams(children.props.className)
const content = children.props.children
return (
<Highlight

This comment has been minimized.

Copy link
@DSchau

DSchau Jul 17, 2019

Author Contributor

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

@sidharthachatterjee

This comment has been minimized.

Copy link
Member

commented Jul 17, 2019

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

@gillkyle
Copy link
Contributor

left a comment

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

This comment has been minimized.

Copy link
Contributor Author

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

This comment has been minimized.

Copy link
Contributor

commented Jul 17, 2019

<3 Will have a mock for this by tomorrow.

@gillkyle

This comment has been minimized.

Copy link
Contributor

commented Jul 18, 2019

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

This comment has been minimized.

Copy link
Contributor Author

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

This comment has been minimized.

Copy link
Member

commented Jul 18, 2019

(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

This comment has been minimized.

Copy link
Contributor

commented Jul 18, 2019

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

@DSchau

This comment has been minimized.

Copy link
Contributor Author

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Contributor Author

commented Jul 19, 2019

@fk implemented! 🙌

button

DSchau added some commits Jul 19, 2019

@DSchau DSchau marked this pull request as ready for review Jul 19, 2019

@DSchau DSchau requested a review from gatsbyjs/website as a code owner Jul 19, 2019

@DSchau DSchau removed the status: WIP label Jul 19, 2019

@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

This comment has been minimized.

Copy link
Contributor Author

commented Jul 19, 2019

This should be ready to go! 🚀

@marcysutton

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Contributor Author

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!

DSchau added some commits Jul 19, 2019

@sidharthachatterjee
Copy link
Member

left a comment

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 added some commits Jul 19, 2019

@DSchau

This comment has been minimized.

Copy link
Contributor Author

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

18 checks passed

Danger All good
Details
Peril All green. Well done.
Details
ci/circleci: bootstrap Your tests passed on CircleCI!
Details
ci/circleci: e2e_tests_development_runtime Your tests passed on CircleCI!
Details
ci/circleci: e2e_tests_gatsby-image Your tests passed on CircleCI!
Details
ci/circleci: e2e_tests_path-prefix Your tests passed on CircleCI!
Details
ci/circleci: e2e_tests_production_runtime Your tests passed on CircleCI!
Details
ci/circleci: integration_tests_gatsby_pipeline Your tests passed on CircleCI!
Details
ci/circleci: integration_tests_long_term_caching Your tests passed on CircleCI!
Details
ci/circleci: lint Your tests passed on CircleCI!
Details
ci/circleci: starters_validate Your tests passed on CircleCI!
Details
ci/circleci: themes_e2e_tests_development_runtime Your tests passed on CircleCI!
Details
ci/circleci: themes_e2e_tests_production_runtime Your tests passed on CircleCI!
Details
ci/circleci: unit_tests_node10 Your tests passed on CircleCI!
Details
ci/circleci: unit_tests_node12 Your tests passed on CircleCI!
Details
ci/circleci: unit_tests_node8 Your tests passed on CircleCI!
Details
ci/circleci: unit_tests_www Your tests passed on CircleCI!
Details
unit_tests_windows Build #20190719.61 succeeded
Details

@DSchau DSchau deleted the DSchau:www/copy branch Jul 19, 2019

@marcysutton

This comment has been minimized.

Copy link
Member

commented Jul 19, 2019

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Contributor Author

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

This comment has been minimized.

Copy link

commented Jul 22, 2019

@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

feat: basic code highlighting-implementation
for a alternate, fully featured approach see gatsbyjs/gatsby#15834

johno added a commit to johno/gatsby that referenced this pull request Jul 29, 2019

feat(www): add copy button to code snippets (gatsbyjs#15834)
* 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
8 participants
You can’t perform that action at this time.