DarkMode Theme

28081 ワード

以前の記事で述べたDarkModeを追加することにしました.(ガア)

1.styled-conents ThemeProvider展開


管理する状態はあまりありませんが、ReduxとRedux Toolkitを使って状態管理を行うことにしました.
今、テーマをstyled-componsesのThemeProviderに転送します.Reduxと一緒に使う必要はないと思います.ThemeProviderは削除されました.
npm install react-redux redux-toolkit
/src/redoxフォルダを作成しthemeを作成します.jsが作成されました
テーマもjsは、トピックに必要な値を格納します.
  windowSize: {
    small: `screen and (max-width: 600px)`,
    base: `screen and (max-width: 768px)`,
    large: `screen and (max-width: 1024px)`,
  },
  fontSize: {
    xs: '0.5rem',
    sm: '0.75rem',
    base: '1rem',
    md: '1.25rem',
    lg: '1.5rem',
  },
  lightversion: {
    background: '#fff',
    fontPrimary: 'black',
    fontSecondary: 'gray',
    primary: '#00a0ff',
    ...
    ....

2.Toggleスイッチの作成


Toggle Switchはinputチェックボックスを使用して作成します.切り替えには、内部背景とボタンモデリングを大量に切り替える必要があります.「仮想要素」(Pseudo-Emement):before,:afterを使用してスイッチング内部を作成します.
  • セレクタに追加されたキーワードは、選択した要素の指定部分にスタイルを追加するために使用されます.
  • :beforeは、実際のコンテンツの前に作成されたサブエレメントです.:beforeは、実際のコンテンツの後に作成されたサブエレメントです.
    ( https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements )
  • import React, { useEffect } from 'react';
    import styled from 'styled-components';
    
    const Toggle = (props) => {
      const dispatch = useDispatch();
      const isSwitchOn = useSelector((state) => state.toggleReducer.isSwitchOn);
    
      const toggleSwitch = () => {
        dispatch(switchOn());
      };
    
      return (
        <ToggleContainer>
          {isSwitchOn ? <Dark>🌙</Dark> : <Light>☀️</Light>}
          <ToggleSwitch>
            <Checkbox
              type="checkbox"
              id="toggleSwitch"
              onClick={toggleSwitch}
              isSwitchOn={isSwitchOn}
            />
            <Label htmlFor="toggleSwitch" isSwitchOn={isSwitchOn}>
              <ToggleInner isSwitchOn={isSwitchOn} />
              <Switch isSwitchOn={isSwitchOn} />
            </Label>
          </ToggleSwitch>
        </ToggleContainer>
      );
    };
    
    export default Toggle;
    
    ...
    ....
    
    const ToggleInner = styled.span`
      display: block;
      width: 200%;
      margin-left: -100%;
      transition: margin-left 0.4s ease-in;
      margin-left: ${(props) => props.isSwitchOn && 0};
      &:before {
        float: left;
        width: 50%;
        height: 20px;
        padding: 0;
        content: '';
        background-color: ${props => props.theme.lightversion.primary};
      }
      &:after {
        float: left;
        width: 50%;
        height: 20px;
        padding: 0;
        box-sizing: border-box;
        content: '';
        background-color: ${props => props.theme.lightversion.secondary};
      }
    `;
    
    const Switch = styled.span`
      display: block;
      width: 12px;
      margin: 5px;
      background: ${props => props.theme.lightversion.primary};
      position: absolute;
      top: 0;
      bottom: 0;
      right: 28px;
      border: 0 solid ${props => props.theme.lightversion.secondary};
      border-radius: 50%;
      transition: all 0.4s ease-in;
      right: ${(props) => props.isSwitchOn && 0};
    `;
    
    パターンを確認できる表情が追加されました

    「このToggleスイッチのステータスを確認して、トピック全体を変更する必要があります.」「isSwitchOn」という名前の状態変数を作成し、減速機を作成することもできます.
    import { createSlice } from '@reduxjs/toolkit';
    
    const initialState = {
      isSwitchOn: false,
    };
    
    export const toggleReducer = createSlice({
      name: 'toggleSwitch',
      initialState,
      reducers: {
        switchOn: (state, actions) => {
          state.isSwitchOn = !state.isSwitchOn;
        },
      },
    });
    
    export const { switchOn } = toggleReducer.actions;
    
    export default toggleReducer.reducer;
    暗いモードを継続したいユーザーがいる場合は、このスイッチ値を引き続き覚えておく必要があります.ブラウザをリフレッシュすると、isSwitchon値はfalseを返し、light themeに変更されます.
    スイッチ値をローカルストレージに格納するロジックも追加されました.リフレッシュまたはクローズしてブラウザを開くときにモードを覚える必要があるため、Effectを使用してgetSwitchStateをロードします.
    // reducer
    switchOn: (state, actions) => {
      state.isSwitchOn = !state.isSwitchOn;
      window.localStorage.setItem(
        'switch',
        JSON.stringify({ isSwitchOn: state.isSwitchOn }),
      );
    },
      getSwitchState: (state, actions) => {
        let result = JSON.parse(window.localStorage.getItem('switch'));
        if (result) {
          state.isSwitchOn = result.isSwitchOn;
        } else {
          state.isSwitchOn = false;
        }
      },
        
    // toggle.js
        
    useEffect(() => {
      dispatch(getSwitchState());
    }, [dispatch]);

    3.各構成部品へのトピックのリンク


    各構成部品には、トピックとisSwitchonがロードされ、ステータスに関連付けられます.
    // src/pages/Search.js
    const Search = () => {
      const isSwitchOn = useSelector((state) => state.toggleReducer.isSwitchOn);
      const theme = useSelector((state) => state.theme);
    	....
        return (...
     )
    }
    
    // example            
    const SearchInput = styled.input`
      margin-left: 30px;
      width: 80%;
      height: 100%;
      border: none;
      border-bottom: 1px solid
        ${(props) =>
          props.isSwitchOn
            ? props.theme.darkversion.secondary
            : props.theme.lightversion.secondary};
      color: ${(props) => props.isSwitchOn && props.theme.darkversion.fontPrimary};
      background-color: ${(props) =>
        props.isSwitchOn && props.theme.darkversion.background};
      font-size: ${(props) => props.theme.fontSize.md};
      &:focus {
        outline: none;
      }
      ....
    `
    この仕事は本当に時間がかかりました...ううう
    すべて接続し、漏れはありません.

    4.完了




    本当に時間がかかりましたが、終わったらこれほどきれいなものはないことに気づきました!(ダークモードよかったㅠ)
    今回のプロジェクトは、機能ではなくユーザーインタフェースを重視しているようです.
    やったことのないことを実現して、たくさん勉強しました.
    最後の課題なのでちょっと残念