> ## Documentation Index
> Fetch the complete documentation index at: https://super-calendar.afonsojramos.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Solid 2

> Install the experimental Solid renderer and use reactive calendar state.

`@super-calendar/solid` provides Solid components over the same calendar logic as
the React renderers. It uses `@super-calendar/core/vanilla` and requires no React
runtime. Solid 1 is not supported.

> [!NOTE]
>
> Solid 2 support is experimental. This package targets `solid-js@2.0.0-rc.20` and
> `@solidjs/web@2.0.0-rc.20`. Keep both peers on these exact versions.

## Install the package

```bash theme={null}
pnpm add @super-calendar/solid@experimental solid-js@2.0.0-rc.20 @solidjs/web@2.0.0-rc.20 date-fns
pnpm add -D @solidjs/vite-plugin@3.0.0-next.55 vite@^8
```

Use the Solid 2 Vite plugin:

```ts theme={null}
import { defineConfig } from "vite";
import solid from "@solidjs/vite-plugin";

export default defineConfig({ plugins: [solid({ ssr: true })] });
```

Set `jsx: "preserve"` and `jsxImportSource: "@solidjs/web"` in your TypeScript
configuration. The package is ESM and supports `date-fns` 3 and 4.

## Render a controlled calendar

```tsx theme={null}
import { createSignal } from "solid-js";
import { Calendar, type CalendarEvent } from "@super-calendar/solid";

export function Schedule() {
  const [date, setDate] = createSignal(new Date(2026, 10, 2));
  const [events, setEvents] = createSignal<CalendarEvent[]>([
    { title: "Planning", start: new Date(2026, 10, 2, 9), end: new Date(2026, 10, 2, 10) },
  ]);

  return (
    <Calendar
      date={date()}
      events={events()}
      mode="week"
      height={600}
      onChangeDate={setDate}
      onDragEvent={(event, start, end) => {
        setEvents((current) =>
          current.map((item) => (item === event ? { ...item, start, end } : item)),
        );
      }}
    />
  );
}
```

