mirror of
https://github.com/remvze/moodist.git
synced 2025-12-11 07:35:17 -05:00
feat: add basic sound components
This commit is contained in:
parent
8d7e4d26fd
commit
4adb8bfdbc
@ -41,6 +41,7 @@
|
|||||||
"prettier/prettier": "error",
|
"prettier/prettier": "error",
|
||||||
"sort-keys-fix/sort-keys-fix": ["warn", "asc"],
|
"sort-keys-fix/sort-keys-fix": ["warn", "asc"],
|
||||||
"sort-destructure-keys/sort-destructure-keys": "warn",
|
"sort-destructure-keys/sort-destructure-keys": "warn",
|
||||||
|
"jsx-a11y/no-static-element-interactions": "off",
|
||||||
"react/jsx-sort-props": [
|
"react/jsx-sort-props": [
|
||||||
"warn",
|
"warn",
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
import { Sounds } from '@/components/sounds';
|
||||||
import { cn } from '@/helpers/styles';
|
import { cn } from '@/helpers/styles';
|
||||||
|
|
||||||
import styles from './category.module.css';
|
import styles from './category.module.css';
|
||||||
@ -12,7 +13,7 @@ interface CategoryProps {
|
|||||||
sounds: Array<{ label: string; src: string }>;
|
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 colorStyle = useMemo(() => {
|
||||||
const colorToStyle: { [color: string]: string } = {
|
const colorToStyle: { [color: string]: string } = {
|
||||||
green: styles.green,
|
green: styles.green,
|
||||||
@ -30,6 +31,8 @@ export function Category({ color, icon, title }: CategoryProps) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 className={styles.title}>{title}</h2>
|
<h2 className={styles.title}>{title}</h2>
|
||||||
|
|
||||||
|
<Sounds color={color} sounds={sounds} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/components/sound/index.ts
Normal file
1
src/components/sound/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { Sound } from './sound';
|
||||||
119
src/components/sound/sound.module.css
Normal file
119
src/components/sound/sound.module.css
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
src/components/sound/sound.tsx
Normal file
47
src/components/sound/sound.tsx
Normal file
@ -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 (
|
||||||
|
<div
|
||||||
|
className={cn(styles.sound, isSelected && styles.selected, colorStyle)}
|
||||||
|
onClick={() => setIsSelected(prev => !prev)}
|
||||||
|
onKeyDown={() => setIsSelected(prev => !prev)}
|
||||||
|
>
|
||||||
|
<h3>{sound.label}</h3>
|
||||||
|
<input
|
||||||
|
disabled={!isSelected}
|
||||||
|
max={100}
|
||||||
|
min={0}
|
||||||
|
type="range"
|
||||||
|
value={volume * 100}
|
||||||
|
onChange={e => isSelected && setVolume(Number(e.target.value) / 100)}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
1
src/components/sounds/index.ts
Normal file
1
src/components/sounds/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { Sounds } from './sounds';
|
||||||
6
src/components/sounds/sounds.module.css
Normal file
6
src/components/sounds/sounds.module.css
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.sounds {
|
||||||
|
display: grid;
|
||||||
|
margin-top: 20px;
|
||||||
|
gap: 20px;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
|
}
|
||||||
18
src/components/sounds/sounds.tsx
Normal file
18
src/components/sounds/sounds.tsx
Normal file
@ -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 (
|
||||||
|
<div className={styles.sounds}>
|
||||||
|
{sounds.map(sound => (
|
||||||
|
<Sound color={color} key={sound.label} sound={sound} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user