From a6233863da4203bec781e817963ac3733279cab5 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Mon, 17 Jan 2022 22:26:16 +0100 Subject: refactor(settings): make toggle reusable Toggle will be used for others settings so I extract the functionnality from ThemeToggle. --- src/components/Form/Form.module.scss | 8 +++- src/components/Form/Toggle/Toggle.module.scss | 56 ++++++++++++++++++++++ src/components/Form/Toggle/Toggle.tsx | 46 ++++++++++++++++++ src/components/Form/index.tsx | 3 +- src/components/Settings/Settings.tsx | 2 +- .../Settings/ThemeToggle/ThemeToggle.tsx | 36 ++++++++++++++ src/components/ThemeToggle/ThemeToggle.module.scss | 54 --------------------- src/components/ThemeToggle/ThemeToggle.tsx | 45 ----------------- 8 files changed, 148 insertions(+), 102 deletions(-) create mode 100644 src/components/Form/Toggle/Toggle.module.scss create mode 100644 src/components/Form/Toggle/Toggle.tsx create mode 100644 src/components/Settings/ThemeToggle/ThemeToggle.tsx delete mode 100644 src/components/ThemeToggle/ThemeToggle.module.scss delete mode 100644 src/components/ThemeToggle/ThemeToggle.tsx (limited to 'src') diff --git a/src/components/Form/Form.module.scss b/src/components/Form/Form.module.scss index e464293..e805c52 100644 --- a/src/components/Form/Form.module.scss +++ b/src/components/Form/Form.module.scss @@ -4,9 +4,15 @@ width: 100%; &--search, - &--theme { + &--toggle { display: flex; flex-flow: row nowrap; + align-items: center; + } + + &--toggle { + position: relative; + margin: var(--spacing-sm) 0; } &--centered { diff --git a/src/components/Form/Toggle/Toggle.module.scss b/src/components/Form/Toggle/Toggle.module.scss new file mode 100644 index 0000000..e860b5e --- /dev/null +++ b/src/components/Form/Toggle/Toggle.module.scss @@ -0,0 +1,56 @@ +@use "@styles/abstracts/functions" as fun; + +.label { + --icon-size: #{fun.convert-px(25)}; + --toggle-width: #{fun.convert-px(45)}; + --toggle-height: calc(var(--toggle-width) / 2); + + display: inline-flex; + align-items: center; +} + +.title { + margin-right: var(--spacing-xs); +} + +.toggle { + display: inline-flex; + align-items: center; + width: var(--toggle-width); + height: var(--toggle-height); + background: var(--color-shadow-light); + border: fun.convert-px(1) solid var(--color-primary); + border-radius: fun.convert-px(32); + box-shadow: inset 0 0 fun.convert-px(3) 0 var(--color-shadow-dark); + margin: 0 var(--spacing-2xs); + position: relative; + + &::after { + content: ""; + display: block; + width: calc(var(--toggle-width) / 2); + height: calc(var(--toggle-width) / 2); + background: var(--color-primary-lighter); + border: fun.convert-px(1) solid var(--color-primary); + border-radius: 50%; + box-shadow: inset 0 0 fun.convert-px(1) fun.convert-px(1) + var(--color-shadow), + 0 0 fun.convert-px(2) fun.convert-px(1) var(--color-shadow-light); + position: absolute; + left: fun.convert-px(-2); + transition: all 0.3s ease-in-out 0s; + } +} + +.checkbox { + position: absolute; + opacity: 0; + cursor: pointer; + + &:checked ~ .label { + .toggle::after { + position: absolute; + left: calc(100% - (var(--toggle-width) / 2) + #{fun.convert-px(2)}); + } + } +} diff --git a/src/components/Form/Toggle/Toggle.tsx b/src/components/Form/Toggle/Toggle.tsx new file mode 100644 index 0000000..36636e4 --- /dev/null +++ b/src/components/Form/Toggle/Toggle.tsx @@ -0,0 +1,46 @@ +import { FormEvent, ReactElement } from 'react'; +import { Form } from '..'; +import styles from './Toggle.module.scss'; + +const Toggle = ({ + id, + label, + value, + changeHandler, + leftChoice, + rightChoice, + name, +}: { + id: string; + label: string; + value: boolean; + changeHandler: (value: boolean) => void; + leftChoice: ReactElement | string; + rightChoice: ReactElement | string; + name?: string; +}) => { + const onSubmit = (e: FormEvent) => { + e.preventDefault(); + }; + + return ( +
+ changeHandler(!value)} + /> + +
+ ); +}; + +export default Toggle; diff --git a/src/components/Form/index.tsx b/src/components/Form/index.tsx index 987e013..0908e9b 100644 --- a/src/components/Form/index.tsx +++ b/src/components/Form/index.tsx @@ -2,5 +2,6 @@ import Form from './Form'; import FormItem from './FormItem/FormItem'; import Input from './Input/Input'; import TextArea from './TextArea/TextArea'; +import Toggle from './Toggle/Toggle'; -export { Form, FormItem, Input, TextArea }; +export { Form, FormItem, Input, TextArea, Toggle }; diff --git a/src/components/Settings/Settings.tsx b/src/components/Settings/Settings.tsx index bfef851..7d5516c 100644 --- a/src/components/Settings/Settings.tsx +++ b/src/components/Settings/Settings.tsx @@ -1,5 +1,5 @@ import { CogIcon } from '@components/Icons'; -import ThemeToggle from '@components/ThemeToggle/ThemeToggle'; +import ThemeToggle from '@components/Settings/ThemeToggle/ThemeToggle'; import { t } from '@lingui/macro'; import styles from './Settings.module.scss'; diff --git a/src/components/Settings/ThemeToggle/ThemeToggle.tsx b/src/components/Settings/ThemeToggle/ThemeToggle.tsx new file mode 100644 index 0000000..e14f39a --- /dev/null +++ b/src/components/Settings/ThemeToggle/ThemeToggle.tsx @@ -0,0 +1,36 @@ +import { Toggle } from '@components/Form'; +import { MoonIcon, SunIcon } from '@components/Icons'; +import Spinner from '@components/Spinner/Spinner'; +import { t } from '@lingui/macro'; +import { useTheme } from 'next-themes'; +import { useEffect, useState } from 'react'; + +const ThemeToggle = () => { + const [isMounted, setIsMounted] = useState(false); + const { resolvedTheme, setTheme } = useTheme(); + + useEffect(() => { + setIsMounted(true); + }, []); + + if (!isMounted) return ; + + const isDarkTheme = resolvedTheme === 'dark'; + + const updateTheme = () => { + setTheme(isDarkTheme ? 'light' : 'dark'); + }; + + return ( + } + rightChoice={} + value={isDarkTheme} + changeHandler={updateTheme} + /> + ); +}; + +export default ThemeToggle; diff --git a/src/components/ThemeToggle/ThemeToggle.module.scss b/src/components/ThemeToggle/ThemeToggle.module.scss deleted file mode 100644 index 74fb542..0000000 --- a/src/components/ThemeToggle/ThemeToggle.module.scss +++ /dev/null @@ -1,54 +0,0 @@ -@use "@styles/abstracts/functions" as fun; - -.label { - --icon-size: #{fun.convert-px(25)}; - --toggle-width: #{fun.convert-px(45)}; - --toggle-height: calc(var(--toggle-width) / 2); - - display: inline-flex; - align-items: center; -} - -.title { - margin-right: var(--spacing-xs); -} - -.toggle { - display: inline-flex; - align-items: center; - width: var(--toggle-width); - height: var(--toggle-height); - background: var(--color-shadow-light); - border: fun.convert-px(1) solid var(--color-primary); - border-radius: fun.convert-px(32); - box-shadow: inset 0 0 fun.convert-px(3) 0 var(--color-shadow-dark); - margin: 0 var(--spacing-2xs); - position: relative; - - &::after { - content: ""; - display: block; - width: calc(var(--toggle-width) / 2); - height: calc(var(--toggle-width) / 2); - background: var(--color-primary-lighter); - border: fun.convert-px(1) solid var(--color-primary); - border-radius: 50%; - box-shadow: inset 0 0 fun.convert-px(1) fun.convert-px(1) - var(--color-shadow), - 0 0 fun.convert-px(2) fun.convert-px(1) var(--color-shadow-light); - position: absolute; - left: fun.convert-px(-2); - transition: all 0.3s ease-in-out 0s; - } -} - -.checkbox { - position: absolute; - opacity: 0; - - &:checked ~ .label { - .toggle::after { - left: calc(100% - (var(--toggle-width) / 2) + #{fun.convert-px(2)}); - } - } -} diff --git a/src/components/ThemeToggle/ThemeToggle.tsx b/src/components/ThemeToggle/ThemeToggle.tsx deleted file mode 100644 index c44f6df..0000000 --- a/src/components/ThemeToggle/ThemeToggle.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Form } from '@components/Form'; -import { MoonIcon, SunIcon } from '@components/Icons'; -import Spinner from '@components/Spinner/Spinner'; -import { t } from '@lingui/macro'; -import { useTheme } from 'next-themes'; -import { FormEvent, useEffect, useState } from 'react'; -import styles from './ThemeToggle.module.scss'; - -const ThemeToggle = () => { - const [isMounted, setIsMounted] = useState(false); - const { resolvedTheme, setTheme } = useTheme(); - - useEffect(() => { - setIsMounted(true); - }, []); - - const onSubmit = (e: FormEvent) => { - e.preventDefault(); - }; - - if (!isMounted) return ; - - const isDarkTheme = resolvedTheme === 'dark'; - - return ( -
- setTheme(isDarkTheme ? 'light' : 'dark')} - /> - -
- ); -}; - -export default ThemeToggle; -- cgit v1.2.3