Zoeken...  ⌘K GitHub

IconList icon

IconList component.

/icon-list
src/components/icon/IconList.astro
---
/**
 * IconList
 * Sectie-header + verticale lijst met icon-items. Elk item: SVG-icoon, titel,
 * optionele badge en beschrijving.
 *
 * Props:
 * - eyebrow?: string
 * - headline?: string
 * - divided?: boolean
 * - compact?: boolean
 * - items?: Array<{ icon: string; title: string; badge?: string; desc: string }>
 *   (icon = inline SVG via set:html)
 */
interface Props {
  eyebrow?: string;
  headline?: string;
  divided?: boolean;
  compact?: boolean;
  items?: { icon: string; title: string; badge?: string; desc: string }[];
}

const ICON_CHECK = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>';
const ICON_PHONE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"/></svg>';
const ICON_BOLT = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>';
const ICON_LOCK = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/></svg>';

const {
  eyebrow = 'Wat je krijgt',
  headline = 'Geen verrassingen, dit is inbegrepen',
  divided = true,
  compact = false,
  items = [
    { icon: ICON_CHECK, title: 'Maandelijkse rapportage', badge: 'Inbegrepen', desc: 'Overzichtelijk dashboard met alle cijfers. Geen losse bijlagen.' },
    { icon: ICON_PHONE, title: 'Directe bereikbaarheid', desc: 'Je vaste aanspreekpunt is bereikbaar via chat en e-mail.' },
    { icon: ICON_BOLT, title: 'Doorlopende optimalisatie', desc: 'Campagnes worden bijgesteld op basis van actuele data.' },
    { icon: ICON_LOCK, title: 'Geen langlopend contract', desc: 'Maand op maand. Opzeggen kan altijd per maand.' },
  ],
} = Astro.props;
---

<section class={`bl-section ils__section${compact ? ' ils__compact' : ''}`}>
  <div class="bl-inner bl-inner--narrow ils__inner">
    {(eyebrow || headline) && (
      <div class="ils__header">
        {eyebrow && <p class="ils__eyebrow">{eyebrow}</p>}
        {headline && <h2 class="ils__headline">{headline}</h2>}
      </div>
    )}
    <ul class={`ils__list${divided ? ' ils__list--divided' : ''}`} role="list">
      {items.map((item, i) => (
        <li class="ils__item" style={`--delay: ${i * 70}ms`}>
          <span class="ils__icon-wrap" aria-hidden="true" set:html={item.icon}></span>
          <span class="ils__content">
            <span class="ils__title-row">
              <span class="ils__title">{item.title}</span>
              {item.badge && <span class="ils__badge">{item.badge}</span>}
            </span>
            <span class="ils__desc">{item.desc}</span>
          </span>
        </li>
      ))}
    </ul>
  </div>
</section>

<style>
.ils__header{margin-bottom:2rem}
.ils__eyebrow{font-size:.75rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--color-accent);margin:0 0 .5rem}
.ils__headline{font-size:clamp(1.5rem,2.5vw,2rem);font-weight:800;color:var(--color-primary);margin:0;line-height:1.2}
.ils__list{list-style:none;padding:0;margin:0}
.ils__list--divided .ils__item:not(:last-child){border-bottom:1px solid rgba(0,0,0,.08)}
.ils__item{display:flex;align-items:flex-start;gap:1rem;padding:1.125rem 0;opacity:0;transform:translate(-18px)}
.ils__compact .ils__item{padding:.625rem 0;gap:.75rem}
.ils__item--visible{animation:ils-slidein .45s ease forwards;animation-delay:var(--delay, 0ms)}
@keyframes ils-slidein{to{opacity:1;transform:translate(0)}}
.ils__icon-wrap{display:flex;align-items:center;justify-content:center;width:40px;height:40px;flex-shrink:0;border-radius:var(--radius);background:#6366f112;color:var(--color-accent);transition:background .2s ease}
.ils__compact .ils__icon-wrap{width:32px;height:32px}
.ils__item:hover .ils__icon-wrap{background:#6366f129}
.ils__icon-wrap svg{width:55%;height:55%}
.ils__content{display:flex;flex-direction:column;gap:.25rem;padding-top:.125rem}
.ils__title-row{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}
.ils__title{font-size:1.0625rem;font-weight:700;color:var(--color-primary);line-height:1.3}
.ils__compact .ils__title{font-size:1rem}
.ils__desc{font-size:.9375rem;color:var(--color-muted);line-height:1.65}
.ils__compact .ils__desc{font-size:.9375rem}
.ils__badge{display:inline-flex;align-items:center;padding:.15em .55em;border-radius:999px;background:#6366f11a;color:var(--color-accent);font-size:.7rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;white-space:nowrap}
</style>