Skip to content

Commit

Permalink
feat(ui): create "combo-list" component
Browse files Browse the repository at this point in the history
A component for list, select and delete sound combos.
  • Loading branch information
mateusfg7 committed Aug 18, 2023
1 parent 5c69eac commit 557aa8e
Show file tree
Hide file tree
Showing 3 changed files with 277 additions and 0 deletions.
120 changes: 120 additions & 0 deletions src/components/header/combo-list/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { Fragment, useState } from 'react'
import { Menu, Transition, Switch } from '@headlessui/react'
import { PiPlaylistBold } from 'react-icons/pi'
import { FiTrash } from 'react-icons/fi'

import { useThemeStore } from '@/stores/theme-store'
import { useComboStore } from '@/stores/combo-store'
import { useSoundsStateStore } from '@/stores/sounds-state-store'

import {
comboButton,
editButton,
toggleEditButton,
toggleEditContainer,
triggerButton
} from './styles'

export function ComboList() {
const theme = useThemeStore(set => set.theme)
const sounds = useSoundsStateStore(state => state.sounds)
const bulkUpdate = useSoundsStateStore(state => state.bulkUpdate)
const combos = useComboStore(state => state.combos)
const deleteCombo = useComboStore(state => state.deleteCombo)

const [editMode, setEditMode] = useState(false)

function updateCombo(id: string) {
const combo = combos.filter(combo => combo.id === id)

if (combo.length === 0) return

const comboSounds = combo[0].sounds

const activeSoundsIds = comboSounds.map(sound => sound.id)

const disabledSounds = sounds
.filter(sound => !activeSoundsIds.includes(sound.id))
.map(sound => ({ ...sound, active: false }))

console.log(
`enabledSounds: ${comboSounds.map(
sound => `${sound.id}:${sound.volume}`
)}`
)

bulkUpdate([...disabledSounds, ...comboSounds])
}

const isEmpty = combos.length === 0

return (
<div className="z-40">
<Menu>
<Menu.Button
title="Toggle combo list"
disabled={isEmpty}
className={triggerButton({ theme })}
>
<PiPlaylistBold size={24} />
</Menu.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
as="div"
className="snap absolute left-4 right-4 mt-2 flex max-h-[85vh] origin-top-right snap-y snap-mandatory scroll-pt-4 flex-col gap-1 overflow-y-auto rounded-2xl p-4 shadow-2xl backdrop-blur-md scrollbar-hide focus:outline-none md:left-auto md:right-0"
>
<div className={toggleEditContainer({ theme })}>
<button
onClick={() => setEditMode(false)}
className={toggleEditButton({ theme, active: !editMode })}
>
Select
</button>
<button
data-is-active={editMode}
onClick={() => setEditMode(true)}
className={toggleEditButton({ theme, active: editMode })}
>
Edit
</button>
</div>

{!editMode &&
combos.map(combo => (
<Menu.Item key={combo.id}>
{({ active }) => (
<button
className={comboButton({ theme, active })}
onClick={() => updateCombo(combo.id)}
>
<span className="font-bold">{combo.name}</span>
</button>
)}
</Menu.Item>
))}

{editMode &&
combos.map(combo => (
<button
key={combo.id}
className={editButton({ theme })}
onClick={() => deleteCombo(combo.id)}
>
<span className="font-bold">{combo.name}</span>
<FiTrash />
</button>
))}
</Menu.Items>
</Transition>
</Menu>
</div>
)
}
155 changes: 155 additions & 0 deletions src/components/header/combo-list/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import { tv } from 'tailwind-variants'

export const triggerButton = tv({
base: /*tw:*/ 'flex opacity-90 hover:opacity-100 disabled:opacity-50 disabled:hover:opacity-50',
variants: {
theme: {
transition: /*tw:*/ 'text-white',
dark: /*tw:*/ 'text-dark-foreground',
'blue-room': /*tw:*/ 'text-blue-room',
train: /*tw:*/ 'text-train',
waterfall: /*tw:*/ 'text-waterfall',
light: /*tw:*/ 'text-light-foreground',
'camping-fire': /*tw:*/ 'text-camping-fire'
}
}
})

