Skip to content

Commit

Permalink
refactor: separate toggle component
Browse files Browse the repository at this point in the history
  • Loading branch information
Bartek532 committed Mar 1, 2024
1 parent 952dbfe commit 1e9c9ad
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 17 deletions.
2 changes: 1 addition & 1 deletion components/blog/listing/PostsListing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
connectStateResults,
} from "react-instantsearch-dom";

import { SearchBox } from "components/common/search/SearchBox";
import { SearchBox } from "components/common/input/search/SearchBox";
import { Skeleton } from "components/common/skeleton/Skeleton";
import { allCategories } from "data/categories";
import { env } from "env/client";
Expand Down
File renamed without changes.
25 changes: 25 additions & 0 deletions components/common/input/toggle/Toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { memo } from "react";

import styles from "./toggle.module.scss";

type ToggleProps = {
readonly value: boolean;
readonly onChange: (value: boolean) => void;
readonly children: React.ReactNode;
};

export const Toggle = memo<ToggleProps>(({ value, onChange, children }) => (
<>
<input
type="checkbox"
className={styles.checkbox}
onChange={(e) => onChange(e.target.checked)}
checked={value}
/>
<div className={styles.toggle}>
<div className={styles.icon}>{children}</div>
</div>
</>
));

Toggle.displayName = "Toggle";
46 changes: 46 additions & 0 deletions components/common/input/toggle/toggle.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
@use "styles/_mixins";

.checkbox {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}

.toggle {
--size: 1.5rem;
--wrapperPadding: 0.2rem;
position: absolute;
top: 50%;
left: 50%;
background-color: var(--gray-100);
transform: translate(-50%, -50%);
border-radius: 2rem;
width: calc(var(--size) * 4);
padding: var(--wrapperPadding);

@include mixins.mediaquery("sm") {
--size: 2rem;
--wrapperPadding: 0.3rem;
border-radius: 3rem;
}

.icon {
width: calc(var(--size) * 2);
height: calc(var(--size) * 2);
background-color: var(--white-100);
border-radius: 50%;
@include mixins.flex;
transition: transform 0.2s ease-in-out;

svg {
width: var(--size);
height: var(--size);
}
}
}

.checkbox:checked ~ .toggle .icon {
transform: translateX(calc(var(--size) * 2 - var(--wrapperPadding) * 2));
}
23 changes: 16 additions & 7 deletions components/common/theme/ThemeSwitcher.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"use client";

import { motion } from "framer-motion";
import { memo } from "react";

import { useTheme } from "providers/ThemeProvider";

import { Toggle } from "../input/toggle/Toggle";

import { moon, sun } from "./consts";
import styles from "./themeSwitcher.module.scss";

const MoonIcon = () => (
<motion.svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" key="moon">
Expand Down Expand Up @@ -72,23 +74,30 @@ const SunIcon = () => (
</motion.svg>
);

export const ThemeSwitcher = () => {
interface ThemeSwitcherProps {
readonly className?: string | undefined;
}

export const ThemeSwitcher = memo<ThemeSwitcherProps>(({ className }) => {
const { theme, toggleTheme } = useTheme();

return (
<>
<label className={className}>
<span className="sr-only">change theme to {theme === "dark" ? "light" : "dark"}</span>
<input
<Toggle value={theme === "light"} onChange={toggleTheme}>
{theme === "light" ? <SunIcon /> : <MoonIcon />}
</Toggle>
{/* <input
type="checkbox"
className={styles.checkbox}
onChange={toggleTheme}
checked={theme === "light"}
/>
<div className={styles.toggle}>
<div className={styles.icon}>{theme === "light" ? <SunIcon /> : <MoonIcon />}</div>
</div>
</>
</div> */}
</label>
);
};
});

ThemeSwitcher.displayName = "ThemeSwitcher";
4 changes: 1 addition & 3 deletions components/layout/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ export const Header = () => (
</Link>
<Navbar routes={routes} />
<div className={styles.right}>
<label className={styles.theme}>
<ThemeSwitcher />
</label>
<ThemeSwitcher className={styles.theme} />
<Link href="/contact" className={styles.contact}>
Contact
<PaperPlane />
Expand Down
6 changes: 1 addition & 5 deletions components/tile/theme/ThemeTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ import { ThemeSwitcher } from "components/common/theme/ThemeSwitcher";

import styles from "./themeTile.module.scss";

export const ThemeTile = () => (
<label className={styles.tile}>
<ThemeSwitcher />
</label>
);
export const ThemeTile = () => <ThemeSwitcher className={styles.tile} />;

ThemeTile.displayName = "ThemeTile";
2 changes: 1 addition & 1 deletion components/work/listing/ProjectsListing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import algoliasearch from "algoliasearch";
import Image from "next/image";
import { InstantSearch, connectHits, connectStateResults } from "react-instantsearch-dom";

import { SearchBox } from "components/common/search/SearchBox";
import { SearchBox } from "components/common/input/search/SearchBox";
import { Skeleton } from "components/common/skeleton/Skeleton";
import { env } from "env/client";
import DisappointedAvatar from "public/img/avatars/disappointed.png";
Expand Down

0 comments on commit 1e9c9ad

Please sign in to comment.