Skip to the solution
HardFrontend7 min read

Build a Calendar Day View with overlapping events

251 views

The problem

Question presented to candidate: "Show one day of a calendar, like Google Calendar's day view, from 8 am to 7 pm. Each event is a box whose top and height come from its start and end time. When events overlap they must sit side by side, never on top of each other, and they should use as much width as they can. Let me add and delete events and see the layout update."

Requirements:

  • A vertical timeline with hour lines; each event positioned by time (top, height) and by column (left, width).
  • Overlapping events never cover each other; an event that touches another (one ends at 10:30, the next starts at 10:30) does not count as overlapping.
  • Events that do not overlap anything use the full width; within a group, an event expands right into free columns.
  • Clicking an event shows its details with a Delete button; a small form adds an event and validates it (title, end after start, inside the visible hours).
  • Events are keyboard reachable in time order and have readable labels such as "Interview, 11:00 to 12:00".

What a strong answer should cover:

  • The layout as a pure function from events to { col, cols, span }, kept out of the components and derived on every change.
  • Sorting by start (longer first on ties), sweeping into clusters of transitively overlapping events, and greedy column assignment (first column whose last event has ended).
  • Why every event in a cluster shares the cluster's column count, and how the right-expansion check works.
  • A tricky test set: a chain of overlaps, an event touching a cluster boundary, equal start times, an event that can span two columns.
  • Complexity: O(n log n) sort plus a sweep; fine for a day of events.

Clarifying questions expected:

  • "Do touching events (end equals start) count as overlapping?"
  • "Should a lone event in a busy cluster expand to the right, or keep its narrow column?"
  • "Are there all-day or multi-day events, and what is the visible time range?"

Code / implementation expected: Yes. The layout function plus a rendered day view; verifying no two boxes overlap is a plus.

  • Layout
  • Algorithms
  • Calendar

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

7 min read ยท 9 sections

React solution

Every file of the working solution. Open it in the playground to run and change it.

ReactComplete solution
import DayView from "./src/components/DayView";

const css = `
  body { margin: 0; background: #0f1115; color: #e6e6e6; font-family: system-ui, sans-serif; }
  .page { max-width: 860px; margin: 0 auto; padding: 20px 16px; }
  .dv h2 { font-size: 17px; margin: 0 0 12px; }
  .dv-body { display: flex; flex-wrap: wrap; gap: 16px; }
  .dv-grid { position: relative; flex: 1 1 320px; min-width: 0; margin-top: 8px; }
  .dv-hour { position: absolute; left: 0; right: 0; border-top: 1px solid #262c36; }
  .dv-hour span { position: absolute; top: -8px; left: 0; font-size: 11px; color: #7d8590; background: #0f1115; padding-right: 4px; }
  .dv-events { position: absolute; top: 0; bottom: 0; left: 48px; right: 4px; }
  .ev { position: absolute; box-sizing: border-box; border: 1px solid #0f1115; border-left: 3px solid #f9a825; border-radius: 6px;
    background: #2a2214; color: #f0e2c8; text-align: left; padding: 2px 6px; font: 12px/1.3 system-ui, sans-serif; overflow: hidden; cursor: pointer; }
  .ev span { color: #c9b48a; }
  .ev.sel { background: #f9a825; color: #1c140a; } .ev.sel span { color: #3d2810; }
  .ev:focus-visible { outline: 2px solid #fff; outline-offset: 1px; z-index: 2; }
  .dv-side { flex: 1 1 220px; display: flex; flex-direction: column; gap: 16px; }
  .dv-side section, .dv-side form { background: #171a21; border: 1px solid #2c3340; border-radius: 10px; padding: 12px; }
  .dv-side h3 { margin: 0 0 4px; font-size: 15px; } .dv-side p { margin: 4px 0; }
  .muted { color: #8b949e; font-size: 14px; }
  form { display: flex; flex-direction: column; gap: 8px; }
  label { display: flex; flex-direction: column; font-size: 12px; color: #9aa4b2; gap: 4px; }
  input { background: #0f1115; color: #e6e6e6; border: 1px solid #2c3340; border-radius: 6px; padding: 6px 8px; font: inherit; color-scheme: dark; }
  button { font: inherit; }
  .dv-side button { background: #222834; color: #e6e6e6; border: 1px solid #2c3340; border-radius: 8px; padding: 6px 12px; cursor: pointer; }
  .err { color: #ff8a80; font-size: 13px; }
`;

export default function App() {
  return (
    <main className="page">
      <style>{css}</style>
      <DayView />
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 103 of 107 in Machine coding

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextHard

Build Tic-Tac-Toe II (N x N board, M in a row)

Continue