개츠비 MDX: 오색 종이 부스러기 효과가 있는 코드 복사 버튼

34749 단어 reactgatsbymdx
TL;박사
개츠비 MDX 블로그를 위한 다기능 클립보드로 복사 단추를 만듭니다.코드가 지루하기 때문에, 우리는 오색 종이 부스러기 폭발을 통해 약간의 소질을 증가시킬 것이다
이 강좌에서 구축할 내용을 빠르게 미리 보십시오.



짐 라프티스💥

나는 어떻게 나의 직무에서 경업도를 장려합니까🎉MDX 및prism react 렌더링 모듈 덕분에 내 생활이 한결 수월해졌다
14:2020년 8월 8일 오후 17시
시작하기 전에 검사할 수 있습니다live example.

설치


이 기초 위에서 MDX 블로그와prismreact 렌더링 모듈에 대한 지원이 내장된 새로운 개츠비 프로젝트 starter template 를 만들 것입니다.
gatsby new gatsby-starter-blog-mdx https://github.com/hagnerd/gatsby-starter-blog-mdx

DX의 기본 사항 이해


MDX의 입구점은 구성 요소를 내부적으로 MDX에 매핑하는 MDXProvider 구성 요소입니다.그 밖에 매우 중요한 지주가 하나 더 있다.components 속성은 각 HTML 요소의 기본 구성 요소 here is a list for them 를 덮어쓰거나 자신의 짧은 코드를 제공할 수 있는 객체입니다.
게츠비 템플릿은 MDXProvider 브라우저 API에서 사용됩니다 wrapRootElement.
WrapProtement 브라우저 API는 응용 프로그램을 봉인할 모든 제공 프로그램 구성 요소를 설정하는 데 유용합니다.
다음은 wrap-root-element.js 파일로 MDXProvider 요소를 설정하고 사용자 정의pre 구성 요소로 대체하는 데 사용됩니다.
import React from "react"
import { MDXProvider } from "@mdx-js/react"
import { Code } from "./src/components/code"
import { preToCodeBlock } from "mdx-utils"

const components = {
  pre: preProps => {
    const props = preToCodeBlock(preProps)
    if (props) {
      return <Code {...props} />
    } else {
      return <pre {...preProps} />
    }
  },
}
export const wrapRootElement = ({ element }) => (
  <MDXProvider components={components}>{element}</MDXProvider>
)
그리고 저희 패키지는 Codegatsby-browser 파일에 추가되어 게이츠비 응용 프로그램의 루트 요소를 보여 줍니다.
import { wrapRootElement as wrap } from "./wrap-root-element"

export const wrapRootElement = wrap

사용자 정의 코드 구성 요소 조정


사용자 정의 gatsby-ssr.js 구성 요소는 Code 파일에 있고 src/components/code.js 를 사용합니다.prism-react-renderer는 Prismjs 하이라이트 코드로 추가 UI를 구현하는 완벽한 방법입니다.
이 라이브러리는 Prism 태그 코드를 사용하고 렌더링 도구로 구동되는 작은 구성 요소를 제공하여 React에 빠르게 렌더링합니다.
기본값prism-react-renderer은 다음과 같습니다.
import React from "react"
import { render } from "react-dom"
import Highlight, { defaultProps } from "prism-react-renderer"
import { LiveProvider, LiveEditor, LiveError, LivePreview } from "react-live"

export const Code = ({ codeString, language, ...props }) => {
  if (props["react-live"]) {
    return (
      <LiveProvider code={codeString} noInline={true}>
        <LiveEditor />
        <LiveError />
        <LivePreview />
      </LiveProvider>
    )
  } else {
    return (
      <Highlight {...defaultProps} code={codeString} language={language}>
        {({ className, style, tokens, getLineProps, getTokenProps }) => (
          <pre className={className} style={style}>
            {tokens.map((line, i) => (
              <div {...getLineProps({ line, key: i })}>
                {line.map((token, key) => (
                  <span {...getTokenProps({ token, key })} />
                ))}
              </div>
            ))}
          </pre>
        )}
      </Highlight>
    )
  }
}
마법은 code.js 구성 요소 내부에서 발생한다.Highlight 요소 렌더링 코드 패키지, 렌더링 속성 함수는 줄과 영패/글자에 필요한 속성을 제공합니다.
클립보드로 복사 버튼은 pre 요소 내에 있습니다.

복사 단추 만들기


복사 버튼은 코드 섹션의 오른쪽 위 모서리에 배치됩니다.
이 포지셔닝을 실현하기 위해 우리는 pre 요소의 위치를 pre 로 설정하고 약간의 충전을 추가합니다.
<pre
  className={className}
  style={{
    ...style,
    padding: "2rem",
    position: "relative",
  }}
>
  ...
