Skip to content

feat: DR-7293 Date picker#7554

Open
carlagn wants to merge 11 commits intomainfrom
feat/DR-7293-date-picker
Open

feat: DR-7293 Date picker#7554
carlagn wants to merge 11 commits intomainfrom
feat/DR-7293-date-picker

Conversation

@carlagn
Copy link
Copy Markdown
Contributor

@carlagn carlagn commented Feb 24, 2026

Add calendar
Add popover
Add presets

Summary by CodeRabbit

  • New Features

    • DatePicker (single + range) with presets, disabled/error states, form integration, calendar and popover UI, and a FontAwesome loader component
    • Reusable date-presets utilities (common ranges and helpers)
  • Documentation

    • Comprehensive DatePicker docs with live examples, usage patterns, presets, props, accessibility guidance, formatting tokens, and best practices

Testing

Testing Instructions — DatePicker Component


Single Date Picker

  • Click the trigger button — calendar popover opens
  • Select a date — popover closes and the selected date appears in the button
  • Click the trigger again — previously selected date is highlighted in the calendar
  • When no date is selected, placeholder text is visible and readable

Date Range Picker

  • Click the trigger — popover opens with two calendar months side by side
  • Click a start date — it highlights, popover stays open
  • Click an end date — the range highlights between both dates, popover closes
  • The selected range displays correctly in the trigger button (e.g. 01/04/2025 - 30/04/2025)

Date Range with Presets

  • Click the trigger — a sidebar with preset labels appears to the left of the calendars
  • Click any preset (e.g. "Last 7 days") — the range is applied and the popover closes
  • The trigger button reflects the preset range after selection

Error State

  • The trigger button shows a red border when isErrored is true
  • The text and calendar icon turn red
  • An error message appears below the input

Disabled Button State

  • The trigger button is not clickable when disabledBtn is true
  • The button appears visually muted (greyed out)
  • The cursor shows as not-allowed on hover

General / Visual

  • The calendar icon is visible on the left of the trigger at all times
  • The popover closes when clicking outside of it
  • The popover closes when pressing Escape
  • All states look correct in both light and dark mode

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
blog Ready Ready Preview, Comment May 6, 2026 11:15am
docs Ready Ready Preview, Comment May 6, 2026 11:15am
eclipse Ready Ready Preview, Comment May 6, 2026 11:15am
site Ready Ready Preview, Comment May 6, 2026 11:15am

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 24, 2026

Walkthrough

Adds a Date Picker system: new DatePicker component (single and range), Calendar and Popover UI primitives, date-presets utilities, documentation and live examples, package dependency additions, public exports, example components, and a small FontAwesome Script loader.

Changes

Date Picker Feature

Layer / File(s) Summary
Dependencies
packages/eclipse/package.json
Adds date-fns and react-day-picker dependencies.
Date Utilities
packages/eclipse/src/lib/date-presets.ts
Adds createDateRangePresets, createDateRangePreset, getLastNDays, getCurrentMonth, getPreviousMonth providing labeled date ranges and helpers.
UI Building Block — Popover
packages/eclipse/src/components/ui/popover.tsx
Adds Popover, PopoverTrigger, PopoverContent, PopoverHeader, PopoverTitle, PopoverDescription wrappers composing Portal/Positioner/Popup and forwarding primitives.
UI Building Block — Calendar
packages/eclipse/src/components/ui/calendar.tsx
Adds Calendar and CalendarDayButton wrapping react-day-picker, supplying default classNames, custom components, formatters, and Button-based day rendering.
Core Component
packages/eclipse/src/components/date-picker.tsx
Adds DatePicker, DatePickerSingle, DatePickerRange, DatePickerProps; supports single/range modes, presets, disabled/error states, formatting; re-exports DateRange and Matcher types and preset helpers.
Component Index & Public API
packages/eclipse/src/components/index.ts, packages/eclipse/src/index.ts
Re-exports date-picker components, types, and preset helpers from component index and package root; minor export formatting changes.
Examples & Documentation
apps/eclipse/src/components/date-picker-examples.tsx, apps/eclipse/content/design-system/components/datepicker.mdx, apps/eclipse/content/design-system/components/meta.json
Adds example components (single, range, presets, error, disabled, validation), comprehensive MDX docs with usage, props, presets, formatting, accessibility, and registers the doc page.

