feat(web-player): filter the explore results with a chip group
Under the search box there are now three checkbox chips choosing what the page shows. Songs keep the existing grid and Albums searches the albums by title; Users is rendered disabled until there is something behind it.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
<script lang="ts" module>
|
||||
import type { LucideIcon } from '@lucide/svelte';
|
||||
|
||||
export interface ChipOption {
|
||||
value: string;
|
||||
label: string;
|
||||
icon?: LucideIcon;
|
||||
disabled?: boolean;
|
||||
hint?: string;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import Check from '@lucide/svelte/icons/check';
|
||||
|
||||
interface Props {
|
||||
options: ChipOption[];
|
||||
selected: string[];
|
||||
label: string;
|
||||
onChange: (selected: string[]) => void;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
let { options, selected, label, onChange, class: klass = '' }: Props = $props();
|
||||
|
||||
function toggle(value: string) {
|
||||
onChange(selected.includes(value) ? selected.filter((v) => v !== value) : [...selected, value]);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div role="group" aria-label={label} class="flex flex-wrap items-center gap-2 {klass}">
|
||||
{#each options as option (option.value)}
|
||||
{@const active = selected.includes(option.value)}
|
||||
<label
|
||||
title={option.hint}
|
||||
class="inline-flex cursor-pointer items-center gap-1.5 rounded-full border px-3.5 py-1.5 text-sm font-semibold transition select-none
|
||||
{active
|
||||
? 'border-transparent bg-accent text-on-accent'
|
||||
: 'border-line bg-surface text-fg-2 hover:bg-surface-hover'}
|
||||
{option.disabled ? 'pointer-events-none opacity-45' : ''}"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="sr-only"
|
||||
checked={active}
|
||||
disabled={option.disabled}
|
||||
onchange={() => toggle(option.value)}
|
||||
/>
|
||||
{#if active}
|
||||
<Check class="h-3.5 w-3.5" strokeWidth={3} />
|
||||
{:else if option.icon}
|
||||
<option.icon class="h-3.5 w-3.5" strokeWidth={2} />
|
||||
{/if}
|
||||
{option.label}
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -6,5 +6,6 @@ export const ALBUMS_PAGE_SIZE = 50;
|
||||
export const ALBUM_TRACKS_PAGE_SIZE = 200;
|
||||
export const ALBUM_EARLIEST_YEAR = 1877;
|
||||
export const LIBRARY_PICKER_PAGE_SIZE = 50;
|
||||
export const EXPLORE_ALBUMS_PAGE_SIZE = 18;
|
||||
export const HOME_LATEST_PAGE_SIZE = 12;
|
||||
export const YOUTUBE_FILLER_LIMIT = 27;
|
||||
|
||||
Reference in New Issue
Block a user