diff --git a/index.html b/index.html index abb4b9c..a3e846c 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ - + Algo Visualizer diff --git a/public/ham.svg b/public/icons/ham.svg similarity index 100% rename from public/ham.svg rename to public/icons/ham.svg diff --git a/public/icons/moon.svg b/public/icons/moon.svg new file mode 100644 index 0000000..4b1f21a --- /dev/null +++ b/public/icons/moon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/pause.svg b/public/icons/pause.svg similarity index 100% rename from public/pause.svg rename to public/icons/pause.svg diff --git a/public/play.svg b/public/icons/play.svg similarity index 100% rename from public/play.svg rename to public/icons/play.svg diff --git a/public/reset.svg b/public/icons/reset.svg similarity index 100% rename from public/reset.svg rename to public/icons/reset.svg diff --git a/public/icons/sun.svg b/public/icons/sun.svg new file mode 100644 index 0000000..3634a20 --- /dev/null +++ b/public/icons/sun.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/public/vite.svg b/public/icons/vite.svg similarity index 100% rename from public/vite.svg rename to public/icons/vite.svg diff --git a/public/bar.png b/public/images/bar.png similarity index 100% rename from public/bar.png rename to public/images/bar.png diff --git a/public/cell.png b/public/images/cell.png similarity index 100% rename from public/cell.png rename to public/images/cell.png diff --git a/src/apps/sorting-visualizer/components/bar/bar-ui.tsx b/src/apps/sorting-visualizer/components/bar/bar-ui.tsx index 466263e..63f7af7 100644 --- a/src/apps/sorting-visualizer/components/bar/bar-ui.tsx +++ b/src/apps/sorting-visualizer/components/bar/bar-ui.tsx @@ -1,27 +1,26 @@ import { UIProps } from "@/apps/sorting-visualizer/models/interfaces"; import classes from "./bar.module.scss"; -import { colors } from "@/apps/sorting-visualizer/config"; import { useMemo } from "react"; -function BarUI({ array, sortPositions, highlightPositions, pivot }: UIProps) { +function BarUI({ array, sorts, highlights, pivot }: UIProps) { const max = useMemo(() => Math.max(...array), [array]); function getBarColor(idx: number) { - let backgroundColor = ""; + let cellClass = ""; if (pivot === idx) { - backgroundColor = colors.pivot; + cellClass = "pivot"; } - if (highlightPositions.includes(idx)) { - backgroundColor = colors.highlight; + if (sorts.includes(idx)) { + cellClass = "sort"; } - if (sortPositions.includes(idx)) { - backgroundColor = colors.sort; + if (highlights.includes(idx)) { + cellClass = "highlight"; } - return backgroundColor; + return cellClass; } return ( @@ -30,9 +29,9 @@ function BarUI({ array, sortPositions, highlightPositions, pivot }: UIProps) { {array.map((item, idx) => (
  • ))} diff --git a/src/apps/sorting-visualizer/components/bar/bar.module.scss b/src/apps/sorting-visualizer/components/bar/bar.module.scss index c05ea10..168f7c8 100644 --- a/src/apps/sorting-visualizer/components/bar/bar.module.scss +++ b/src/apps/sorting-visualizer/components/bar/bar.module.scss @@ -1,7 +1,9 @@ +@use "/src/apps/sorting-visualizer/styles/cell-colors"; + .arrayContainer { + position: relative; padding: 25px 0 40px; overflow-x: auto; - position: relative; .values { display: flex; @@ -9,13 +11,15 @@ height: var(--bar-max-height); li { - border: 1px solid var(--bar-bg); + flex-shrink: 1; width: var(--bar-size); min-width: var(--bar-min-size); - background-color: var(--bar-bg); - flex-shrink: 1; margin: 0 calc(var(--bar-margin) / 2); + background-color: var(--color-bar); + border: 1px solid var(--color-bar); } + + @include cell-colors.sort-status-colors; } .indices { @@ -27,9 +31,9 @@ opacity: 0.4; li { + flex-shrink: 1; width: var(--bar-size); min-width: var(--bar-min-size); - flex-shrink: 1; margin: 0 calc(var(--bar-margin) / 2); } } diff --git a/src/apps/sorting-visualizer/components/cell/cell-ui.tsx b/src/apps/sorting-visualizer/components/cell/cell-ui.tsx index 0cf75b5..c64eb36 100644 --- a/src/apps/sorting-visualizer/components/cell/cell-ui.tsx +++ b/src/apps/sorting-visualizer/components/cell/cell-ui.tsx @@ -6,34 +6,34 @@ import classes from "./cell.module.scss"; const CellUI = function CellUI({ array, - swapPositions, - sortPositions, - highlightPositions, - movePositions, + swaps, + sorts, + highlights, + moves, pivot, }: UIProps) { function getCell(idx: number, item: number) { - if (swapPositions.includes(idx)) { + if (swaps.includes(idx)) { return ( ); } - if (movePositions && idx >= movePositions[0] && idx <= movePositions[1]) { + if (moves && idx >= moves[0] && idx <= moves[1]) { return ( ); } @@ -43,8 +43,8 @@ const CellUI = function CellUI({ key={idx} order={idx} value={item} - isSorted={sortPositions.includes(idx)} - isHighlighted={highlightPositions.includes(idx)} + isSorted={sorts.includes(idx)} + isHighlighted={highlights.includes(idx)} isPivot={idx === pivot} /> ); diff --git a/src/apps/sorting-visualizer/components/cell/cell.module.scss b/src/apps/sorting-visualizer/components/cell/cell.module.scss index 3d1bf4d..808bc2d 100644 --- a/src/apps/sorting-visualizer/components/cell/cell.module.scss +++ b/src/apps/sorting-visualizer/components/cell/cell.module.scss @@ -1,3 +1,6 @@ +@use "/src/styles/theme"; +@use "/src/apps/sorting-visualizer/styles/cell-colors"; + .arrayContainer { position: relative; padding: 0 20px; @@ -15,10 +18,14 @@ width: var(--cell-size); height: var(--cell-size); margin: 0 calc(var(--cell-margin) / 2); - border: 1px solid black; + color: black; + background-color: white; + border: 1px solid theme.$base; border-radius: 4px; - box-shadow: 0 4px 4px rgb(0 0 0 / 10%); + box-shadow: 0 4px 4px theme.$shadow1; } + + @include cell-colors.sort-status-colors; } .indices { diff --git a/src/apps/sorting-visualizer/components/cell/cell.tsx b/src/apps/sorting-visualizer/components/cell/cell.tsx index 87e091f..2d1bec0 100644 --- a/src/apps/sorting-visualizer/components/cell/cell.tsx +++ b/src/apps/sorting-visualizer/components/cell/cell.tsx @@ -1,6 +1,5 @@ import { CellProps } from "@/apps/sorting-visualizer/models/interfaces"; import classes from "./cell.module.scss"; -import { colors } from "@/apps/sorting-visualizer/config"; function Cell({ order, @@ -10,27 +9,26 @@ function Cell({ isHighlighted = false, isPivot = false, }: CellProps) { - let backgroundColor = ""; + let cellClass = ""; if (isPivot) { - backgroundColor = colors.pivot; + cellClass = "pivot"; } - if (isHighlighted) { - backgroundColor = colors.highlight; + if (isSorted) { + cellClass = "sort"; } - if (isSorted) { - backgroundColor = colors.sort; + if (isHighlighted) { + cellClass = "highlight"; } return (
  • {value} diff --git a/src/apps/sorting-visualizer/components/controller/controls.module.scss b/src/apps/sorting-visualizer/components/controller/controls.module.scss index a61cbaf..ee189cc 100644 --- a/src/apps/sorting-visualizer/components/controller/controls.module.scss +++ b/src/apps/sorting-visualizer/components/controller/controls.module.scss @@ -1,3 +1,5 @@ +@use "/src/styles/theme"; + .controllerWrapper { padding: 0 20px; margin-bottom: 16px; @@ -12,9 +14,11 @@ gap: 16px; .arrayInput { - width: 100%; flex: 1; + width: 100%; padding: 5px; + color: black; + background-color: white; border: 1px solid black; border-radius: 4px; } @@ -27,7 +31,7 @@ .rndmBtn { padding: 5px 10px; color: white; - background-color: #2b4bfe; + background-color: theme.$primary; border: none; border-radius: 4px; } @@ -86,9 +90,9 @@ .switchContainer { display: flex; + gap: 20px; align-items: center; justify-content: center; - gap: 20px; } @media screen and (width >= 960px) { @@ -100,3 +104,16 @@ } } } + +@media screen and (prefers-color-scheme: dark) { + img { + filter: invert(1); + } +} + +[data-theme="dark"] { + /* stylelint-disable-next-line no-descending-specificity */ + .controllerWrapper img { + filter: invert(1); + } +} diff --git a/src/apps/sorting-visualizer/components/controller/execution.tsx b/src/apps/sorting-visualizer/components/controller/execution.tsx index a4fefa1..a6ab6f7 100644 --- a/src/apps/sorting-visualizer/components/controller/execution.tsx +++ b/src/apps/sorting-visualizer/components/controller/execution.tsx @@ -7,9 +7,9 @@ import { import { useAppDispatch, useAppSelector } from "@/store/hooks"; import classes from "./controls.module.scss"; -import pauseIcon from "/pause.svg"; -import playIcon from "/play.svg"; -import resetIcon from "/reset.svg"; +import pauseIcon from "/icons/pause.svg"; +import playIcon from "/icons/play.svg"; +import resetIcon from "/icons/reset.svg"; import { useEffect } from "react"; function Execution() { diff --git a/src/apps/sorting-visualizer/components/controller/type-switch.tsx b/src/apps/sorting-visualizer/components/controller/type-switch.tsx index fa70bb8..b72afa4 100644 --- a/src/apps/sorting-visualizer/components/controller/type-switch.tsx +++ b/src/apps/sorting-visualizer/components/controller/type-switch.tsx @@ -22,16 +22,19 @@ function TypeSwitch() { return (
    - Cell + dispatch(toggleVisualizerType())} checked={visualizerType === "bar"} checkedIcon={false} uncheckedIcon={false} height={20} width={40} + offColor="#2b4bfe" + onColor="#2b4bfe" /> - Bar +
    ); } diff --git a/src/apps/sorting-visualizer/components/navbar/navbar.module.scss b/src/apps/sorting-visualizer/components/navbar/navbar.module.scss index 2e7122a..21e7e32 100644 --- a/src/apps/sorting-visualizer/components/navbar/navbar.module.scss +++ b/src/apps/sorting-visualizer/components/navbar/navbar.module.scss @@ -1,3 +1,5 @@ +@use "/src/styles/theme"; + .navbar { position: relative; display: flex; @@ -5,7 +7,7 @@ justify-content: space-between; padding: 12px 20px; margin-bottom: 24px; - box-shadow: 0 4px 4px rgb(0 0 0 / 15%); + box-shadow: 0 4px 4px theme.$shadow1; img { width: 25px; @@ -33,8 +35,8 @@ width: 100%; padding-bottom: 12px; list-style: none; - background-color: white; - box-shadow: 0 4px 4px rgb(0 0 0 / 15%); + background-color: theme.$background; + box-shadow: 0 4px 4px theme.$shadow1; &[data-toggle="false"] { display: none; @@ -43,23 +45,22 @@ li { width: 100%; padding: 10px; - background-color: white; a { display: block; width: auto; - padding: 8px; + padding: 8px 6px; text-transform: capitalize; border-radius: 8px; } a.active { color: white; - background-color: rgb(255 64 0); + background-color: theme.$primary; } a:hover { - outline: 1px solid rgb(255 163 132); + outline: 1px solid theme.$primary; } } } @@ -86,3 +87,19 @@ } } } + +@media screen and (prefers-color-scheme: dark) { + .navbar { + img { + filter: invert(1); + } + } +} + +[data-theme="dark"] { + .navbar { + img { + filter: invert(1); + } + } +} diff --git a/src/apps/sorting-visualizer/components/navbar/navbar.tsx b/src/apps/sorting-visualizer/components/navbar/navbar.tsx index 410a305..d45507e 100644 --- a/src/apps/sorting-visualizer/components/navbar/navbar.tsx +++ b/src/apps/sorting-visualizer/components/navbar/navbar.tsx @@ -1,7 +1,7 @@ import { NavLink } from "react-router-dom"; import { NavbarProps } from "@/apps/sorting-visualizer/models/interfaces"; import classes from "./navbar.module.scss"; -import hamIcon from "/ham.svg"; +import hamIcon from "/icons/ham.svg"; import { useState } from "react"; function Navbar({ menuItems }: NavbarProps) { diff --git a/src/apps/sorting-visualizer/components/visualizer/visualizer.module.scss b/src/apps/sorting-visualizer/components/visualizer/visualizer.module.scss index f387e97..2894f05 100644 --- a/src/apps/sorting-visualizer/components/visualizer/visualizer.module.scss +++ b/src/apps/sorting-visualizer/components/visualizer/visualizer.module.scss @@ -1,9 +1,11 @@ +@use "/src/styles/theme"; + .container { display: inline-block; min-width: 300px; max-width: 100%; padding: 20px; - box-shadow: 0 0 4px rgb(0 0 0 / 40%); + box-shadow: 0 0 4px theme.$shadow2; header, footer { diff --git a/src/apps/sorting-visualizer/components/visualizer/visualizer.tsx b/src/apps/sorting-visualizer/components/visualizer/visualizer.tsx index 6392642..7c8601e 100644 --- a/src/apps/sorting-visualizer/components/visualizer/visualizer.tsx +++ b/src/apps/sorting-visualizer/components/visualizer/visualizer.tsx @@ -15,14 +15,14 @@ const Visualizer = function Visualizer({ const sortingArray = useRef([...array]); const { + swapCount, + compareCount, + isCompleted, swaps, + sorts, + highlights, pivot, - compares, - isCompleted, - swapPositions, - sortPositions, - highlightPositions, - movePositions, + moves, } = useAlgo(sortingArray.current, algoFn); useEffect(() => { @@ -38,18 +38,18 @@ const Visualizer = function Visualizer({
    - Swaps: {swaps} + Swaps: {swapCount} - Comparisons: {compares} + Comparisons: {compareCount}
    diff --git a/src/apps/sorting-visualizer/config.ts b/src/apps/sorting-visualizer/config.ts index 4a39bf5..84aacb8 100644 --- a/src/apps/sorting-visualizer/config.ts +++ b/src/apps/sorting-visualizer/config.ts @@ -27,8 +27,11 @@ export const selectedAlgosStatus = algoList.map(() => true); const root = document.querySelector(":root") as HTMLElement; root.style.setProperty("--cell-size", `${cellCSS.size}px`); root.style.setProperty("--cell-margin", `${cellCSS.margin}px`); -root.style.setProperty("--bar-bg", `${colors.bar}`); root.style.setProperty("--bar-size", `${barCSS.size}px`); root.style.setProperty("--bar-min-size", `${barCSS.minSize}px`); root.style.setProperty("--bar-max-height", `${barCSS.maxHeight}px`); root.style.setProperty("--bar-margin", `${barCSS.margin}px`); +root.style.setProperty("--color-sort", colors.sort); +root.style.setProperty("--color-highlight", colors.highlight); +root.style.setProperty("--color-pivot", colors.pivot); +root.style.setProperty("--color-bar", colors.bar); diff --git a/src/apps/sorting-visualizer/hooks/use-algo.hook.tsx b/src/apps/sorting-visualizer/hooks/use-algo.hook.tsx index 8cfdf75..fd3e401 100644 --- a/src/apps/sorting-visualizer/hooks/use-algo.hook.tsx +++ b/src/apps/sorting-visualizer/hooks/use-algo.hook.tsx @@ -7,50 +7,50 @@ function useAlgo( array: number[], algorithm: (array: number[]) => SortAsyncGenerator ) { - const [swapPositions, setSwapPositions] = useState([-1, -1]); - const [movePositions, setMovePositions] = useState([-1, -1]); - const [sortPositions, setSortPositions] = useState([]); - const [highlightPositions, setHighlightPositions] = useState([-1, -1]); + const [swaps, setSwaps] = useState([-1, -1]); + const [moves, setMoves] = useState([-1, -1]); + const [sorts, setSorts] = useState([]); + const [highlights, setHighlights] = useState([-1, -1]); const [pivot, setPivot] = useState(-1); const [isCompleted, setIsCompleted] = useState(false); const it = useRef(algorithm(array)); - const swaps = useRef(0); - const compares = useRef(0); + const swapCount = useRef(0); + const compareCount = useRef(0); const fn = async () => { await resolveWhenPlaying; for await (const data of it.current) { - setSwapPositions([-1, -1]); - setHighlightPositions([-1, -1]); - setMovePositions([-1, -1]); + setSwaps([-1, -1]); + setHighlights([-1, -1]); + setMoves([-1, -1]); switch (data.type) { case "swap": - setHighlightPositions(data.positions); - setSwapPositions(data.positions); + setHighlights(data.positions); + setSwaps(data.positions); if (data.positions[0] !== data.positions[1]) { - swaps.current++; + swapCount.current++; } break; case "sort": - setSortPositions((arr) => [...arr, data.position]); + setSorts((arr) => [...arr, data.position]); break; case "highlight": - setHighlightPositions(data.positions); + setHighlights(data.positions); if (data.positions[0] !== data.positions[1]) { - compares.current++; + compareCount.current++; } break; case "pivot": setPivot(data.position); break; case "move": - setHighlightPositions([data.positions[0], data.positions[0] + 1]); - setMovePositions(data.positions); + setHighlights([data.positions[0], data.positions[0] + 1]); + setMoves(data.positions); if (data.positions[0] !== data.positions[1]) { - swaps.current++; + swapCount.current++; } break; } @@ -66,12 +66,12 @@ function useAlgo( return { pivot, isCompleted, - swapPositions, - sortPositions, - highlightPositions, - movePositions, - swaps: swaps.current, - compares: compares.current, + swaps, + sorts, + highlights, + moves, + swapCount: swapCount.current, + compareCount: compareCount.current, }; } diff --git a/src/apps/sorting-visualizer/layouts/layout.module.scss b/src/apps/sorting-visualizer/layouts/layout.module.scss index c82df55..f7058bc 100644 --- a/src/apps/sorting-visualizer/layouts/layout.module.scss +++ b/src/apps/sorting-visualizer/layouts/layout.module.scss @@ -10,3 +10,21 @@ justify-content: center; margin: 30px 0; } + +.iconBtn { + position: absolute; + right: 25px; + bottom: 25px; + padding: 5px; + cursor: pointer; + background-color: white; + border: 1px solid black; + border-radius: 50%; + fill: red; + transition: all 0.5s; + + img { + width: 25px; + height: 25px; + } +} diff --git a/src/apps/sorting-visualizer/layouts/main.layout.tsx b/src/apps/sorting-visualizer/layouts/main.layout.tsx index 0e9a812..a103394 100644 --- a/src/apps/sorting-visualizer/layouts/main.layout.tsx +++ b/src/apps/sorting-visualizer/layouts/main.layout.tsx @@ -1,15 +1,49 @@ +import { PropsWithChildren, useEffect } from "react"; +import { useAppDispatch, useAppSelector } from "@/store/hooks"; + import Controller from "@/apps/sorting-visualizer/components/controller/controller"; import Navbar from "@/apps/sorting-visualizer/components/navbar/navbar"; -import { PropsWithChildren } from "react"; +import { Theme } from "@/types/interfaces"; import classes from "./layout.module.scss"; import { menuItems } from "@/apps/sorting-visualizer/config"; +import moonIcon from "/icons/moon.svg"; +import { setTheme } from "@/store/app.slice"; +import sunIcon from "/icons/sun.svg"; + +const SunIcon = dark mode; +const MoonIcon = dark mode; function MainLayout({ children }: PropsWithChildren) { + const dispatch = useAppDispatch(); + const storeTheme = useAppSelector((state) => state.app.theme); + const cssTheme = window.matchMedia("(prefers-color-scheme: dark)").matches + ? Theme.DARK + : Theme.LIGHT; + const currentTheme = storeTheme ?? cssTheme; + + useEffect(() => { + dispatch(setTheme(currentTheme)); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + return ( -
    +
    -
    {children}
    +
    + {children} + + +
    ); } diff --git a/src/apps/sorting-visualizer/models/interfaces.ts b/src/apps/sorting-visualizer/models/interfaces.ts index 1404897..8611a28 100644 --- a/src/apps/sorting-visualizer/models/interfaces.ts +++ b/src/apps/sorting-visualizer/models/interfaces.ts @@ -19,10 +19,10 @@ export interface MovingCellProps { export interface UIProps { array: number[]; - swapPositions: number[]; - sortPositions: number[]; - highlightPositions: number[]; - movePositions?: number[]; + swaps: number[]; + sorts: number[]; + highlights: number[]; + moves?: number[]; pivot?: number; } diff --git a/src/apps/sorting-visualizer/styles/_cell-colors.scss b/src/apps/sorting-visualizer/styles/_cell-colors.scss new file mode 100644 index 0000000..a6fe30b --- /dev/null +++ b/src/apps/sorting-visualizer/styles/_cell-colors.scss @@ -0,0 +1,13 @@ +@mixin sort-status-colors { + .pivot { + background-color: var(--color-pivot); + } + + .sort { + background-color: var(--color-sort); + } + + .highlight { + background-color: var(--color-highlight); + } +} diff --git a/src/index.scss b/src/index.scss index a5a75f8..e81ac5a 100644 --- a/src/index.scss +++ b/src/index.scss @@ -1,11 +1,34 @@ -/* stylelint-disable */ -@use "./styles/tooltip.scss"; -@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"); - +/* stylelint-disable scss/at-rule-no-unknown */ +@use "./styles/tooltip"; +@use "./styles/themes/light"; +@use "./styles/themes/dark"; +@use "./styles/theme"; +@import "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"; @tailwind base; @tailwind components; @tailwind utilities; +:root { + @include light.light-theme; +} + +@media screen and (prefers-color-scheme: dark) { + :root { + @include dark.dark-theme; + } +} + +html[data-theme="light"] { + @include light.light-theme; +} + +html[data-theme="dark"] { + @include dark.dark-theme; +} + body { - font-family: "Inter", sans-serif; + font-family: Inter, sans-serif; + color: theme.$base; + background-color: theme.$background; + transition: all 0.25s; } diff --git a/src/store/app.slice.ts b/src/store/app.slice.ts new file mode 100644 index 0000000..8ee7453 --- /dev/null +++ b/src/store/app.slice.ts @@ -0,0 +1,22 @@ +import { AppState, Theme } from "@/types/interfaces"; + +import type { PayloadAction } from "@reduxjs/toolkit"; +import { createSlice } from "@reduxjs/toolkit"; + +const initialState: AppState = { + theme: null, +}; + +export const appSlice = createSlice({ + name: "app", + initialState, + reducers: { + setTheme: (state, action: PayloadAction) => { + state.theme = action.payload; + document.documentElement.setAttribute("data-theme", action.payload); + }, + }, +}); + +export const { setTheme } = appSlice.actions; +export default appSlice.reducer; diff --git a/src/store/store.ts b/src/store/store.ts index f043222..294065a 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -9,19 +9,25 @@ import { persistStore, } from "redux-persist"; +import appReducer from "./app.slice"; import { configureStore } from "@reduxjs/toolkit"; import sortingVisualizerReducer from "@/apps/sorting-visualizer/store/sorting-visualizer.slice"; import storage from "redux-persist/lib/storage"; -const persistConfig = { - key: "sorting-viz", - storage, -}; - export const store = configureStore({ reducer: { + app: persistReducer>( + { + key: "app", + storage, + }, + appReducer + ), sortViz: persistReducer>( - persistConfig, + { + key: "sorting-viz", + storage, + }, sortingVisualizerReducer ), }, diff --git a/src/styles/_colors.scss b/src/styles/_colors.scss new file mode 100644 index 0000000..eef5f56 --- /dev/null +++ b/src/styles/_colors.scss @@ -0,0 +1,7 @@ +$white: white; +$black: black; +$white1: rgb(256 256 256 / 15%); +$white2: rgb(256 256 256 / 40%); +$black1: rgb(0 0 0 / 15%); +$black2: rgb(0 0 0 / 40%); +$blue1: #2b4bfe; diff --git a/src/styles/theme.scss b/src/styles/theme.scss new file mode 100644 index 0000000..d385e75 --- /dev/null +++ b/src/styles/theme.scss @@ -0,0 +1,5 @@ +$base: var(--base); +$background: var(--background); +$primary: var(--primary); +$shadow1: var(--shadow1); +$shadow2: var(--shadow2); diff --git a/src/styles/themes/_dark.scss b/src/styles/themes/_dark.scss new file mode 100644 index 0000000..82565c5 --- /dev/null +++ b/src/styles/themes/_dark.scss @@ -0,0 +1,9 @@ +@use "../colors"; + +@mixin dark-theme { + --base: #{colors.$white}; + --background: #{colors.$black}; + --primary: #{colors.$blue1}; + --shadow1: #{colors.$white1}; + --shadow2: #{colors.$white2}; +} diff --git a/src/styles/themes/_light.scss b/src/styles/themes/_light.scss new file mode 100644 index 0000000..c2f2f82 --- /dev/null +++ b/src/styles/themes/_light.scss @@ -0,0 +1,9 @@ +@use "../colors"; + +@mixin light-theme { + --base: #{colors.$black}; + --background: #{colors.$white}; + --primary: #{colors.$blue1}; + --shadow1: #{colors.$black1}; + --shadow2: #{colors.$black2}; +} diff --git a/src/styles/tooltip.scss b/src/styles/tooltip.scss index 136af26..7d08122 100644 --- a/src/styles/tooltip.scss +++ b/src/styles/tooltip.scss @@ -1,30 +1,32 @@ -[data-tooltip] { - position: relative; -} +@media screen and (width >= 960px) { + [data-tooltip] { + position: relative; + } -[data-tooltip]:hover:after { - content: attr(data-tooltip); - position: absolute; - background-color: #333; - padding: 5px; - border-radius: 4px; - transform: translate(-50%, 100%); - color: #fff; - bottom: -6px; - left: 50%; - text-align: center; - font-size: 0.75rem; - transition: opacity 0.3s ease-in-out; - z-index: 1; -} + [data-tooltip]:hover::after { + position: absolute; + bottom: -6px; + left: 50%; + z-index: 1; + padding: 5px; + font-size: 0.75rem; + color: #fff; + text-align: center; + content: attr(data-tooltip); + background-color: #333; + border-radius: 4px; + transition: opacity 0.3s ease-in-out; + transform: translate(-50%, 100%); + } -[data-tooltip]:hover:before { - content: ""; - position: absolute; - bottom: -6px; - left: 50%; - transform: translateX(-50%); - border-width: 0 6px 10px 6px; - border-style: solid; - border-color: transparent transparent #333 transparent; + [data-tooltip]:hover::before { + position: absolute; + bottom: -6px; + left: 50%; + content: ""; + border-color: transparent transparent #333; + border-style: solid; + border-width: 0 6px 10px; + transform: translateX(-50%); + } } diff --git a/src/types/interfaces.ts b/src/types/interfaces.ts new file mode 100644 index 0000000..06da05b --- /dev/null +++ b/src/types/interfaces.ts @@ -0,0 +1,8 @@ +export const enum Theme { + LIGHT = "light", + DARK = "dark", +} + +export interface AppState { + theme: null | Theme; +}