FontAwesome Script Loader

Layer / File(s) Summary
Utility Component
packages/eclipse/src/components/fontawesome-script.tsx
Adds FontAwesomeScript client component that injects a Next.js <Script> to load a FontAwesome kit (async, crossOrigin, afterInteractive).

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change—adding a date picker component system with calendar, popover, and presets functionality across the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 24, 2026

🍈 Lychee Link Check Report

3664 links: ✅ 2742 OK | 🚫 0 errors | 🔀 256 redirects | 👻 664 excluded

✅ All links are working!


Full Statistics Table
Status Count
✅ Successful 2742
🔀 Redirected 256
👻 Excluded 664
🚫 Errors 0
⛔ Unsupported 2
⏳ Timeouts 0
❓ Unknown 0

@carlagn carlagn force-pushed the feat/DR-7293-date-picker branch from adfcf60 to c5bf3b1 Compare March 5, 2026 16:19
@carlagn carlagn force-pushed the feat/DR-7293-date-picker branch from c5bf3b1 to dda84bc Compare April 24, 2026 14:26
@argos-ci
Copy link
Copy Markdown

argos-ci Bot commented Apr 24, 2026

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - May 6, 2026, 11:22 AM

@carlagn carlagn marked this pull request as ready for review May 6, 2026 10:28
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (2)
packages/eclipse/src/components/date-picker.tsx (1)

187-201: 💤 Low value

Consider using preset label as the key instead of index.

While the presets array is likely stable, using the label as a key is more semantically correct and resilient to potential reordering:

