From 4adb8bfdbc86a475d59e1d636927539592ec4b6c Mon Sep 17 00:00:00 2001 From: MAZE Date: Fri, 6 Oct 2023 13:25:39 +0330 Subject: [PATCH] feat: add basic sound components --- .eslintrc.json | 1 + src/components/category/category.tsx | 5 +- src/components/sound/index.ts | 1 + src/components/sound/sound.module.css | 119 ++++++++++++++++++++++++ src/components/sound/sound.tsx | 47 ++++++++++ src/components/sounds/index.ts | 1 + src/components/sounds/sounds.module.css | 6 ++ src/components/sounds/sounds.tsx | 18 ++++ 8 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 src/components/sound/index.ts create mode 100644 src/components/sound/sound.module.css create mode 100644 src/components/sound/sound.tsx create mode 100644 src/components/sounds/index.ts create mode 100644 src/components/sounds/sounds.module.css create mode 100644 src/components/sounds/sounds.tsx diff --git a/.eslintrc.json b/.eslintrc.json index 78ca909..2991f48 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -41,6 +41,7 @@ "prettier/prettier": "error", "sort-keys-fix/sort-keys-fix": ["warn", "asc"], "sort-destructure-keys/sort-destructure-keys": "warn", + "jsx-a11y/no-static-element-interactions": "off", "react/jsx-sort-props": [ "warn", { diff --git a/src/components/category/category.tsx b/src/components/category/category.tsx index 7fce723..2fa91c6 100644 --- a/src/components/category/category.tsx +++ b/src/components/category/category.tsx @@ -1,5 +1,6 @@ import { useMemo } from 'react'; +import { Sounds } from '@/components/sounds'; import { cn } from '@/helpers/styles'; import styles from './category.module.css'; @@ -12,7 +13,7 @@ interface CategoryProps { sounds: Array<{ label: string; src: string }>; } -export function Category({ color, icon, title }: CategoryProps) { +export function Category({ color, icon, sounds, title }: CategoryProps) { const colorStyle = useMemo(() => { const colorToStyle: { [color: string]: string } = { green: styles.green, @@ -30,6 +31,8 @@ export function Category({ color, icon, title }: CategoryProps) {

{title}

+ + ); } diff --git a/src/components/sound/index.ts b/src/components/sound/index.ts new file mode 100644 index 0000000..41a202a --- /dev/null +++ b/src/components/sound/index.ts @@ -0,0 +1 @@ +export { Sound } from './sound'; diff --git a/src/components/sound/sound.module.css b/src/components/sound/sound.module.css new file mode 100644 index 0000000..96e8014 --- /dev/null +++ b/src/components/sound/sound.module.css @@ -0,0 +1,119 @@ +.sound { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 30px 20px; + border: 1px solid var(--color-neutral-200); + border-radius: 10px; + background: linear-gradient(var(--color-neutral-100), transparent); + text-align: center; + + &:not(.selected)::before { + position: absolute; + top: -1px; + left: 0; + width: 100%; + height: 1px; + background: linear-gradient( + 90deg, + transparent, + var(--color-neutral-300), + transparent + ); + content: ''; + } + + &.selected { + &.green { + border: 2px solid #4ade80; + box-shadow: 0 10px 20px #4ade8033; + } + + &.indigo { + border: 2px solid #818cf8; + box-shadow: 0 10px 20px #818cf833; + } + } + + & h3 { + font-family: var(--font-heading); + font-size: 15px; + font-weight: 600; + line-height: 1.6; + } + + & input { + width: 100%; + max-width: 120px; + margin-top: 12px; + + /********** Range Input Styles **********/ + + /* Range Reset */ + appearance: none; + background: transparent; + cursor: pointer; + + /* Removes default focus */ + &:focus { + outline: none; + } + + &:disabled { + cursor: default; + opacity: 0.5; + pointer-events: none; + } + + /***** Chrome, Safari, Opera and Edge Chromium styles *****/ + + &::-webkit-slider-runnable-track { + height: 0.5rem; + border-radius: 0.5rem; + background-color: #27272a; + } + + &::-webkit-slider-thumb { + width: 14px; + height: 14px; + border: 1px solid #52525b; + border-radius: 50%; + margin-top: -3px; + appearance: none; + background-color: #3f3f46; + } + + &:not(:disabled):focus::-webkit-slider-thumb { + border: 1px solid #053a5f; + outline: 3px solid #053a5f; + outline-offset: 0.125rem; + } + + /******** Firefox styles ********/ + + &::-moz-range-track { + height: 0.5rem; + border-radius: 0.5rem; + background-color: #27272a; + } + + &::-moz-range-thumb { + width: 14px; + height: 14px; + border: none; + border: 1px solid #52525b; + border-radius: 0; + border-radius: 50%; + margin-top: -3px; + background-color: #3f3f46; + } + + &:not(:disabled):focus::-moz-range-thumb { + border: 1px solid #053a5f; + outline: 3px solid #053a5f; + outline-offset: 0.125rem; + } + } +} diff --git a/src/components/sound/sound.tsx b/src/components/sound/sound.tsx new file mode 100644 index 0000000..4cb9234 --- /dev/null +++ b/src/components/sound/sound.tsx @@ -0,0 +1,47 @@ +import { useState, useMemo, useEffect } from 'react'; + +import { cn } from '@/helpers/styles'; + +import styles from './sound.module.css'; + +interface SoundProps { + color: string; + sound: { label: string; src: string }; +} + +export function Sound({ color, sound }: SoundProps) { + const [isSelected, setIsSelected] = useState(false); + const [volume, setVolume] = useState(0.5); + + const colorStyle = useMemo(() => { + const colorToStyle: { [color: string]: string } = { + green: styles.green, + indigo: styles.indigo, + }; + + return colorToStyle[color]; + }, [color]); + + useEffect(() => { + if (!isSelected) setVolume(0.5); + }, [isSelected]); + + return ( +
setIsSelected(prev => !prev)} + onKeyDown={() => setIsSelected(prev => !prev)} + > +

{sound.label}

+ isSelected && setVolume(Number(e.target.value) / 100)} + onClick={e => e.stopPropagation()} + /> +
+ ); +} diff --git a/src/components/sounds/index.ts b/src/components/sounds/index.ts new file mode 100644 index 0000000..a2cb9e0 --- /dev/null +++ b/src/components/sounds/index.ts @@ -0,0 +1 @@ +export { Sounds } from './sounds'; diff --git a/src/components/sounds/sounds.module.css b/src/components/sounds/sounds.module.css new file mode 100644 index 0000000..0732eea --- /dev/null +++ b/src/components/sounds/sounds.module.css @@ -0,0 +1,6 @@ +.sounds { + display: grid; + margin-top: 20px; + gap: 20px; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); +} diff --git a/src/components/sounds/sounds.tsx b/src/components/sounds/sounds.tsx new file mode 100644 index 0000000..7307a4a --- /dev/null +++ b/src/components/sounds/sounds.tsx @@ -0,0 +1,18 @@ +import { Sound } from '@/components/sound'; + +import styles from './sounds.module.css'; + +interface SoundsProps { + color: string; + sounds: Array<{ label: string; src: string }>; +} + +export function Sounds({ color, sounds }: SoundsProps) { + return ( +
+ {sounds.map(sound => ( + + ))} +
+ ); +}