filters-size

PreviousNext
Docs
reuicomponent

Preview

Loading preview…
registry/default/components/filters/size.tsx
'use client';

import { useCallback, useState } from 'react';
import { Button } from '@/registry/default/ui/button';
import { createFilter, Filters, type Filter, type FilterFieldConfig } from '@/registry/default/ui/filters';
import {
  AlertCircle,
  Ban,
  Calendar,
  CheckCircle,
  Circle,
  Clock,
  FunnelPlus,
  Globe,
  Mail,
  Star,
  Tag,
} from 'lucide-react';

const StatusIcon = ({ status }: { status: string }) => {
  switch (status) {
    case 'todo':
      return <Clock className="text-primary" />;
    case 'in-progress':
      return <AlertCircle className="text-yellow-500" />;
    case 'done':
      return <CheckCircle className="text-green-500" />;
    case 'cancelled':
      return <Ban className="text-destructive" />;
    default:
      return <Circle className="text-muted-foreground" />;
  }
};

// Priority icon component
const PriorityIcon = ({ priority }: { priority: string }) => {
  const colors = {
    low: 'text-green-500',
    medium: 'text-yellow-500',
    high: 'text-orange-500',
    urgent: 'text-red-500',
  };
  return <Star className={colors[priority as keyof typeof colors]} />;
};

export default function FiltersDemo() {
  // Basic filter fields for size variant demo
  const fields: FilterFieldConfig[] = [
    {
      key: 'text',
      label: 'Text',
      icon: <Tag className="size-3.5" />,
      type: 'text',
      className: 'w-36',
      placeholder: 'Search text...',
    },
    {
      key: 'email',
      label: 'Email',
      icon: <Mail className="size-3.5" />,
      type: 'email',
      className: 'w-48',
      placeholder: 'user@example.com',
    },
    {
      key: 'website',
      label: 'Website',
      icon: <Globe className="size-3.5" />,
      type: 'url',
      className: 'w-40',
      placeholder: 'https://example.com',
    },
    {
      key: 'status',
      label: 'Status',
      icon: <Clock className="size-3.5" />,
      type: 'select',
      searchable: false,
      className: 'w-[200px]',
      options: [
        { value: 'todo', label: 'To Do', icon: <StatusIcon status="todo" /> },
        { value: 'in-progress', label: 'In Progress', icon: <StatusIcon status="in-progress" /> },
        { value: 'done', label: 'Done', icon: <StatusIcon status="done" /> },
        { value: 'cancelled', label: 'Cancelled', icon: <StatusIcon status="cancelled" /> },
      ],
    },
    {
      key: 'priority',
      label: 'Priority',
      icon: <AlertCircle className="size-3.5" />,
      type: 'multiselect',
      className: 'w-[180px]',
      options: [
        { value: 'low', label: 'Low', icon: <PriorityIcon priority="low" /> },
        { value: 'medium', label: 'Medium', icon: <PriorityIcon priority="medium" /> },
        { value: 'high', label: 'High', icon: <PriorityIcon priority="high" /> },
        { value: 'urgent', label: 'Urgent', icon: <PriorityIcon priority="urgent" /> },
      ],
    },
    {
      key: 'dueDate',
      label: 'Due Date',
      icon: <Calendar className="size-3.5" />,
      type: 'date',
      className: 'w-36',
    },
    {
      key: 'score',
      label: 'Score',
      icon: <Star className="size-3.5" />,
      type: 'number',
      min: 0,
      max: 100,
      step: 1,
    },
    {
      key: 'isActive',
      label: 'Active Status',
      icon: <CheckCircle className="size-3.5" />,
      type: 'boolean',
    },
  ];

  const [smallFilters, setSmallFilters] = useState<Filter[]>([createFilter('priority', 'is', ['high', 'urgent'])]);

  const [mediumFilters, setMediumFilters] = useState<Filter[]>([createFilter('status', 'is', ['todo'])]);

  const [largeFilters, setLargeFilters] = useState<Filter[]>([
    createFilter('email', 'contains', ['example@example.com']),
  ]);

  const handleSmallFiltersChange = useCallback((filters: Filter[]) => {
    console.log('Small filters updated:', filters);
    setSmallFilters(filters);
  }, []);

  const handleMediumFiltersChange = useCallback((filters: Filter[]) => {
    console.log('Medium filters updated:', filters);
    setMediumFilters(filters);
  }, []);

  const handleLargeFiltersChange = useCallback((filters: Filter[]) => {
    console.log('Large filters updated:', filters);
    setLargeFilters(filters);
  }, []);

  return (
    <div className="flex items-start flex-col gap-2.5 grow space-y-6 self-start content-start">
      <div>
        <h3 className="text-sm font-semibold mb-4">Small Size</h3>
        <Filters
          size="sm"
          filters={smallFilters}
          fields={fields}
          variant="outline"
          onChange={handleSmallFiltersChange}
          addButton={
            <Button size="sm" mode="icon" variant="outline">
              <FunnelPlus />
            </Button>
          }
        />
      </div>

      <div>
        <h3 className="text-sm font-semibold mb-4">Medium Size (Default)</h3>
        <Filters
          size="md"
          filters={mediumFilters}
          fields={fields}
          variant="outline"
          onChange={handleMediumFiltersChange}
          addButton={
            <Button mode="icon" variant="outline">
              <FunnelPlus />
            </Button>
          }
        />
      </div>

      <div>
        <h3 className="text-sm font-semibold mb-4">Large Size</h3>
        <Filters
          size="lg"
          filters={largeFilters}
          fields={fields}
          variant="outline"
          onChange={handleLargeFiltersChange}
          addButton={
            <Button size="lg" mode="icon" variant="outline">
              <FunnelPlus />
            </Button>
          }
        />
      </div>
    </div>
  );
}

Installation

npx shadcn@latest add @reui/filters-size

Usage

import { FiltersSize } from "@/components/filters-size"
<FiltersSize />