Переключение между переменными CSS на основе состояний

Я пытаюсь внедрить цветовые темы в свое приложение для реагирования и использовал переменные css, и пока основы работают.

Однако я также пытаюсь применить тему к значку SVG, который меняет цвет в зависимости от состояния. Он меняется с серого на цвет, который определяется темой, когда телефон подключается к устройству.

У меня есть themes.css, который выглядит так:

    :root {
    --fillInactive: #7c7c7c;
}

[data-theme='Blue'] {
    --fillHover: #708fa8;
    --fillActive: #3f77a4;
}

[data-theme='Red'] {
    --fillHover: #cd6969;
    --fillActive: #cd2424;

}

[data-theme='Green'] {
    --fillHover: #85b08e;
    --fillActive: #41ad56;
}

[data-theme='White'] {
    --fillHover: #9f9f9f;
    --fillActive: #ffffff;
}

Мой topbar.js выглядит так:

import React from "react";
import { useState, useEffect } from "react";
import "./topbar.scss";
import "../components/themes.scss"

const electron = window.require('electron');
const { ipcRenderer } = electron;

const TopBar = () => {

  const Store = window.require('electron-store');
  const store = new Store();

  const [phoneState, setPhoneState] = useState("#7c7c7c");
  const [theme, setTheme] = useState(store.get("colorTheme"));

  const plugged = () => {
    setPhoneState("#3f77a4");
  }

  const unplugged = () => {
    setPhoneState("#7c7c7c");
  }

  useEffect(() => {
    ipcRenderer.send('statusReq');
    ipcRenderer.on("plugged", plugged);
    ipcRenderer.on("unplugged", unplugged);

    return function cleanup() {
      ipcRenderer.removeListener('plugged',   plugged);
      ipcRenderer.removeListener('unplugged', unplugged);
      
    };
  }, []);

  return (
    <div className = "topbar" data-theme = {theme}}>
      <div className = "topbar__info">
        <svg className = "topbar__icon">
          <use xlinkHref = "./svg/phone.svg#phone" color = {phoneState}></use>
        </svg>
      </div>
    </div>

  );
};

export default TopBar;

Мой TopBar.scss выглядит так:

.topbar {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    position: absolute;
    top: 0;

    height: 66px;
    width: 100%;
    background: #000000;

    &__info {
      margin-left: 3rem;
    }

    &__icon {
      &__phone {
      }
      margin-top: 1rem;
      margin-right:1rem;
      width:  1rem;
      height: 1rem;
    }
  }

На данный момент я жестко запрограммировал синий цвет в свой JS, но хотел бы, чтобы свойство --fillActive устанавливалось для SVG, когда телефон подключен, в зависимости от выбранной темы. Когда телефон отключен от сети, он должен переключиться на «--fillInactive», чтобы он снова стал серым.

Надеюсь, мой вопрос достаточно конкретен. Я попытался найти решение в Google, но я даже не уверен, что то, что я пытаюсь сделать, - правильный путь, поэтому найти хороший поисковый запрос довольно сложно. Я видел несколько решений, в которых вы можете просто переопределить переменную через javascript, но я хотел бы, чтобы свойства оставались такими, какие они есть, и чтобы я просто выбирал между ними, чтобы установить правильный цвет в зависимости от состояния.

Любая помощь или подсказка высоко ценятся.

🤔 А знаете ли вы, что...
JavaScript позволяет создавать асинхронные запросы к серверу с помощью технологии AJAX.


55
1

Ответ:

Решено

По идее, phoneState может содержать фактическое состояние телефона: plugged/unplugged:

const [phoneState, setPhoneState] = useState(() => 'unplugged');

Затем соответствующий обратный вызов будет переключать состояние:

  useEffect(() => {
    ipcRenderer.send('statusReq');
    ipcRenderer.on("plugged", setPhoneState(() => 'plugged'));
    ipcRenderer.on("unplugged", setPhoneState(() => 'unplugged'));

    return function cleanup() { ... },
 []);

В этом случае phoneState можно использовать для динамического класса какого-либо элемента, например:

return (
    <div className = "topbar" data-theme = {theme}}>
      <div className = {`topbar__info topbar__info--${phoneState}`}>
        <svg className = "topbar__icon">
          <use xlinkHref = "./svg/phone.svg#phone" ></use>
        </svg>
      </div>
    </div>
  );

Затем, когда применяются переменные css, они будут иметь соответствующие значения в соответствии с активной темой.

.topbar {
  &__info{
    &--plugged{
      color: var(--fillActive);
    }
    &--unplugged{
      color: var(--fillInactive);
    }
  }
}