Gatsby

ljho01·2022년 7월 21일
0

다크모드 구현

토글 컴포넌트

import React, { useState, useEffect } from "react"
import "./themetog.css"


const Toggle = () => {
    const websiteTheme = typeof window != `undefined` ? window.__theme : null
    const [ theme, setTheme ] = useState(websiteTheme)
    useEffect(() => {
        setTheme(window.__theme)
        window.__onThemeChange = () => {
        setTheme(window.__theme)
        }
    }, [])

    const ThemeToggle = () => {
        window.__setPreferredTheme(websiteTheme === 'dark' ? 'light' : 'dark')
    }
    return (
        <>
            <button onClick={ThemeToggle} id="tog"/>
            <label className="toggleback" htmlFor="tog">
                    <div className="togglecon"/>
            </label>
        </>   
    )
}

export default Toggle

index.html에 스크립트 삽입

내가 기반으로 사용중인 gatsby-blog-starter는 html.js가 없는데, .cache/default-html.js 파일을 src폴더로 가져와서 html.js로 바꿔주면 된다.
그 다음 body태그에 'light'과 같은 기본 테마를 className으로 지정해주고

dangerouslySetInnerHtml 사용하여 다음 스크립트를 삽입.
https://overreacted.io 를 참고함

<script dangerouslySetInnerHTML={{
		__html: `
        	(function() {
                window.__onThemeChange = function() {};
                function setTheme(newTheme) {
                  window.__theme = newTheme;
                  preferredTheme = newTheme;
                  document.body.className = newTheme;
                  window.__onThemeChange(newTheme);
                }
                var preferredTheme;
                try {
                  preferredTheme = localStorage.getItem('theme');
                } catch (err) { }
                window.__setPreferredTheme = function(newTheme) {
                  setTheme(newTheme);
                  try {
                    localStorage.setItem('theme', newTheme);
                  } catch (err) {}
                }
                var darkQuery = window.matchMedia('(prefers-color-scheme: dark)');
                darkQuery.addListener(function(e) {
                  window.__setPreferredTheme(e.matches ? 'dark' : 'light')
                });
                setTheme(preferredTheme || (darkQuery.matches ? 'dark' : 'light'));
              })();
            `,
        }}
/>

CSS

.light {
  --color-text: black;
  --color-text-sub: var(--black-90);
  --color-line: rgba(10,10,10,0.2);
}


.dark {
  --color-text: white;
  --color-text-sub: var(--black-10);
  --color-line: rgba(240,240,240,0.2);
}

이런 식으로 변수를 만들어주면 된다.

네비바(헤더) 자동 숨기기

스크롤을 내리면 사라지고 올리면 나타난다.
https://lxieyang.github.io/blogs/tech-2018-08-18-reactstrap-gatsby-auto-hiding-navbar-trick/

TOC 만들기

https://www.gatsbyjs.com/plugins/gatsby-remark-autolink-headers/
npm install --save gatsby-remark-autolink-headers
각 제목들에 링크를 달아주는 역할을 함. 설치 후 gatsby-config에서
gatsby-transformer-remark 아래 plugin에 추가해준다.

graphql 쿼리

export const pageQuery = graphql`
  query BlogPostBySlug(
    $id: String!
    $previousPostId: String
    $nextPostId: String
  ) {
    site {
      siteMetadata {
        title
      }
    }
    markdownRemark(id: { eq: $id }) {
      id
      excerpt(pruneLength: 160)
      html
      tableOfContents
   	}

blog-post.js의 일부이다. tableOfContents를 알아서 잘 불러와준다. html태그형태로 불러와지니 dangerouslySetInnerHTML로 밀어넣어주면 된다.

네비바와 스크롤

문제는 toc에서 각 제목으로 클릭해서 이동하면 제목이 위에 딱 붙는 식으로 스크롤이 되어버려서 네비바에 가려진다는 것..
css의 scroll-margin-top을 사용하면 약간의 여백을 만들어서 쉽게 해결할 수 있다.
gatsby-remark-autolink-headersoffsetY라는 속성이 이 역할을 한다고는 나와있는데 뭘 잘못했는지 작동을 안했다.

0개의 댓글