♻️ Suggested change
-                {presets.map((preset, index) => (
+                {presets.map((preset) => (
                   <Button
-                    key={index}
+                    key={preset.label}
                     variant="default-weaker"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/eclipse/src/components/date-picker.tsx` around lines 187 - 201, In
the presets.map in date-picker.tsx, replace the unstable key={index} with a
stable identifier such as key={preset.label} to avoid reordering bugs; update
the map callback that renders <Button> (the block that calls onDateRangeChange
and setOpen) to use preset.label as the key and, if labels might be non-unique
or missing, fall back to a deterministic alternative (e.g., `${preset.label ??
''}-${index}`) to guarantee uniqueness.
apps/eclipse/src/components/date-picker-examples.tsx (1)

98-103: 💤 Low value

Consider using the design system Button component for consistency.

The submit button uses raw HTML with inline Tailwind classes. For documentation examples, using the Button component from the design system would better demonstrate the intended usage patterns.

♻️ Suggested change
+import {
+  DatePickerSingle,
+  DatePickerRange,
+  createDateRangePresets,
+  Button,
+} from "@prisma/eclipse";

// ... in the form:
-      <button
-        type="submit"
-        className="px-4 py-2 bg-background-ppg text-foreground-ppg rounded-md hover:bg-background-ppg/90"
-      >
-        Submit
-      </button>
+      <Button type="submit" variant="primary">
+        Submit
+      </Button>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/eclipse/src/components/date-picker-examples.tsx` around lines 98 - 103,
Replace the raw HTML <button> used in date-picker examples with the design
system Button component: import Button where needed and render <Button
type="submit">Submit</Button> (or use the Button props that map to the current
Tailwind styling, e.g., variant/size/intent if your design system exposes them)
so the example uses the shared component API and visual styles; preserve the
type="submit" and any accessibility attributes (aria-*) when converting and
remove the inline Tailwind className.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/eclipse/content/design-system/components/datepicker.mdx`:
- Around line 228-229: The disabled predicates in the DatePicker examples use
direct timestamp comparisons (disabled={(date) => date < new Date()}) so "today"
can be treated as past; update each predicate (the disabled prop instances in
the examples) to normalize both operands to start-of-day (midnight) before
comparing—for example compute startOfDay(date) and startOfDay(new Date()) (or
call a small helper like startOfDay) and then compare those values; apply this
change to all three occurrences of the disabled prop in this file so the
comparison uses date-only values.
- Around line 186-205: The example's customPresets uses startOfWeek but doesn't
import it; update the snippet to import startOfWeek from date-fns so the example
compiles. Specifically, add an import for startOfWeek alongside any existing
DatePicker/React imports referenced in the snippet so startOfWeek(new Date()) in
customPresets (used by DatePickerRange) resolves correctly.
- Around line 544-549: The example's MyForm component calls
handleSubmit(onSubmit) but never defines onSubmit, causing a runtime
ReferenceError; fix by adding a submission handler named onSubmit in the MyForm
scope (e.g., a function that accepts form data and processes it) or by passing
an inline handler to handleSubmit (e.g., handleSubmit(data => { ... })); update
the snippet around the useForm/Controller block so MyForm declares onSubmit
before it is referenced.

In `@packages/eclipse/src/components/date-picker.tsx`:
- Around line 68-75: The JSDoc for the dateFormat prop is inconsistent with the
implemented default; update the JSDoc so the `@default` for single mode matches
the actual default used in the code (change `@default` "PPP" to `@default` "P"),
keep the range-mode `@default` "LLL dd, y" and existing examples as appropriate,
and ensure the JSDoc references the same symbol name dateFormat used in the
component so documentation and implementation align.
- Around line 126-136: The Calendar component uses the removed react-day-picker
v9 prop initialFocus; replace initialFocus with autoFocus in both Calendar
instances (the one inside PopoverContent and the other occurrence around lines
~204-211) so the Calendar props include autoFocus instead of initialFocus;
update the Calendar JSX in the date-picker component accordingly (look for the
Calendar elements with props mode="single", selected={date}, onSelect and
disabled={disabled} to locate each instance).

In `@packages/eclipse/src/components/fontawesome-script.tsx`:
- Around line 28-35: The FontAwesomeScript component currently hard-codes the
kit URL; change FontAwesomeScript to accept a kitUrl prop (e.g., function
FontAwesomeScript({ kitUrl }: { kitUrl?: string })) and use that for the Script
src, with a safe fallback to an environment variable like
process.env.NEXT_PUBLIC_FONT_AWESOME_KIT; also validate/panic with a clear error
or skip rendering if neither prop nor env var is provided so consumers must
supply their own kit URL. Ensure you only change the FontAwesomeScript
export/usage (update any internal calls to pass the prop) and keep
crossOrigin/async/strategy unchanged.

In `@packages/eclipse/src/lib/date-presets.ts`:
- Around line 22-49: The preset date calculations in date-presets.ts that
compute from via new Date(today.getTime() - N * 24 * 60 * 60 * 1000) are
vulnerable to DST errors; replace those millisecond arithmetic usages for the
"Last 7 days", "Last 14 days", "Last 30 days", and "Last 90 days" presets with
date-fns helpers (e.g. import and use subDays and optionally startOfDay) to
compute the from/to ranges (use startOfDay(today) for consistent boundaries and
subDays(startOfDay(today), N-1) or subDays(today, N-1) as appropriate) so DST
transitions are handled correctly.

---

Nitpick comments:
In `@apps/eclipse/src/components/date-picker-examples.tsx`:
- Around line 98-103: Replace the raw HTML <button> used in date-picker examples
with the design system Button component: import Button where needed and render
<Button type="submit">Submit</Button> (or use the Button props that map to the
current Tailwind styling, e.g., variant/size/intent if your design system
exposes them) so the example uses the shared component API and visual styles;
preserve the type="submit" and any accessibility attributes (aria-*) when
converting and remove the inline Tailwind className.

In `@packages/eclipse/src/components/date-picker.tsx`:
- Around line 187-201: In the presets.map in date-picker.tsx, replace the
unstable key={index} with a stable identifier such as key={preset.label} to
avoid reordering bugs; update the map callback that renders <Button> (the block
that calls onDateRangeChange and setOpen) to use preset.label as the key and, if
labels might be non-unique or missing, fall back to a deterministic alternative
(e.g., `${preset.label ?? ''}-${index}`) to guarantee uniqueness.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d10cc91b-8105-4278-b05d-4e68e282518d

📥 Commits

Reviewing files that changed from the base of the PR and between a7adfed and 87a576d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • apps/eclipse/content/design-system/components/datepicker.mdx
  • apps/eclipse/src/components/date-picker-examples.tsx
  • packages/eclipse/package.json
  • packages/eclipse/src/components/date-picker.tsx
  • packages/eclipse/src/components/fontawesome-script.tsx
  • packages/eclipse/src/components/index.ts
  • packages/eclipse/src/components/ui/calendar.tsx
  • packages/eclipse/src/components/ui/popover.tsx
  • packages/eclipse/src/index.ts
  • packages/eclipse/src/lib/date-presets.ts

Comment thread apps/eclipse/content/design-system/components/datepicker.mdx
Comment thread apps/eclipse/content/design-system/components/datepicker.mdx Outdated
Comment thread apps/eclipse/content/design-system/components/datepicker.mdx
Comment thread packages/eclipse/src/components/date-picker.tsx
Comment thread packages/eclipse/src/components/date-picker.tsx
Comment thread packages/eclipse/src/components/fontawesome-script.tsx
Comment thread packages/eclipse/src/lib/date-presets.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/eclipse/content/design-system/components/datepicker.mdx`:
- Around line 193-195: The "Yesterday" example uses Date.now() minus
24*60*60*1000 which fails across DST; change the example so the from and to
values are computed by creating a Date for midnight today and then subtracting
one calendar day via setDate(getDate() - 1) (so both `from` and `to` are that
adjusted Date), ensuring calendar-day arithmetic rather than fixed millisecond
offsets.

In `@packages/eclipse/src/lib/date-presets.ts`:
- Around line 85-90: The getLastNDays(DateRange) helper should validate its days
input: ensure the days parameter is a positive integer (>0) before computing the
range. In the getLastNDays function, check Number.isInteger(days) and days > 0
and if the check fails throw a clear RangeError (or TypeError) with a
descriptive message, so callers cannot get an invalid range; then proceed to use
startOfDay/new Date and subDays as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: aed2f433-3ec8-47fc-a728-cd72ff3deec5

📥 Commits

Reviewing files that changed from the base of the PR and between 87a576d and d371cab.

📒 Files selected for processing (2)
  • apps/eclipse/content/design-system/components/datepicker.mdx
  • packages/eclipse/src/lib/date-presets.ts

Comment thread apps/eclipse/content/design-system/components/datepicker.mdx
Comment thread packages/eclipse/src/lib/date-presets.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/eclipse/src/components/date-picker.tsx`:
- Around line 100-112: The visual "disabled" state (disabledBtn) is only applied
as styling so the DatePicker triggers remain interactive; update the trigger
Button elements (the single-date trigger and the range triggers identified by
the Button components inside date-picker.tsx) to actually disable interaction
when disabledBtn is true by adding the disabled prop (disabled={disabledBtn})
and also include aria-disabled={disabledBtn} for accessibility; keep the
existing className conditional logic (isErrored, className) but ensure the
Button elements reference disabledBtn to prevent opening/selection when
disabled.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ff8460fa-84cb-4886-80b3-64586d33c731

📥 Commits

Reviewing files that changed from the base of the PR and between 733ab81 and 13baffc.

📒 Files selected for processing (1)
  • packages/eclipse/src/components/date-picker.tsx

Comment on lines +100 to +112
<Button
variant="default"
size="lg"
className={cn(
"w-full p-1.5 text-left font-normal bg-background-default border-stroke-neutral font-mono text-foreground-neutral",
!date && "text-foreground-neutral-weak",
isErrored && "border-stroke-error text-foreground-error",
disabledBtn &&
"cursor-not-allowed text-foreground-neutral-weaker bg-background-neutral-weak",
className,
)}
type="button"
>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

disabledBtn is styling-only; the picker is still interactive.

On Line 107 and Line 154, the component looks disabled but neither trigger Button is actually disabled, so users can still open/select dates.

Suggested fix (apply to both single and range trigger buttons)
- <Popover open={open} onOpenChange={setOpen}>
+ <Popover
+   open={open}
+   onOpenChange={(nextOpen) => {
+     if (!disabledBtn) setOpen(nextOpen);
+   }}
+ >
...
- <Button
+ <Button
+   disabled={disabledBtn}
    variant="default"
    size="lg"

Also applies to: 147-159

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/eclipse/src/components/date-picker.tsx` around lines 100 - 112, The
visual "disabled" state (disabledBtn) is only applied as styling so the
DatePicker triggers remain interactive; update the trigger Button elements (the
single-date trigger and the range triggers identified by the Button components
inside date-picker.tsx) to actually disable interaction when disabledBtn is true
by adding the disabled prop (disabled={disabledBtn}) and also include
aria-disabled={disabledBtn} for accessibility; keep the existing className
conditional logic (isErrored, className) but ensure the Button elements
reference disabledBtn to prevent opening/selection when disabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant