klyv-ui

Time Slot Picker

Component 1

About

A booking widget that shows a strip of days and that day's available times as two keyboard-navigable radio groups, so free and taken slots read at a glance.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Time Slot Picker to your project and fits it to your theme.

Code

How Time Slot Picker is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";

import React from "react";
import TimeSlotPicker from "@/components/ui/time-slot-picker";
import type { TimeSlotPickerDay } from "@/components/ui/time-slot-picker";

function toISODate(d: Date) {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${m}-${day}`;
}

/** Next Monday on or after `from`. */
function nextMonday(from: Date) {
  const d = new Date(from);
  const offset = (8 - d.getDay()) % 7 || 7;
  d.setDate(d.getDate() + (d.getDay() === 1 ? 0 : offset));
  return d;
}

function buildDays(): TimeSlotPickerDay[] {
  const start = nextMonday(new Date());
  const template = [
    [
      { time: "09:00" },
      { time: "09:30", available: false },
      { time: "10:00" },
      { time: "11:30" },
      { time: "14:00", available: false },
      { time: "15:30" },
    ],
    [
      { time: "09:00" },
      { time: "10:30" },
      { time: "13:00", available: false },
      { time: "16:00" },
    ],
    [
      { time: "09:30" },
      { time: "11:00" },
      { time: "12:30" },
      { time: "14:30", available: false },
    ],
    [
      { time: "10:00", available: false },
      { time: "11:30", available: false },
    ],
    [
      { time: "09:00" },
      { time: "10:00" },
      { time: "13:30" },
      { time: "15:00" },
    ],
  ];
  return template.map((slots, i) => {
    const d = new Date(start);
    d.setDate(d.getDate() + i);
    return { date: toISODate(d), slots };
  });
}

export default function TimeSlotPickerDemo() {
  const days = React.useMemo(buildDays, []);
  const [value, setValue] = React.useState("");

  return (
    <div className="flex w-full max-w-md flex-col gap-4 rounded-[var(--radius-card,20px)] border border-line bg-surface p-6 shadow-sm">
      <div>
        <h2 className="text-[15px] font-semibold text-ink">
          Book a 30-minute demo
        </h2>
        <p className="text-[13px] text-ink-faint">
          Pick a time that works for you.
        </p>
      </div>
      <TimeSlotPicker
        days={days}
        value={value}
        onValueChange={setValue}
        timeZoneLabel="Europe/London (BST)"
      />
      <div className="flex items-center justify-between border-t border-line pt-3">
        <span className="text-[12px] font-medium text-ink-faint">
          value: {value ? value : "—"}
        </span>
        <button
          type="button"
          disabled={!value}
          className="rounded-full bg-accent px-4 py-1.5 text-[13px] font-semibold text-accent-ink disabled:cursor-not-allowed disabled:opacity-50"
        >
          Pick a time
        </button>
      </div>
    </div>
  );
}

More by klyv-ui

View all
  • Gantt Chart

    Gantt Chart

    63
  • Klyv Animated Beam

    Klyv Animated Beam

    50
  • Shader Canvas

    Shader Canvas

    49
  • Pareto Chart

    Pareto Chart

    44
  • Gooey Loader

    Gooey Loader

    26
  • Sunburst Chart

    Sunburst Chart

    24
  • Fluid Canvas

    Fluid Canvas

    23
  • Morphing Text

    Morphing Text

    21