state+components: reimplement 'isDark' as a selector
We now have a consolidated source of truth for whether the UI should us dark mode to accomodate a light icon color. This is a recoil selector that derives from iconColorAtom. In addition, we renamed styleQueryAtom -> iconStyleAtom for consistency.
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { useRecoilState } from "recoil";
|
import { useRecoilState, useRecoilValue } from "recoil";
|
||||||
import TinyColor from "tinycolor2";
|
|
||||||
|
|
||||||
import { iconColorAtom } from "../../state/atoms";
|
import { iconColorAtom } from "../../state/atoms";
|
||||||
|
import { isDarkThemeSelector } from "../../state/selectors";
|
||||||
import useThrottled from "../../hooks/useThrottled";
|
import useThrottled from "../../hooks/useThrottled";
|
||||||
import "./ColorInput.css";
|
import "./ColorInput.css";
|
||||||
|
|
||||||
@@ -10,17 +10,19 @@ type ColorInputProps = {};
|
|||||||
|
|
||||||
const ColorInput: React.FC<ColorInputProps> = () => {
|
const ColorInput: React.FC<ColorInputProps> = () => {
|
||||||
const [color, setColor] = useRecoilState(iconColorAtom);
|
const [color, setColor] = useRecoilState(iconColorAtom);
|
||||||
const isDark = TinyColor(color).isDark();
|
const isDark = useRecoilValue(isDarkThemeSelector);
|
||||||
|
|
||||||
const handleColorChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleColorChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const {
|
const {
|
||||||
target: { value: color },
|
target: { value: color },
|
||||||
} = event;
|
} = event;
|
||||||
if (color[0] === "#") setColor(color);
|
if (color[0] === "#") setColor(color);
|
||||||
};
|
};
|
||||||
|
|
||||||
const throttledColorChange = useThrottled(handleColorChange, 100, [handleColorChange])
|
const throttledColorChange = useThrottled(handleColorChange, 100, [
|
||||||
|
handleColorChange,
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="color-picker">
|
<div className="color-picker">
|
||||||
<input
|
<input
|
||||||
@@ -31,7 +33,7 @@ const ColorInput: React.FC<ColorInputProps> = () => {
|
|||||||
onChange={throttledColorChange}
|
onChange={throttledColorChange}
|
||||||
value={color}
|
value={color}
|
||||||
/>
|
/>
|
||||||
<span style={{ color: isDark ? "white" : "black" }}>{color}</span>
|
<span style={{ color: isDark ? "black" : "white" }}>{color}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,27 +2,26 @@ import React, { useRef, useEffect } from "react";
|
|||||||
import { useRecoilValue } from "recoil";
|
import { useRecoilValue } from "recoil";
|
||||||
import { motion, useAnimation } from "framer-motion";
|
import { motion, useAnimation } from "framer-motion";
|
||||||
import { useWindowSize } from "react-use";
|
import { useWindowSize } from "react-use";
|
||||||
import TinyColor from "tinycolor2";
|
|
||||||
import { IconContext, Warning } from "phosphor-react";
|
import { IconContext, Warning } from "phosphor-react";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
styleQueryAtom,
|
iconStyleAtom,
|
||||||
iconSizeAtom,
|
iconSizeAtom,
|
||||||
iconColorAtom,
|
iconColorAtom,
|
||||||
searchQueryAtom,
|
searchQueryAtom,
|
||||||
} from "../../state/atoms";
|
} from "../../state/atoms";
|
||||||
import { filteredQueryResultsSelector } from "../../state/selectors";
|
import { filteredQueryResultsSelector, isDarkThemeSelector } from "../../state/selectors";
|
||||||
import GridItem from "./IconGridItem";
|
import GridItem from "./IconGridItem";
|
||||||
import "./IconGrid.css";
|
import "./IconGrid.css";
|
||||||
|
|
||||||
type IconGridProps = {};
|
type IconGridProps = {};
|
||||||
|
|
||||||
const IconGridAnimated: React.FC<IconGridProps> = () => {
|
const IconGrid: React.FC<IconGridProps> = () => {
|
||||||
const weight = useRecoilValue(styleQueryAtom);
|
const weight = useRecoilValue(iconStyleAtom);
|
||||||
const size = useRecoilValue(iconSizeAtom);
|
const size = useRecoilValue(iconSizeAtom);
|
||||||
const color = useRecoilValue(iconColorAtom);
|
const color = useRecoilValue(iconColorAtom);
|
||||||
const query = useRecoilValue(searchQueryAtom);
|
const query = useRecoilValue(searchQueryAtom);
|
||||||
const isDark = TinyColor(color).isLight();
|
const isDark = useRecoilValue(isDarkThemeSelector);
|
||||||
|
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
const spans = Math.floor(Math.min(width - 32, 1120) / 168);
|
const spans = Math.floor(Math.min(width - 32, 1120) / 168);
|
||||||
@@ -77,4 +76,4 @@ const IconGridAnimated: React.FC<IconGridProps> = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default IconGridAnimated;
|
export default IconGrid;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { saveAs } from "file-saver";
|
|||||||
import { Icon, Copy, X, CheckCircle, ArchiveDiskDot } from "phosphor-react";
|
import { Icon, Copy, X, CheckCircle, ArchiveDiskDot } from "phosphor-react";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
styleQueryAtom,
|
iconStyleAtom,
|
||||||
iconSizeAtom,
|
iconSizeAtom,
|
||||||
iconColorAtom,
|
iconColorAtom,
|
||||||
iconPreviewOpenAtom,
|
iconPreviewOpenAtom,
|
||||||
@@ -37,7 +37,7 @@ interface InfoPanelProps {
|
|||||||
|
|
||||||
const InfoPanel: React.FC<InfoPanelProps> = (props) => {
|
const InfoPanel: React.FC<InfoPanelProps> = (props) => {
|
||||||
const { index, spans, isDark, name, Icon } = props;
|
const { index, spans, isDark, name, Icon } = props;
|
||||||
const weight = useRecoilValue(styleQueryAtom);
|
const weight = useRecoilValue(iconStyleAtom);
|
||||||
const size = useRecoilValue(iconSizeAtom);
|
const size = useRecoilValue(iconSizeAtom);
|
||||||
const color = useRecoilValue(iconColorAtom);
|
const color = useRecoilValue(iconColorAtom);
|
||||||
const setOpen = useSetRecoilState(iconPreviewOpenAtom);
|
const setOpen = useSetRecoilState(iconPreviewOpenAtom);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useRecoilState } from "recoil";
|
|||||||
import Select from "react-dropdown-select";
|
import Select from "react-dropdown-select";
|
||||||
import { PencilLine } from "phosphor-react";
|
import { PencilLine } from "phosphor-react";
|
||||||
|
|
||||||
import { styleQueryAtom } from "../../state/atoms";
|
import { iconStyleAtom } from "../../state/atoms";
|
||||||
import { IconStyle } from "../../lib";
|
import { IconStyle } from "../../lib";
|
||||||
import "./StyleInput.css";
|
import "./StyleInput.css";
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ const options = [
|
|||||||
type StyleInputProps = {};
|
type StyleInputProps = {};
|
||||||
|
|
||||||
const StyleInput: React.FC<StyleInputProps> = () => {
|
const StyleInput: React.FC<StyleInputProps> = () => {
|
||||||
const [style, setStyle] = useRecoilState(styleQueryAtom);
|
const [style, setStyle] = useRecoilState(iconStyleAtom);
|
||||||
void style;
|
void style;
|
||||||
|
|
||||||
// const handleStyleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
// const handleStyleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const searchQueryAtom = atom<string>({
|
|||||||
default: "",
|
default: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const styleQueryAtom = atom<IconStyle>({
|
export const iconStyleAtom = atom<IconStyle>({
|
||||||
key: "styleQueryAtom",
|
key: "styleQueryAtom",
|
||||||
default: IconStyle.REGULAR,
|
default: IconStyle.REGULAR,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { selector, selectorFamily } from "recoil";
|
import { selector, selectorFamily } from "recoil";
|
||||||
|
import TinyColor from "tinycolor2";
|
||||||
|
|
||||||
import { searchQueryAtom, styleQueryAtom } from "./atoms";
|
import { searchQueryAtom, iconStyleAtom, iconColorAtom } from "./atoms";
|
||||||
import { IconEntry, IconCategory } from "../lib";
|
import { IconEntry, IconCategory } from "../lib";
|
||||||
import { icons } from "../lib/icons";
|
import { icons } from "../lib/icons";
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ export const filteredQueryResultsSelector = selector<Readonly<IconEntry[]>>({
|
|||||||
key: "filteredQueryResultsSelector",
|
key: "filteredQueryResultsSelector",
|
||||||
get: async ({ get }) => {
|
get: async ({ get }) => {
|
||||||
const query = get(searchQueryAtom).trim().toLowerCase();
|
const query = get(searchQueryAtom).trim().toLowerCase();
|
||||||
const style = get(styleQueryAtom);
|
const style = get(iconStyleAtom);
|
||||||
|
|
||||||
if (!query && !style) return icons;
|
if (!query && !style) return icons;
|
||||||
|
|
||||||
@@ -62,3 +63,8 @@ export const singleCategoryQueryResultsSelector = selectorFamily<
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const isDarkThemeSelector = selector<boolean>({
|
||||||
|
key: "isDarkThemeSelector",
|
||||||
|
get: ({ get }) => TinyColor(get(iconColorAtom)).isLight(),
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user