calendar day-view time-blocks schedule productivity planner now-line calendar day view time blocks schedule hours events planner now line show a daily schedule display time blocks on a day grid interactive day calendar
Calendar Day View
Fetch pattern JSON:
curl https://webspire.de/patterns/calendar-day/base.json base.html
<!-- Calendar Day View — 6:00–20:00, hourHeight = 64px -->
<!-- Event top = (hour - 6 + min/60) * 64 | height = durationMin/60 * 64 -->
<div class="ws-calendar-day bg-[var(--ws-color-surface)] rounded-2xl border border-slate-200 overflow-hidden flex flex-col" style="height: 680px">
<!-- Header -->
<div class="flex items-center justify-between px-4 py-3 border-b border-slate-100 flex-shrink-0">
<h2 class="text-sm font-semibold text-slate-900">Freitag, 27. März</h2>
<div class="flex items-center gap-1">
<button class="px-2 py-1 rounded-md text-xs text-slate-500 hover:bg-slate-100 dark:hover:bg-slate-800">‹</button>
<button class="px-2.5 py-1 rounded-md text-xs font-medium bg-blue-600 text-white">Heute</button>
<button class="px-2 py-1 rounded-md text-xs text-slate-500 hover:bg-slate-100 dark:hover:bg-slate-800">›</button>
</div>
</div>
<!-- Scrollable grid -->
<div class="flex-1 overflow-y-auto">
<!-- Grid: total height = 14 hours × 64px = 896px -->
<div class="relative" style="height: 896px">
<!-- Hour rows -->
<div class="absolute inset-0 pointer-events-none select-none">
<!-- 06:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:0px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">06:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 07:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:64px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">07:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 08:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:128px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">08:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 09:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:192px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">09:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 10:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:256px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">10:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 11:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:320px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">11:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 12:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:384px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">12:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 13:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:448px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">13:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 14:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:512px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">14:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 15:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:576px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">15:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 16:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:640px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">16:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 17:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:704px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">17:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 18:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:768px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">18:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
<!-- 19:00 --> <div class="absolute left-0 right-0 flex items-start" style="top:832px;height:64px"><span class="w-12 text-right pr-2 pt-1 text-[10px] text-slate-400">19:00</span><div class="flex-1 border-t border-slate-100 dark:border-slate-800 mt-[10px]"></div></div>
</div>
<!-- 15-min half-lines (subtle dashes at :30) -->
<div class="absolute inset-0 pointer-events-none select-none">
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:32px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:96px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:160px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:224px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:288px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:352px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:416px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:480px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:544px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:608px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:672px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:736px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:800px"></div>
<div class="absolute left-12 right-0 border-t border-dashed border-slate-50" style="top:864px"></div>
</div>
<!-- Events -->
<!-- Deep Work: 09:00–10:30 → top=(3+0/60)*64=192, height=90min/60*64=96 -->
<div class="absolute rounded-lg bg-blue-50 border-l-[3px] border-blue-500 px-2.5 py-1.5 overflow-hidden cursor-pointer hover:bg-blue-100 dark:hover:bg-blue-900/50 transition-colors"
style="left:52px;right:6px;top:192px;height:96px">
<p class="text-xs font-semibold text-blue-700 leading-tight">Deep Work</p>
<p class="text-[10px] text-blue-500 mt-0.5">09:00 – 10:30</p>
<span class="inline-block mt-1 text-[10px] bg-blue-200 text-blue-700 rounded px-1">Projekt</span>
</div>
<!-- Team Sync: 11:30–12:00 → top=(5.5)*64=352, height=32 -->
<div class="absolute rounded-lg bg-emerald-50 border-l-[3px] border-emerald-500 px-2.5 py-1.5 overflow-hidden cursor-pointer hover:bg-emerald-100 dark:hover:bg-emerald-900/50 transition-colors"
style="left:52px;right:6px;top:352px;height:32px">
<p class="text-xs font-semibold text-emerald-700 leading-tight">Team Sync · 11:30</p>
</div>
<!-- API Review: 14:00–15:00 → top=(8)*64=512, height=64 -->
<div class="absolute rounded-lg bg-violet-50 border-l-[3px] border-violet-500 px-2.5 py-1.5 overflow-hidden cursor-pointer hover:bg-violet-100 dark:hover:bg-violet-900/50 transition-colors"
style="left:52px;right:6px;top:512px;height:64px">
<p class="text-xs font-semibold text-violet-700 leading-tight">API Review</p>
<p class="text-[10px] text-violet-500 mt-0.5">14:00 – 15:00</p>
</div>
<!-- Now line: 10:15 → top=(4.25)*64=272 -->
<div class="absolute left-0 right-0 z-10 pointer-events-none flex items-center" style="top:272px">
<span class="w-12 text-right pr-1.5 text-[10px] font-bold text-red-500 select-none">10:15</span>
<div class="flex-1 h-px bg-red-500">
<div class="w-2 h-2 rounded-full bg-red-500 -mt-[3px] -ml-[1px]"></div>
</div>
</div>
</div>
</div>
</div>
Details
Dark Mode Tailwind Only SSR Safe Copy & Paste
Stable Published
calendarday-viewtime-blocksscheduleproductivityplannernow-line
Slots
| Name | Required | Description |
|---|---|---|
| header | No | Date label and navigation controls above the grid. |
| events | No | Absolutely positioned event blocks within the time grid. |
| now-line | No | Red horizontal indicator showing the current time. |
Props
| Name | Type | Default | Description |
|---|---|---|---|
| dayStart | number | 6 | First visible hour (0–23). |
| dayEnd | number | 20 | Last visible hour (0–23). Each hour is 64px tall. |
| hourHeight | number | 64 | Pixel height per hour row. |
A scrollable day-view calendar grid showing hourly rows from 6:00 to 20:00. Time-block events are absolutely positioned based on start time and duration. A red “now” line marks the current time. Use as the core component for daily scheduling, time-blocking, and agenda views in productivity applications.