export const comboButton = tv({
base: /*tw:*/ 'rounded-xl p-3 leading-none tracking-wider duration-300',
variants: {
theme: {
transition: /*tw:*/ 'text-white bg-white/5',
dark: /*tw:*/ 'text-dark-foreground bg-dark-foreground/5',
light: /*tw:*/ 'text-light-foreground bg-light-foreground/5',
'blue-room': /*tw:*/ 'text-blue-room bg-blue-room/5',
train: /*tw:*/ 'text-train bg-train/5',
waterfall: /*tw:*/ 'text-waterfall bg-waterfall/5',
'camping-fire': /*tw:*/ 'text-camping-fire bg-camping-fire/5'
},
active: {
true: /*tw:*/ 'bg-white/20'
}
},
compoundVariants: [
{
theme: 'dark',
active: true,
class: /*tw:*/ 'bg-dark-foreground/20'
},
{
theme: 'light',
active: true,
class: /*tw:*/ 'bg-light-foreground/20'
},
{
theme: 'blue-room',
active: true,
class: /*tw:*/ 'bg-blue-room/20'
},
{
theme: 'train',
active: true,
class: /*tw:*/ 'bg-train/20'
},
{
theme: 'waterfall',
active: true,
class: /*tw:*/ 'bg-waterfall/20'
},
{
theme: 'camping-fire',
active: true,
class: /*tw:*/ 'bg-camping-fire/20'
}
]
})

export const editButton = tv({
extend: comboButton,
base: /*tw:*/ 'flex items-center gap-1 justify-between',
variants: {
theme: {
transition: /*tw:*/ 'hover:bg-white/20',
dark: /*tw:*/ 'hover:bg-dark-foreground/20',
light: /*tw:*/ 'hover:bg-light-foreground/20',
'blue-room': /*tw:*/ 'hover:bg-blue-room/20',
train: /*tw:*/ 'hover:bg-train/20',
waterfall: /*tw:*/ 'hover:bg-waterfall/20',
'camping-fire': /*tw:*/ 'hover:bg-camping-fire/20'
},
active: {
true: /*tw:*/ 'bg-white/20'
}
}
})

export const toggleEditContainer = tv({
base: /*tw:*/ 'min-w-40 mb-2 flex items-center justify-around gap-1 rounded-lg',
variants: {
theme: {
transition: /*tw:*/ 'bg-white/5 text-white',
dark: /*tw:*/ 'bg-dark-foreground/5 text-dark-foreground',
light: /*tw:*/ 'bg-light-foreground/5 text-light-foreground',
'blue-room': /*tw:*/ 'bg-blue-room/5 text-blue-room',
train: /*tw:*/ 'bg-train/5 text-train',
waterfall: /*tw:*/ 'bg-waterfall/5 text-waterfall',
'camping-fire': /*tw:*/ 'bg-camping-fire/5 text-camping-fire'
}
}
})

export const toggleEditButton = tv({
base: /*tw:*/ 'flex-1 rounded-lg py-1',
variants: {
theme: {
transition: /*tw:*/ 'hover:bg-white/10',
dark: /*tw:*/ 'hover:bg-dark-foreground/10',
light: /*tw:*/ 'hover:bg-light-foreground/10',
'blue-room': /*tw:*/ 'hover:bg-blue-room/10',
train: /*tw:*/ 'hover:bg-train/10',
waterfall: /*tw:*/ 'hover:bg-waterfall/10',
'camping-fire': /*tw:*/ 'hover:bg-camping-fire/10'
},
active: {
true: ''
}
},
compoundVariants: [
{
theme: 'transition',
active: true,
class: /*tw:*/ 'bg-white/20'
},
{
theme: 'dark',
active: true,
class: /*tw:*/ 'bg-dark-foreground/20'
},
{
theme: 'light',
active: true,
class: /*tw:*/ 'bg-light-foreground/20'
},
{
theme: 'blue-room',
active: true,
class: /*tw:*/ 'bg-blue-room/20'
},
{
theme: 'train',
active: true,
class: /*tw:*/ 'bg-train/20'
},
{
theme: 'waterfall',
active: true,
class: /*tw:*/ 'bg-waterfall/20'
},
{
theme: 'camping-fire',
active: true,
class: /*tw:*/ 'bg-camping-fire/20'
}
]
})
2 changes: 2 additions & 0 deletions src/components/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ThemeMenu } from './theme-menu'
import { GlobalVolumeController } from './global-volume-controller'
import { title } from './styles'
import { Pomodoro } from './pomodoro'
import { ComboList } from './combo-list'

export const Header: React.FC = () => {
const theme = useThemeStore(set => set.theme)
Expand All @@ -21,6 +22,7 @@ export const Header: React.FC = () => {
<div className="right-10 flex items-center gap-3">
<GlobalVolumeController />
<ThemeMenu />
<ComboList />
</div>
</header>
)
Expand Down

0 comments on commit 557aa8e

Please sign in to comment.