Future of Open Source: Annual Summit
Two days of talks, workshops, and hallway conversations with maintainers from across the open-source ecosystem.
- July 1, 2026
- 09:00 - 18:00
- Istanbul Conference Center
Event preview card with six status states and four layouts — capacity-aware badges, overlay links, and soft-failure item handling.
Use when listing events on a community / association / conference / training site, or when mixing events into a multi-content feed. The grid variant fits magazine grids; the feed variant fits social-style single-column feeds; the list variant fits info-rich sidebars / dashboard listings; the compact variant fits text-only sidebar widgets / 'upcoming events' tickers. Public helpers (`getEventStatus`, `EVENT_STATUS_CONFIG`, `formatEventDate`, `getDaysUntilEvent`) are exported alongside the card so consumers can derive status independently for header counters, calendar coloring, filter logic, or deterministic tests — without rendering a card. Migration origin: kasder kas-social-front-v0 EventCard.tsx + SocialEventCard.tsx.
pnpm dlx shadcn@latest init"registries": {
"@ilinxa": "https://ui.ilinxa.com/r/{name}.json"
}pnpm dlx shadcn@latest add @ilinxa/event-cardAdd -fixtures for dummy data:
pnpm dlx shadcn@latest add @ilinxa/event-card-fixturesTwo days of talks, workshops, and hallway conversations with maintainers from across the open-source ecosystem.
Hands-on workshop covering Tailwind v4's new theme system, container queries, and OKLCH color migration.
Walk through a real WCAG 2.1 AA audit on a production component library and the fixes that followed.
Live coding session — building a force-directed knowledge graph editor on top of Sigma.js v3 and React 19.
Five founders share what's working and what's not in technical hiring this year. Off the record.
Two-day hands-on training on GraphQL federation v2 — from subgraph composition through production rollout.
Full-day flagship event — keynotes, breakout tracks, networking, and the annual Knowledge Day awards ceremony.
Casual drop-in office hours — no registration needed, no cap. Bring your questions about anything we ship.
Reach for EventCard when you need an event preview with a live, time-and-capacity-aware status (registration open, almost full, sold out, happening right now, ended) plus a status-driven CTA. Four layouts: variant="grid" (image-on-top magazine card), variant="feed" (full-bleed image background, white-on-dark content), variant="list" (thumbnail + 4-icon meta + status indicator), and variant="compact" (text-only minimal row for sidebars / widgets).
import { EventCard } from "@/components/event-card";
<EventCard
event={{
id: "1",
title: "Annual Summit",
type: "Conference",
date: "2026-07-01",
time: "09:00 - 18:00",
location: "Istanbul Conference Center",
image: "/cover.jpg",
capacity: 200,
registered: 50,
}}
variant="grid"
href="/events/1"
/>;grid — image-on-top magazine card with full meta lines, capacity progress bar, and decorative status CTA at the foot. Renders well in 1/2/3-column responsive grids.feed — full-bleed image background, content overlaid white-on-dark. Single-column feed item. No capacity progress bar (intentional — spots-left is shown inline in the meta row instead).list— info-rich row with thumbnail: 16/20 px square thumb left, content middle (status badge + type badge + title + 4-icon inline meta row showing date / time / location / spots-left), status-aware right indicator (days-until / pulsing "Live now" / chevron). Featured rows get a left accent border. Use when you want a scannable list with visual context per row.compact— text-only minimal row for sidebars / widgets / "upcoming events" tickers. Title + type pill (top-right) + 3 stacked meta lines (date / time / location). NO thumbnail, NO status badge, NO capacity bar. Tightest variant — maximum density per pixel. Pairs naturally with a "See all →" footer link.Status flows from the event data + an optional now reference. The card never needs you to set status — it's derived from the event and clock:
open — registrations available, more than 7 days out.upcoming — within 7 days. Amber badge.lastSpots — ≥80% capacity hit. Amber badge + spots-left counter flips to text-destructive when ≤5 left.ongoing — between start and end. Pulsing badge + live indicator.full — capacity reached. Sold-out CTA, button disabled.expired — past end date. Card fades to opacity-60 grayscale-30; CTA shows "View details."The status helpers are exported alongside the component so consumers can derive status, format dates, and compute days-until without rendering an actual card — for header counters, calendar day-cells, filter logic, deterministic tests:
import {
EventCard,
getEventStatus,
EVENT_STATUS_CONFIG,
formatEventDate,
getDaysUntilEvent,
type EventStatus,
} from "@/components/event-card";
// Header counter
const liveCount = events.filter(
(e) => getEventStatus(e) === "ongoing",
).length;
// Calendar day cell — pure-helper composition, no card render
function DayCell({ events, day }: { events: EventCardItem[]; day: Date }) {
const todays = events.filter((e) => sameDay(e.date, day));
const hasOngoing = todays.some(
(e) => getEventStatus(e, day) === "ongoing",
);
return (
<div className={hasOngoing ? "bg-accent/30" : ""}>
{todays.length > 0 && <span>{todays.length}</span>}
</div>
);
}import NextLink from "next/link";
<EventCard
event={event}
variant="grid"
linkComponent={NextLink}
getHref={(e) => `/etkinlik/${e.slug}`}
/>;<EventCard
event={event}
variant="grid"
href={href}
formatDate={(d) =>
new Date(d).toLocaleDateString("tr-TR", {
day: "numeric",
month: "long",
year: "numeric",
})
}
labels={{
open: "Kayıt Açık",
upcoming: "Yaklaşıyor",
ctaRegister: "Kayıt Ol",
daysUntilSuffix: "gün kaldı",
capacityAriaPrefix: "Kayıtlı",
capacityAriaSeparator: "/",
// ... 17 keys total, all optional
}}
typeStyles={{
Konferans: { className: "bg-primary/10 text-primary border-primary/20" },
}}
/>;The whole card is a link via the overlay-link pattern. Drop nested interactive buttons (Save / Share / Calendar) into the actions prop — they render at z-10 above the link overlay. Each action button MUST call e.preventDefault() + e.stopPropagation() in its onClick or the click bubbles to the link and navigates. Tab order: card-link → action1 → action2 → next card.
now for testing + live clocksPass a now Date to make status derivation deterministic. For demos / SSR / screenshot tests, pin nowto a fixed date so events don't silently drift over time. For minute-accurate live status, drive now from a parent setInterval:
function LiveEvents({ events }: { events: EventCardItem[] }) {
const [now, setNow] = useState(() => new Date());
useEffect(() => {
const id = setInterval(() => setNow(new Date()), 60_000);
return () => clearInterval(id);
}, []);
return events.map((e) => (
<EventCard key={e.id} event={e} variant="grid" href={`/events/${e.id}`} now={now} />
));
}Only id, title, type, date are required. Missing optional fields gracefully omit:
capacity / registered — capacity bar + spots-left counter omitted; status logic skips full / lastSpots states; CTA reverts to plain Register / View Details / Ended.image — tinted placeholder with calendar icon.endDate — falls back to date (single-day event spans 00:00 → 23:59:59).time / location / description — meta line omitted.actions.setInterval. For live updates, drive now from upstream.getEventStatus, EVENT_STATUS_CONFIG, formatEventDate, getDaysUntilEvent) are part of the API contract — stable across v0.x.motion-safe: — reduced-motion users see static cards.