`Calendar` supports month, week, day, 3-day, custom, schedule, and year modes.
Use `MonthList` for a virtualized scrolling picker and `ResourceTimeline` for
horizontal or vertical resource lanes. `DatePicker` and `DateRangePicker` wrap
the month list in a popover. See the [Solid API reference](https://super-calendar.afonsojramos.me/reference/api.md#solid-exports).

The Solid and React DOM components share prop names. Their render callbacks
return their framework's JSX. In Solid, read callback props inside JSX instead
of destructuring them into nonreactive values.

A drag stays owned by the contact that starts it. Other contacts cannot move,
finish, or cancel an active drag. An additional contact cancels a touch hold
that has not started dragging yet. Cancellation discards pending event creation
and moves. `onSelectDrag` reports selection changes live; cancellation does not
undo selection updates your callback has already applied.

`ResourceTimeline` retains the grabbed event when other events are inserted or
reordered. Removing or replacing that event cancels its drag. Events with
`draggable: false` remain clickable and keyboard accessible in both orientations.
Removing a resource cancels creation in its lane. Losing pointer capture cancels
the active interaction.

## Add range selection

```tsx theme={null}
import { MonthView, createDateRange } from "@super-calendar/solid";

export function Dates() {
  const month = new Date(2026, 10, 1);
  const selection = createDateRange(() => ({ minDate: month }));
  return (
    <MonthView
      date={month}
      minDate={month}
      selectedRange={selection.range() ?? undefined}
      onPressDay={selection.onPressDate}
      onSelectDrag={selection.selectRange}
    />
  );
}
```

Pass an accessor to `createDateRange` when constraints change. Read the returned
`range()` accessor in JSX. `createMonthGrid` and `createNow` also accept accessors;
create them inside a Solid component or root so their work is disposed with it.
The React hooks remain available from the existing React packages.

## Add date pickers

Keep picker values in signals. `DateRangePicker` reports a start-only range with
`end: null` until you choose the second day. Clearing a range reports `null`.

```tsx theme={null}
import { createSignal } from "solid-js";
import { DatePicker, DateRangePicker, type DateRange } from "@super-calendar/solid";

export function BookingDates() {
  const [date, setDate] = createSignal<Date | null>(null);
  const [range, setRange] = createSignal<DateRange | null>(null);

  return (
    <>
      <DatePicker value={date()} onChange={setDate} placeholder="Choose a day" />
      <DateRangePicker value={range()} onChange={setRange} placeholder="Choose a stay" />
    </>
  );
}
```

Both pickers accept `minDate`, `maxDate`, `isDateDisabled`, and `theme`. Changing
`disabled` to `true` closes an open popover. Re-enabling it leaves it closed.
See [date and range pickers](https://super-calendar.afonsojramos.me/guides/date-picker.md) for the shared behavior.

## Schedule resources

Use a custom field to assign each event to a resource. Apply the proposed dates
in `onDragEvent` to commit a move or resize. Return `false` to reject it.

```tsx theme={null}
import { createSignal } from "solid-js";
import { ResourceTimeline, type CalendarEvent } from "@super-calendar/solid";

type Booking = { room: string };

export function Rooms() {
  const date = new Date(2026, 10, 2);
  const [events, setEvents] = createSignal<CalendarEvent<Booking>[]>([
    {
      title: "Planning",
      start: new Date(2026, 10, 2, 9),
      end: new Date(2026, 10, 2, 10),
      room: "studio",
    },
  ]);

  return (
    <ResourceTimeline
      date={date}
      resources={[
        { id: "studio", title: "Studio" },
        { id: "meeting", title: "Meeting room" },
      ]}
      events={events()}
      resourceId={(event) => event.room}
      startHour={8}
      endHour={18}
      onDragEvent={(event, start, end, resource) => {
        setEvents((current) =>
          current.map((item) =>
            item === event ? { ...item, start, end, room: resource.id } : item,
          ),
        );
      }}
      onCreateEvent={(start, end, resource) => {
        setEvents((current) => [
          ...current,
          { title: "New booking", start, end, room: resource.id },
        ]);
      }}
    />
  );
}
```

Set `orientation="vertical"` to place resources in columns. See
[resource timelines](https://super-calendar.afonsojramos.me/guides/resource-timeline.md) for paging, business hours, and
custom headers. Direct views expect already expanded events; use
`expandRecurringEvents` when your bookings recur.

## Render custom events

`Calendar` uses `renderTimeEvent`, `renderMonthEvent`, and `renderScheduleEvent`
for the corresponding views. Direct views such as `TimeGrid` use `renderEvent`.
Define the renderer once and read its props inside JSX to keep updates reactive.

```tsx theme={null}
import { Calendar, type CalendarEvent, type SolidRenderEventArgs } from "@super-calendar/solid";

type Meeting = { room: string };

function MeetingCard(props: SolidRenderEventArgs<Meeting>) {
  return (
    <div style={{ height: "100%", overflow: "hidden", padding: "4px", "box-sizing": "border-box" }}>
      <strong>{props.event.title}</strong>
      <div>{props.event.room}</div>
    </div>
  );
}

export function Meetings(props: { date: Date; events: CalendarEvent<Meeting>[] }) {
  return (
    <Calendar date={props.date} events={props.events} mode="week" renderTimeEvent={MeetingCard} />
  );
}
```

The calendar positions the event and handles its gestures. Keep custom content
within its box; `boxHeight` reports the available timed-event height. A custom
renderer replaces the default event content and its themed appearance. Use the
shared [styling options](https://super-calendar.afonsojramos.me/guides/styling.md) when you only need different colors or spacing.

## Load an event feed

Create the source inside a component. Pass accessors for the URL or async loader
and its options so changing them reloads the feed.

```tsx theme={null}
import { Calendar, createEventSource } from "@super-calendar/solid";

export function Feed(props: { url: string; date: Date }) {
  const feed = createEventSource(
    () => props.url,
    () => ({ refetchIntervalMs: 60_000 }),
  );
  return (
    <>
      <button disabled={feed.loading()} onClick={() => void feed.refetch()}>
        Refresh
      </button>
      <p role="status">{feed.error()?.message}</p>
      <Calendar mode="week" date={props.date} events={feed.events()} />
    </>
  );
}
```

`events()`, `loading()`, and `error()` are accessors. The previous events remain
visible during a refresh or an error. A source or options change cancels the
previous URL request. Disposal stops polling and cancels pending requests;
later `refetch()` calls do nothing. Async function sources cannot be aborted,
but their stale results are ignored. Fetching starts on the client, including
after hydration; server rendering does not fetch.

Use `createEventSource(() => loadEvents)` for your own async function. URL feeds
support JSON and iCalendar through the shared [event-source options](https://super-calendar.afonsojramos.me/guides/events.md#loading-events-from-a-feed).
The example's **feed** view demonstrates loading and manual refresh.

## Customize the appearance

Pass `theme={darkSolidTheme}` for the built-in dark theme, or pass a partial
`SolidCalendarTheme`. `mergeSolidTheme` fills omitted tokens with the defaults.
Use `className` and `style` on the root, or `classNames` and `styles` for named
slots. Slot classes replace themed styles and preserve layout, matching the
[web styling contract](https://super-calendar.afonsojramos.me/guides/styling.md). Numeric lengths use pixels. No stylesheet
import is needed.

## Render on a server

The package's `solid` export lets the Vite plugin compile the library with your
app. Use `solid({ ssr: true })` for hydration. Precompiled hydratable browser and
server entries are also available through the `browser` and default export
conditions. Server rendering does not access the DOM or start timers.

Keep the initial dates, events, locale, and time zone equal on server and client.
Pass a fixed `now` to make the current-time indicator deterministic. Construct
anchor dates in the same local zone on both sides, as described in
[time zones](https://super-calendar.afonsojramos.me/guides/time-zones.md#anchor-dates-are-local).

The repository's `examples/solid` app includes `/` and `/ssr` routes. Start it
with `pnpm --filter @super-calendar/example-solid dev` after `pnpm build`.

## Troubleshoot an integration

### JSX compilation or missing exports

Check that `solid-js` and `@solidjs/web` both resolve to `2.0.0-rc.20`.
Use `@solidjs/vite-plugin@3.0.0-next.55`, `jsx: "preserve"`, and
`jsxImportSource: "@solidjs/web"`. Remove React JSX transforms from the Solid app.
Import calendar components from `@super-calendar/solid`; use
`@super-calendar/core/vanilla` for shared logic without React.

### Changes do not appear

Read accessors in JSX, such as `events={events()}`. Reading `events()` once in
the component body captures a snapshot. Keep reactive props as `props.event`
inside custom renderers instead of destructuring them. Update event arrays with
a signal setter, and replace the edited event object. For helpers such as
`createDateRange` and `createEventSource`, pass accessors for changing options.

### Hydration reports mismatches

Enable `solid({ ssr: true })`. Insert `generateHydrationScript()` from
`@solidjs/web` in the server document before the client entry, and use `hydrate`
for the container that already holds server-rendered HTML. Use `render` for an
empty client-only container. The repository example shows both paths.

Compare the initial date, events, locale, time zone, and `now` on both sides.
JSON serializes dates as strings, so restore each date field before passing
events to the calendar. Keep browser-only values out of the initial server render.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.