Skip to content

Schedule View Refactor — Token-Based Responsive Layout, Fixed Atmospheric Background & Deterministic Overlap Engine #436

Description

@ayanimea

PR: Schedule View Refactor — Token-Based Responsive Layout, Fixed Atmospheric Background & Deterministic Overlap Engine

Overview

This PR refactors the Schedule view to achieve:

  • A fixed, calm atmospheric background
  • Fully token-based theming (no hardcoded colors in components)
  • Mathematically precise time rendering
  • Deterministic overlap column layout
  • Responsive vertical scaling
  • Reduced visual stress and improved clarity
  • Accessibility and performance safeguards

The result is a schedule that feels stable, structured, and lightweight while preserving its cosmic identity.


Visual Reference

The final visual state of the Schedule view is documented here:
/docs/schedule-after-mockup.png and below:

Image

This image represents the intended layout, proportions, and visual weight hierarchy.


Mockup Description (Detailed)

The mockup shows a single-day vertical schedule view with the following characteristics:

Overall Composition

  • A full-height vertical timeline (00:00–23:00).
  • Evenly spaced hourly divisions.
  • Subtle hour separators (no heavy grid).
  • A visible current-time horizontal indicator.
  • Events positioned proportionally by time.
  • A fixed atmospheric background with:
    • A deep vertical sky gradient
    • Subtle time-of-day tint
    • Static star field
    • A single blurred planet in the bottom-right

The design feels immersive but not decorative-heavy.


Background (Fixed & Stable)

The background is completely fixed and does not scroll.

It consists of:

1. Base Sky Gradient (Vertical)

A deep indigo → blue → darker indigo vertical gradient.

It must:

  • Be subtle
  • Avoid high saturation
  • Preserve text contrast
  • Not contain harsh transitions

2. Time-of-Day Atmospheric Overlay

The day is visually segmented by a very subtle overlay:

  • Morning: slight warm tint (very low opacity)
  • Afternoon: neutral blue tint
  • Evening: slightly cooler violet tint

Important:

  • These zones are purely visual.
  • They do NOT create layout columns.
  • They do NOT split events.
  • They do NOT duplicate headers.
  • They must remain barely perceptible.

3. Stars

  • Three star sizes only: 1px, 1.5px, 2px.
  • 70% small, 25% medium, 5% large.
  • Opacity ≤ 0.4.
  • No animation.
  • No parallax.
  • No drift.
  • Must remain subtle texture, not focal elements.

4. Single Planet

  • Exactly one.
  • Positioned bottom-right.
  • Blurred.
  • Low opacity (≤ 0.08 effective).
  • Never animated.
  • Must never compete with event readability.

Time Grid

The time grid is mathematically precise.

Each hour:

  • Occupies identical vertical space.
  • Scales responsively via --hour-height.
  • Has subtle separators.
  • No rigid boxed layout.

Event height and position are proportional to time:
top = (startMinutes / 60) * hourHeight
height = (durationMinutes / 60) * hourHeight

No visual approximation is allowed.


Event Blocks

Events are:

  • Slightly rounded (10px radius)
  • Semi-translucent glass
  • Subtle vertical gradient
  • Soft border
  • No heavy drop shadows
  • No excessive glow

Each event includes:

  • Time range (secondary text)
  • Title (primary text)
  • Optional metadata

Hierarchy must remain clear even when columns narrow.


Overlap Behavior

Columns are created ONLY when events overlap in time.

Two events overlap if:
A.start < B.end && A.end > B.start

Touching at boundaries is NOT overlap.

Events crossing Morning → Afternoon remain a single continuous block.

Columns are triggered only by real time intersection.


Current Time Indicator

The current time is represented by:

  • A thin horizontal mint line
  • A subtle glow
  • A small circular marker at the left edge
  • Optional slow pulse (disabled under reduced motion)

Position must be mathematically accurate.

It must feel informative, not alarming.


Implementation Details

1. Token-Based Color System

All visual values defined in :root.

No hardcoded colors in components.

:root {
  --bg-sky-top: #0F172A;
  --bg-sky-mid: #16213E;
  --bg-sky-bottom: #1A1F3C;

  --zone-morning: rgba(255, 200, 120, 0.05);
  --zone-afternoon: rgba(100, 160, 255, 0.04);
  --zone-evening: rgba(120, 100, 200, 0.05);

  --star-color: rgba(255, 255, 255, 0.3);

  --planet-core: rgba(180, 200, 255, 0.08);
  --planet-mid: rgba(150, 180, 255, 0.05);
  --planet-edge: rgba(120, 150, 255, 0.03);

  --event-glass-top: rgba(255, 255, 255, 0.06);
  --event-glass-bottom: rgba(255, 255, 255, 0.03);
  --event-border: rgba(255, 255, 255, 0.15);

  --category-blue: rgba(100, 160, 255, 0.22);

  --now-line: #A3FFD6;

  --hour-height: clamp(48px, 8vh, 96px);
}

2. Fixed Background Layer

.app-background {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

3. Deterministic Overlap Algorithm

Cluster events:

function clusterEvents(events) {
  events.sort((a, b) => a.start - b.start);
  const clusters = [];
  let cluster = [];

  for (const event of events) {
    if (!cluster.length) {
      cluster.push(event);
      continue;
    }

    const maxEnd = Math.max(...cluster.map(e => e.end));

    if (event.start < maxEnd) {
      cluster.push(event);
    } else {
      clusters.push(cluster);
      cluster = [event];
    }
  }

  if (cluster.length) clusters.push(cluster);
  return clusters;
}

Assign columns:

function assignColumns(cluster) {
  const columns = [];

  cluster.forEach(event => {
    let placed = false;

    for (let i = 0; i < columns.length; i++) {
      const last = columns[i][columns[i].length - 1];
      if (last.end <= event.start) {
        columns[i].push(event);
        event.column = i;
        placed = true;
        break;
      }
    }

    if (!placed) {
      columns.push([event]);
      event.column = columns.length - 1;
    }
  });

  cluster.forEach(event => {
    event.totalColumns = columns.length;
  });
}

Accessibility

  • WCAG AA minimum contrast maintained
  • prefers-reduced-motion disables pulse animation
  • Increased border contrast under prefers-contrast: more

Performance Constraints

  • No parallax
  • No animated background
  • No blur > 80px
  • ≤ 4 layered gradients per container
  • 60fps scroll target

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions