feat: replace filter dropdowns with FilterPills component
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
interface Option {
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
options,
|
||||||
|
value,
|
||||||
|
onchange,
|
||||||
|
scrollable = false,
|
||||||
|
class: className = "",
|
||||||
|
}: {
|
||||||
|
options: Option[];
|
||||||
|
value: string;
|
||||||
|
onchange: (value: string) => void;
|
||||||
|
scrollable?: boolean;
|
||||||
|
class?: string;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class={cn("flex gap-2", scrollable && "overflow-x-auto pb-0.5 scrollbar-none", className)}>
|
||||||
|
{#each options as option (option.value)}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => onchange(option.value)}
|
||||||
|
class={cn(
|
||||||
|
"whitespace-nowrap rounded-full px-4 py-1.5 text-sm font-medium transition-all duration-200 cursor-pointer shrink-0",
|
||||||
|
value === option.value
|
||||||
|
? "bg-gradient-to-r from-primary to-accent text-white shadow-sm shadow-primary/30 border border-transparent"
|
||||||
|
: "border border-primary/20 text-muted-foreground bg-background/50 hover:border-primary/50 hover:text-foreground hover:bg-background/80",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{option.label}
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default as FilterPills } from "./filter-pills.svelte";
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
import { Button } from "$lib/components/ui/button";
|
import { Button } from "$lib/components/ui/button";
|
||||||
import { Card, CardContent } from "$lib/components/ui/card";
|
import { Card, CardContent } from "$lib/components/ui/card";
|
||||||
import { Input } from "$lib/components/ui/input";
|
import { Input } from "$lib/components/ui/input";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger } from "$lib/components/ui/select";
|
import { FilterPills } from "$lib/components/ui/filter-pills";
|
||||||
import TimeAgo from "javascript-time-ago";
|
import TimeAgo from "javascript-time-ago";
|
||||||
import { getAssetUrl } from "$lib/api";
|
import { getAssetUrl } from "$lib/api";
|
||||||
import { calcReadingTime } from "$lib/utils.js";
|
import { calcReadingTime } from "$lib/utils.js";
|
||||||
@@ -77,57 +77,32 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Filters -->
|
<!-- Category -->
|
||||||
<div class="flex gap-3">
|
<FilterPills
|
||||||
<!-- Category Filter -->
|
scrollable
|
||||||
<Select
|
|
||||||
type="single"
|
|
||||||
value={data.category ?? "all"}
|
value={data.category ?? "all"}
|
||||||
onValueChange={(v) => v && setParam("category", v)}
|
options={[
|
||||||
>
|
{ value: "all", label: $_("magazine.categories.all") },
|
||||||
<SelectTrigger class="flex-1 bg-background/50 border-primary/20 focus:border-primary">
|
{ value: "photography", label: $_("magazine.categories.photography") },
|
||||||
<span class="icon-[ri--filter-line] w-4 h-4 mr-2"></span>
|
{ value: "production", label: $_("magazine.categories.production") },
|
||||||
{!data.category
|
{ value: "interview", label: $_("magazine.categories.interview") },
|
||||||
? $_("magazine.categories.all")
|
{ value: "psychology", label: $_("magazine.categories.psychology") },
|
||||||
: data.category === "photography"
|
{ value: "trends", label: $_("magazine.categories.trends") },
|
||||||
? $_("magazine.categories.photography")
|
{ value: "spotlight", label: $_("magazine.categories.spotlight") },
|
||||||
: data.category === "production"
|
]}
|
||||||
? $_("magazine.categories.production")
|
onchange={(v) => setParam("category", v)}
|
||||||
: data.category === "interview"
|
/>
|
||||||
? $_("magazine.categories.interview")
|
|
||||||
: data.category === "psychology"
|
|
||||||
? $_("magazine.categories.psychology")
|
|
||||||
: data.category === "trends"
|
|
||||||
? $_("magazine.categories.trends")
|
|
||||||
: $_("magazine.categories.spotlight")}
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="all">{$_("magazine.categories.all")}</SelectItem>
|
|
||||||
<SelectItem value="photography">{$_("magazine.categories.photography")}</SelectItem>
|
|
||||||
<SelectItem value="production">{$_("magazine.categories.production")}</SelectItem>
|
|
||||||
<SelectItem value="interview">{$_("magazine.categories.interview")}</SelectItem>
|
|
||||||
<SelectItem value="psychology">{$_("magazine.categories.psychology")}</SelectItem>
|
|
||||||
<SelectItem value="trends">{$_("magazine.categories.trends")}</SelectItem>
|
|
||||||
<SelectItem value="spotlight">{$_("magazine.categories.spotlight")}</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
<!-- Sort -->
|
<!-- Sort -->
|
||||||
<Select type="single" value={data.sort} onValueChange={(v) => v && setParam("sort", v)}>
|
<FilterPills
|
||||||
<SelectTrigger class="flex-1 bg-background/50 border-primary/20 focus:border-primary">
|
value={data.sort ?? "recent"}
|
||||||
{data.sort === "featured"
|
options={[
|
||||||
? $_("magazine.sort.featured")
|
{ value: "recent", label: $_("magazine.sort.recent") },
|
||||||
: data.sort === "name"
|
{ value: "featured", label: $_("magazine.sort.featured") },
|
||||||
? $_("magazine.sort.name")
|
{ value: "name", label: $_("magazine.sort.name") },
|
||||||
: $_("magazine.sort.recent")}
|
]}
|
||||||
</SelectTrigger>
|
onchange={(v) => setParam("sort", v)}
|
||||||
<SelectContent>
|
/>
|
||||||
<SelectItem value="recent">{$_("magazine.sort.recent")}</SelectItem>
|
|
||||||
<SelectItem value="featured">{$_("magazine.sort.featured")}</SelectItem>
|
|
||||||
<SelectItem value="name">{$_("magazine.sort.name")}</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</PageHero>
|
</PageHero>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import { Button } from "$lib/components/ui/button";
|
import { Button } from "$lib/components/ui/button";
|
||||||
import { Card, CardContent } from "$lib/components/ui/card";
|
import { Card, CardContent } from "$lib/components/ui/card";
|
||||||
import { Input } from "$lib/components/ui/input";
|
import { Input } from "$lib/components/ui/input";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger } from "$lib/components/ui/select";
|
import { FilterPills } from "$lib/components/ui/filter-pills";
|
||||||
import { getAssetUrl } from "$lib/api";
|
import { getAssetUrl } from "$lib/api";
|
||||||
import Meta from "$lib/components/meta/meta.svelte";
|
import Meta from "$lib/components/meta/meta.svelte";
|
||||||
import SexyBackground from "$lib/components/background/background.svelte";
|
import SexyBackground from "$lib/components/background/background.svelte";
|
||||||
@@ -70,18 +70,15 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Filters -->
|
<!-- Sort -->
|
||||||
<div class="flex gap-3">
|
<FilterPills
|
||||||
<Select type="single" value={data.sort} onValueChange={(v) => v && setParam("sort", v)}>
|
value={data.sort ?? "name"}
|
||||||
<SelectTrigger class="flex-1 bg-background/50 border-primary/20 focus:border-primary">
|
options={[
|
||||||
{data.sort === "recent" ? $_("models.sort.recent") : $_("models.sort.name")}
|
{ value: "name", label: $_("models.sort.name") },
|
||||||
</SelectTrigger>
|
{ value: "recent", label: $_("models.sort.recent") },
|
||||||
<SelectContent>
|
]}
|
||||||
<SelectItem value="name">{$_("models.sort.name")}</SelectItem>
|
onchange={(v) => setParam("sort", v)}
|
||||||
<SelectItem value="recent">{$_("models.sort.recent")}</SelectItem>
|
/>
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</PageHero>
|
</PageHero>
|
||||||
<!-- Models Grid -->
|
<!-- Models Grid -->
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import { Button } from "$lib/components/ui/button";
|
import { Button } from "$lib/components/ui/button";
|
||||||
import { Card, CardContent } from "$lib/components/ui/card";
|
import { Card, CardContent } from "$lib/components/ui/card";
|
||||||
import { Input } from "$lib/components/ui/input";
|
import { Input } from "$lib/components/ui/input";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger } from "$lib/components/ui/select";
|
import { FilterPills } from "$lib/components/ui/filter-pills";
|
||||||
import { getAssetUrl } from "$lib/api";
|
import { getAssetUrl } from "$lib/api";
|
||||||
import Meta from "$lib/components/meta/meta.svelte";
|
import Meta from "$lib/components/meta/meta.svelte";
|
||||||
import SexyBackground from "$lib/components/background/background.svelte";
|
import SexyBackground from "$lib/components/background/background.svelte";
|
||||||
@@ -73,51 +73,29 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Filters -->
|
<!-- Duration -->
|
||||||
<div class="flex gap-3">
|
<FilterPills
|
||||||
<!-- Duration Filter -->
|
value={data.duration ?? "all"}
|
||||||
<Select
|
options={[
|
||||||
type="single"
|
{ value: "all", label: $_("videos.duration.all") },
|
||||||
value={data.duration}
|
{ value: "short", label: $_("videos.duration.short") },
|
||||||
onValueChange={(v) => v && setParam("duration", v)}
|
{ value: "medium", label: $_("videos.duration.medium") },
|
||||||
>
|
{ value: "long", label: $_("videos.duration.long") },
|
||||||
<SelectTrigger class="flex-1 bg-background/50 border-primary/20 focus:border-primary">
|
]}
|
||||||
<span class="icon-[ri--timer-2-line] w-4 h-4 mr-2"></span>
|
onchange={(v) => setParam("duration", v)}
|
||||||
{data.duration === "short"
|
/>
|
||||||
? $_("videos.duration.short")
|
|
||||||
: data.duration === "medium"
|
|
||||||
? $_("videos.duration.medium")
|
|
||||||
: data.duration === "long"
|
|
||||||
? $_("videos.duration.long")
|
|
||||||
: $_("videos.duration.all")}
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="all">{$_("videos.duration.all")}</SelectItem>
|
|
||||||
<SelectItem value="short">{$_("videos.duration.short")}</SelectItem>
|
|
||||||
<SelectItem value="medium">{$_("videos.duration.medium")}</SelectItem>
|
|
||||||
<SelectItem value="long">{$_("videos.duration.long")}</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
<!-- Sort -->
|
<!-- Sort -->
|
||||||
<Select type="single" value={data.sort} onValueChange={(v) => v && setParam("sort", v)}>
|
<FilterPills
|
||||||
<SelectTrigger class="flex-1 bg-background/50 border-primary/20 focus:border-primary">
|
value={data.sort ?? "recent"}
|
||||||
{data.sort === "most_liked"
|
options={[
|
||||||
? $_("videos.sort.most_liked")
|
{ value: "recent", label: $_("videos.sort.recent") },
|
||||||
: data.sort === "most_played"
|
{ value: "most_liked", label: $_("videos.sort.most_liked") },
|
||||||
? $_("videos.sort.most_played")
|
{ value: "most_played", label: $_("videos.sort.most_played") },
|
||||||
: data.sort === "name"
|
{ value: "name", label: $_("videos.sort.name") },
|
||||||
? $_("videos.sort.name")
|
]}
|
||||||
: $_("videos.sort.recent")}
|
onchange={(v) => setParam("sort", v)}
|
||||||
</SelectTrigger>
|
/>
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="recent">{$_("videos.sort.recent")}</SelectItem>
|
|
||||||
<SelectItem value="most_liked">{$_("videos.sort.most_liked")}</SelectItem>
|
|
||||||
<SelectItem value="most_played">{$_("videos.sort.most_played")}</SelectItem>
|
|
||||||
<SelectItem value="name">{$_("videos.sort.name")}</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</PageHero>
|
</PageHero>
|
||||||
<!-- Videos Grid -->
|
<!-- Videos Grid -->
|
||||||
|
|||||||
Reference in New Issue
Block a user