← Components/Data Display

SearchFilterBar

searchfilterbar-1779388706222.tsx
'use client';
import { useState } from 'react';

export default function SearchFilterBar() {
  const [query, setQuery] = useState('');
  const [filters, setFilters] = useState([]);
  const [showDropdown, setShowDropdown] = useState(false);

  const filterOptions = [
    { id: 'status:active', label: 'Active', color: '#4ade80' },
    { id: 'status:archived', label: 'Archived', color: '#6366f1' },
    { id: 'type:project', label: 'Project', color: '#C9A84C' },
    { id: 'type:document', label: 'Document', color: '#f472b6' },
    { id: 'priority:high', label: 'High Priority', color: '#ef4444' },
    { id: 'assigned:me', label: 'Assigned to me', color: '#22d3ee' },
  ];

  const toggleFilter = (id) => {
    setFilters(f => f.includes(id) ? f.filter(x => x !== id) : [...f, id]);
    setShowDropdown(false);
  };

  const activeFilters = filterOptions.filter(o => filters.includes(o.id));

  return (
    <div style={{ fontFamily: 'system-ui, sans-serif', maxWidth: '560px' }}>
      <div style={{
        display: 'flex', gap: '8px', alignItems: 'center',
        background: 'rgba(255,255,255,0.04)',
        border: '1px solid rgba(255,255,255,0.1)',
        borderRadius: '12px', padding: '8px 14px',
        marginBottom: '10px',
      }}>
        <span style={{ color: 'rgba(245,245,240,0.35)', fontSize: '16px' }}>🔍</span>
        {activeFilters.map(f => (
          <span key={f.id} style={{
            background: f.color + '20', color: f.color, border: `1px solid ${f.color}40`,
            borderRadius: '6px', padding: '3px 8px', fontSize: '12px', fontWeight: 600,
            display: 'flex', alignItems: 'center', gap: '4px', whiteSpace: 'nowrap',
          }}>
            {f.label}
            <span onClick={() => toggleFilter(f.id)} style={{ cursor: 'pointer', opacity: 0.7, marginLeft: '2px' }}>✕</span>
          </span>
        ))}
        <input
          value={query}
          onChange={e => setQuery(e.target.value)}
          placeholder={activeFilters.length ? '' : 'Search anything...'}
          style={{ flex: 1, background: 'none', border: 'none', color: '#F5F5F0', fontSize: '14px', outline: 'none', fontFamily: 'system-ui', minWidth: '100px' }}
        />
        <div style={{ position: 'relative' }}>
          <button onClick={() => setShowDropdown(d => !d)} style={{
            background: showDropdown ? 'rgba(201,168,76,0.15)' : 'rgba(255,255,255,0.05)',
            border: `1px solid ${showDropdown ? 'rgba(201,168,76,0.3)' : 'rgba(255,255,255,0.1)'}`,
            borderRadius: '8px', padding: '6px 12px', cursor: 'pointer',
            color: showDropdown ? '#C9A84C' : 'rgba(245,245,240,0.5)', fontSize: '12px',
            display: 'flex', alignItems: 'center', gap: '6px',
          }}>
            Filters {filters.length > 0 && <span style={{ background: '#C9A84C', color: '#0A0A0A', borderRadius: '50%', width: '16px', height: '16px', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '10px', fontWeight: 700 }}>{filters.length}</span>}
          </button>
          {showDropdown && (
            <div style={{
              position: 'absolute', top: '100%', right: 0, marginTop: '8px',
              background: '#161616', border: '1px solid rgba(255,255,255,0.1)',
              borderRadius: '12px', padding: '8px', minWidth: '200px',
              boxShadow: '0 12px 40px rgba(0,0,0,0.5)', zIndex: 100,
            }}>
              {filterOptions.map(opt => (
                <div key={opt.id} onClick={() => toggleFilter(opt.id)} style={{
                  display: 'flex', alignItems: 'center', gap: '10px',
                  padding: '8px 10px', borderRadius: '8px', cursor: 'pointer',
                  background: filters.includes(opt.id) ? opt.color + '12' : 'transparent',
                  transition: 'background 0.15s',
                }}
                  onMouseEnter={e => { if (!filters.includes(opt.id)) e.currentTarget.style.background = 'rgba(255,255,255,0.04)'; }}
                  onMouseLeave={e => { if (!filters.includes(opt.id)) e.currentTarget.style.background = 'transparent'; }}
                >
                  <div style={{ width: '8px', height: '8px', borderRadius: '50%', background: opt.color }} />
                  <span style={{ color: '#F5F5F0', fontSize: '13px' }}>{opt.label}</span>
                  {filters.includes(opt.id) && <span style={{ marginLeft: 'auto', color: opt.color, fontSize: '12px' }}>✓</span>}
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
      {query && (
        <p style={{ color: 'rgba(245,245,240,0.35)', fontSize: '12px', margin: 0 }}>
          Searching for "<strong style={{ color: '#C9A84C' }}>{query}</strong>" {filters.length > 0 && `with ${filters.length} filter${filters.length > 1 ? 's' : ''}`}
        </p>
      )}
    </div>
  );
}

Component info

CategoryData Display
Frameworkreact
TierFREE
Views0
Copies0

About

Advanced search bar with filter chips and dropdown

More from Data Display

'use client'
import { useState, useRef, useCallback, useEffect } from 'react'

export default function ComparisonSlider() {
  const [position, setPosition] = useState(50)
  const [dragging, setDragging] = useState(false)
  const containerRef = useRef
ComparisonSlider
Data Display
'use client'
import { useState } from 'react'

const WEEKS = 26
const DAYS = 7

function randomActivity(): number {
  const r = Math.random()
  if (r < 0.3) return 0
  if (r < 0.55) return 1
  if (r < 0.75) return 2
  if (r < 0.9) return 3
  return 4
HeatmapCalendar
Data Display
'use client'
import { useState } from 'react'

const events = [
  { id: 1, icon: '🚀', title: 'Wave 7 generation complete', desc: '57 new components published across 14 categories', time: '14:32', type: 'success', day: 'Today' },
  { id: 2, icon: '👥
TimelineActivity
Data Display
'use client';
import { useState, useEffect } from 'react';

function FlipDigit({ digit, prev }) {
  const [flipping, setFlipping] = useState(false);

  useEffect(() => {
    if (digit !== prev) {
      setFlipping(true);
      const t = setTimeout(()
FlipCounter
Data Display