Zoeken...  ⌘K GitHub

FormFilter Forms

Filter-/zoekbalk met zoekveld en groepen van checkbox-filters.

/form-filter
src/components/forms/FormFilter.astro
---
/**
 * FormFilter — filter-/zoekbalk met zoekveld en groepen van checkbox-filters.
 *
 * Props:
 * - headline?: string
 * - searchPlaceholder?: string
 * - groups?: { label: string; options: string[] }[]
 * - submitLabel?: string
 * - resetLabel?: string
 * - action?: string
 */
interface Props {
  headline?: string;
  searchPlaceholder?: string;
  groups?: { label: string; options: string[] }[];
  submitLabel?: string;
  resetLabel?: string;
  action?: string;
}
const {
  headline = 'Filter resultaten',
  searchPlaceholder = 'Zoek op trefwoord…',
  groups = [
    { label: 'Dienst', options: ['SEO', 'Google Ads', 'Social Media', 'Webdesign', 'Branding'] },
    { label: 'Budget', options: ['< € 500 / mnd', '€ 500–1.000', '€ 1.000–2.500', '> € 2.500'] },
    { label: 'Branche', options: ['E-commerce', 'B2B', 'Horeca', 'Zorg', 'Technologie'] },
  ],
  submitLabel = 'Resultaten tonen',
  resetLabel = 'Filters wissen',
  action = '#',
} = Astro.props;
---

<section class="bl-section ffl">
  <div class="bl-inner bl-inner--narrow ffl__inner">
    {headline && <h2 class="ffl__headline">{headline}</h2>}
    <form class="ffl__form" action={action} novalidate>
      <div class="ffl__search-wrap">
        <input class="ffl__search" type="search" placeholder={searchPlaceholder} aria-label={searchPlaceholder} />
        <button class="ffl__search-btn" type="submit" aria-label="Zoeken">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
        </button>
      </div>
      <div class="ffl__filters">
        {groups.map((g, gi) => (
          <div class="ffl__group">
            <span class="ffl__group-label">{g.label}</span>
            <div class="ffl__checkboxes">
              {g.options.map((opt) => (
                <label class="ffl__checkbox">
                  <input type="checkbox" name={`filter-${gi}`} value={opt} /> <span>{opt}</span>
                </label>
              ))}
            </div>
          </div>
        ))}
      </div>
      <div class="ffl__actions">
        <button class="ffl__btn" type="submit">{submitLabel}</button>
        <button class="ffl__reset" type="reset">{resetLabel}</button>
      </div>
    </form>
  </div>
</section>

<style>
.ffl{background:#f9f9fb}
.ffl__headline{font-size:clamp(1.5rem,3vw,1.75rem);font-weight:800;color:var(--color-primary, #0a0a0a);letter-spacing:-.02em;margin:0 0 1.5rem}
.ffl__form{display:flex;flex-direction:column;gap:1.5rem}
.ffl__search-wrap{position:relative;max-width:520px}
.ffl__search{width:100%;box-sizing:border-box;padding:.75rem 3rem .75rem 1rem;border:1.5px solid #d1d5db;border-radius:8px;font-size:1rem;background:#fff;outline:none;font-family:inherit;transition:border-color .2s}
.ffl__search:focus{border-color:var(--color-accent, #6366f1)}
.ffl__search-btn{position:absolute;right:.75rem;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;color:#6b7280;display:flex;align-items:center}
.ffl__filters{display:flex;flex-wrap:wrap;gap:1.5rem}
.ffl__group{display:flex;flex-direction:column;gap:.5rem;min-width:160px}
.ffl__group-label{font-size:.8125rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:#374151}
.ffl__checkboxes{display:flex;flex-direction:column;gap:.4rem}
.ffl__checkbox{display:flex;align-items:center;gap:.5rem;font-size:1rem;color:var(--color-primary, #0a0a0a);cursor:pointer}
.ffl__checkbox input[type=checkbox]{accent-color:var(--color-accent, #6366f1);width:15px;height:15px;cursor:pointer}
.ffl__actions{display:flex;gap:1rem;align-items:center}
.ffl__btn{padding:.8rem 1.75rem;background:var(--color-accent, #6366f1);color:#fff;border:none;border-radius:8px;font-size:1rem;font-weight:600;cursor:pointer;transition:opacity .2s}
.ffl__btn:hover{opacity:.88}
.ffl__reset{background:none;border:none;font-size:.9375rem;color:#6b7280;cursor:pointer;text-decoration:underline;font-family:inherit}
.ffl__reset:hover{color:#0a0a0a}
</style>

Props

Prop Type Default Beschrijving
headline string 'Filter resultaten' Koptekst
searchPlaceholder string - Placeholder zoekveld
groups { label: string; options: string[] }[] - Filtergroepen
submitLabel string 'Resultaten tonen' Label submit-knop
resetLabel string 'Filters wissen' Label reset-knop
action string '#' Form action URL

* = verplicht