Troubleshooting
Common issues and how to fix them.
Installation
Cannot find module '@kalyx/react'
Make sure you have the correct peer dependencies installed:
pnpm add @kalyx/react react react-dom
Kalyx requires React 19+. Check your version:
pnpm list react
TypeScript errors after install
Kalyx ships its own .d.ts files. If you see type errors, ensure your tsconfig.json has:
{
"compilerOptions": {
"moduleResolution": "bundler" // or "node16" / "nodenext"
}
}
The legacy "node" resolution mode doesn't support package.json exports — upgrade to "bundler" or "node16".
SSR / Next.js
useLayoutEffect warning in Next.js
Kalyx does not use useLayoutEffect. If you see this warning, it's from another library in your tree. Kalyx uses only useEffect and useId for SSR safety.
ReferenceError: window is not defined
This should never happen with Kalyx components — all window/document access is inside useEffect. If you encounter it:
- Check that you're using
@kalyx/react(not importing from@kalyx/coredirectly in a server component) - Ensure you're not destructuring Kalyx components in a Server Component file — wrap them in a Client Component:
'use client';
import { DatePicker } from '@kalyx/react';
export function MyDatePicker() {
return (
<DatePicker>
<DatePicker.Input />
<DatePicker.Popover>
<DatePicker.Calendar />
</DatePicker.Popover>
</DatePicker>
);
}
Hydration mismatch
If you see a hydration mismatch, check:
- Are you using
displayTimezone? The server and client must resolve the same timezone. Avoid relying on the system timezone — always pass an explicit IANA zone string. - Are you conditionally rendering based on
new Date()? The server timestamp differs from the client's. UsedefaultValueinstead of computing a value during render.
Popover / Positioning
Popover appears in the wrong position
Kalyx uses Floating UI with flip and shift middleware. If the popover is mispositioned:
- Check for
overflow: hiddenon ancestors — Floating UI detects overflow boundaries. A parent withoverflow: hiddencan clip or misposition the popover. - Check CSS transforms on ancestors —
transformcreates a new containing block, which can offsetposition: fixedelements. - In a modal/dialog? — The popover renders as a sibling, not a portal. If your modal clips overflow, the popover may be clipped.
Popover doesn't close on outside click
This can happen if an element calls event.stopPropagation() before the click reaches the document listener. Check your modal or dropdown wrappers.
Timezone
Selected date is off by one day
This is the most common timezone confusion. When you store a UTC ISO string like "2026-04-15T00:00:00.000Z" and display it in a timezone like Asia/Seoul (UTC+9), the displayed date is April 15 — but if the value was "2026-04-15T15:00:00.000Z", that's April 16 in Seoul.
Fix: Use displayTimezone to ensure correct display, and always let onChange handle the value — it emits civil midnight in the display timezone:
<DatePicker
value={value}
onChange={setValue}
displayTimezone="Asia/Seoul"
>
...
</DatePicker>
DST transition causes unexpected behavior
During DST transitions (e.g., US "spring forward"), 2:00 AM doesn't exist. Kalyx handles this internally with two-pass offset correction. If you're doing manual timezone math, use @kalyx/core's startOfDayInTimezone instead of computing midnight yourself.
Styling
Components have no styles at all
This is by design — Kalyx is headless. You must provide styles via classNames props or className. See the Tailwind recipe for a complete example.
classNames prop doesn't work
Make sure you're passing an object, not a string:
// ❌ Wrong — className (string) only applies to the root element
<DatePicker.Calendar className="my-calendar" />
// ✅ Right — classNames (object) targets internal slots
<DatePicker.Calendar
classNames={{
root: 'my-calendar',
day: 'my-day',
daySelected: 'my-day-selected',
}}
/>
Both className (root element) and classNames (slots) are supported. Use classNames when you need to style internal elements.
Forms
Value is not submitted with the form
In uncontrolled mode, pass a name prop to DatePicker.Root:
<DatePicker name="startDate" defaultValue="2026-04-15T00:00:00.000Z">
<DatePicker.Input name="startDate" />
...
</DatePicker>
react-hook-form integration
See the dedicated React Hook Form recipe.
Performance
Calendar re-renders on every state change
This is normal — the calendar grid is lightweight (~42 cells). If you're experiencing jank:
- Profile with React DevTools — check if the re-render is actually slow
- Avoid creating new objects on every render in parent components:
// ❌ Creates a new array on every render
<DatePicker disabled={[{ dayOfWeek: [0, 6] }]}>
// ✅ Stable reference
const DISABLED = [{ dayOfWeek: [0, 6] }] as const;
<DatePicker disabled={DISABLED}>
Bundle size seems larger than expected
Kalyx's @kalyx/react is ~15 KB gzipped (CI ceiling 16 KB). If your bundle is larger:
- Check that tree-shaking is working — only import what you use
date-fnsis a dependency and adds ~5KB for the functions Kalyx uses. If you already use date-fns in your app, the cost is shared.- Run
pnpm check-bundlein the Kalyx repo to verify
Still stuck?
- Search existing issues
- Open a bug report
- Request a feature
- Ask a question in Discussions