</pre>
relative 구성 요소는 Button 와 함께 배치되는 간단한 버튼 요소입니다.
const Button = props => (
  <button
    style={{
      position: "absolute",
      top: 0,
      right: 0,
      border: "none",
      boxShadow: "none",
      textDecoration: "none",
      margin: "8px",
      padding: "8px 12px",
      background: "#E2E8F022",
      color: "white",
      borderRadius: "8px",
      cursor: "pointer",
      color: "#E2E8F0",
      fontSize: "14px",
      fontFamily: "sans-serif",
      lineHeight: "1",
    }}
    {...props}
  />
)
더 좋은 사용자 체험을 얻기 위해서는 사용자의 조작 결과를 알아야 합니다.따라서 코드를 복사한 후 단추 텍스트를 전환하는 것은 좋은 추가 기능이다.
그리고 React hook 상태 변수position: absolute를 설정해야 합니다.
const [isCopied, setIsCopied] = React.useState(false)
사용자가 복사 단추를 눌렀을 때 isCopied 변수는true로 변하고 특정 시간 (예를 들어 3초) 후에false로 재설정됩니다.
<Button
  onClick={() => {
    copyToClipboard(codeString)
    setIsCopied(true)
    setTimeout(() => setIsCopied(false), 3000)
  }}
>
  {isCopied ? "🎉 Copied!" : "Copy"}
</Button>
isCopied는 우리의 핵심 기능이다.나는 this article 중의 함수를 반복해서 사용했다.
const copyToClipboard = str => {
  const el = document.createElement("textarea")
  el.value = str
  el.setAttribute("readonly", "")
  el.style.position = "absolute"
  el.style.left = "-9999px"
  document.body.appendChild(el)
  el.select()
  document.execCommand("copy")
  document.body.removeChild(el)
}

최종 코드 구성 요소


지금까지 우리는 사용자 정의 copyToClipboard 구성 요소, Code 함수와 copyToClipboard 구성 요소를 가지고 있다.그런 다음 최종 코드 구성 요소는 다음과 같습니다.
export const Code = ({ codeString, children, language, ...props }) => {
  const [isCopied, setIsCopied] = React.useState(false)

  if (props["react-live"]) {
    return (
      <LiveProvider code={codeString} noInline={true}>
        <LiveEditor />
        <LiveError />
        <LivePreview />
      </LiveProvider>
    )
  } else {
    return (
      <Highlight
        {...defaultProps}
        code={codeString}
        language={language}
        theme={dracula}
      >
        {({ className, style, tokens, getLineProps, getTokenProps }) => (
          <pre
            className={className}
            style={{
              ...style,
              padding: "2rem",
              position: "relative",
            }}
          >
            <Button
              onClick={() => {
                copyToClipboard(codeString)
                setIsCopied(true)
                setTimeout(() => setIsCopied(false), 3000)
              }}
            >
              {isCopied ? "🎉 Copied!" : "Copy"}
            </Button>

            {tokens.map((line, i) => (
              <div {...getLineProps({ line, key: i })} style={style}>
                {line.map((token, key) => (
                  <span {...getTokenProps({ token, key })} />
                ))}
              </div>
            ))}
          </pre>
        )}
      </Highlight>
    )
  }
}

오색 종이 부스러기 파티


코드가 잘 작동합니다.클립보드로 복사 기능은 매우 완벽합니다.하지만 우리는 여전히 천부적인 재능을 그리워한다!
전단 개발 지역사회에 모두가 알고 있는 비밀이 하나 있다!

Everything is better with a little confetti


이것은 정말 쓸모가 없지만, 우리는 오색 종이 부스러기 비로 우리의 독자를 축하해야 한다.
이를 위해서는 React 의존 항목 Button 을 설치해야 합니다.
    yarn add react-dom-confetti
구성이 간단합니다.JSON 객체일 뿐입니다a couple of options.
const config = {
  angle: 90,
  spread: 360,
  startVelocity: 40,
  elementCount: 70,
  dragFriction: 0.12,
  duration: 3000,
  stagger: 3,
  width: "10px",
  height: "10px",
  perspective: "500px",
  colors: ["#a864fd", "#29cdff", "#78ff44", "#ff718d", "#fdff6a"],
}
다음은 react-dom-confetti 구성 요소를 추가하는 것입니다.아이템Confetti이 진짜일 때마다 이 부품은 오색 종이 부스러기로 폭발한다.
그리고 우리는 isCopied 변수를 전달하여 우리의 예시에서 폭발시키기만 하면 된다.간단해, 응?
<Confetti active={isCopied} config={config} />
오색 종이 부스러기 부품을 배치하기 위해서 우리는 이전과 같은 포지셔닝 기교를 사용할 수 있다.버튼 앞에서 폭탄을 터뜨리고 싶어서요.
CSS 속성active이 있는 WrapperConfetti 구성 요소에 대해 Highlight 구성 요소를 설정합니다.그리고 우리는 position: relative로 오색 종이 부스러기 부품을 감싸는데, 그것은 절대 오른쪽 상단에 있다.
<Wrapper>
  <Highlight>...</Highlight>

  <ConfettiWrapper>
    <Confetti active={isCopied} config={config} />
  </ConfettiWrapper>
</Wrapper>
그리고 두 개의 포장기 코드:
const Wrapper = props => <div style={{ position: "relative" }} {...props} />

const ConfettiWrapper = props => (
  <div style={{ position: "absolute", top: 0, right: 0 }} {...props} />
)

이게 다예요.


클론Github repository, 트위터에 나를 표시하는 것을 잊지 말고 너의 창작을 보여줘💪
만약 당신이 이 글을 좋아한다면, 당신은 나를 따라 인코딩, 디자인, 미니 창업 회사를 유도하는 매일의 힌트를 공유할 수 있습니다.

좋은 웹페이지 즐겨찾기