Skip to content

feature: Add pickerType prop with custom popper-based dropdown to modus-wc-time-input - #1201

Draft
ElishaSamPeterPrabhu wants to merge 6 commits into
mainfrom
cursor/time-picker-design-0c88
Draft

feature: Add pickerType prop with custom popper-based dropdown to modus-wc-time-input#1201
ElishaSamPeterPrabhu wants to merge 6 commits into
mainfrom
cursor/time-picker-design-0c88

Conversation

@ElishaSamPeterPrabhu

@ElishaSamPeterPrabhu ElishaSamPeterPrabhu commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

📄 Summary of Changes

Adds a new optional pickerType prop to modus-wc-time-input that renders a custom Popper.js-powered dropdown instead of the native browser time picker. The default behavior (no pickerType) is fully backwards compatible.

New props:

  • pickerType?: 'picker' | 'datalist' — controls which custom dropdown to render
  • use12Hour?: boolean (HTML attribute: use12-hour) — shows AM/PM column in picker mode

picker type renders side-by-side scrollable columns:

  • Hours column (01–12 or 00–23 depending on use12Hour)
  • Minutes column (00–59)
  • Seconds column (00–59) when showSeconds is true
  • AM/PM column when use12Hour is true
  • Selected item highlighted with var(--modus-wc-color-primary-pale, #DCEDF9)

datalist type renders a flat popper panel:

  • Items sourced from datalistOptions
  • Selected item highlighted
  • Hardcoded "Other" item at the bottom that closes the dropdown and enables free-text entry

Shared dropdown behavior:

  • @popperjs/core with placement: 'bottom-start', strategy: 'fixed', offset: [0, 4], flip modifier (matching modus-wc-date lifecycle pattern)
  • Closes on outside click and Escape key
  • When pickerType is set, renders <input type="text" readonly> to prevent native browser picker

Design tokens (from Figma node 44494:96164):

  • Panel: --modus-wc-color-base-page background, 1px solid var(--modus-wc-color-base-200) border, var(--rounded-box, 16px) border-radius, shadow
  • Panel padding: 8px (--t-spacing/2 from Figma)
  • Column gap: 12px between picker columns
  • Column max-height: 220px (6 items × 40px − 5 × 4px negative overlap = correct height; total panel including padding = 236px matching Figma)
  • Item: padding: 8px 16px, border-radius: var(--modus-wc-border-radius-btn, 8px), font-size: var(--modus-wc-font-size-sm, 14px), line-height: 24px, margin-bottom: -4px (last-child resets to 0)
  • Selected: var(--modus-wc-color-primary-pale, #DCEDF9)
  • Text: var(--modus-wc-color-base-content, #171c1e)

Files changed:

  • modus-wc-time-input.tsx — new props, popper lifecycle, picker/datalist render methods
  • modus-wc-time-input.scss — dropdown panel and item styles with correct Figma tokens
  • modus-wc-time-input.stories.tsWithPicker, WithPickerSeconds, WithPickerDatalist stories
  • modus-wc-time-input.spec.ts — comprehensive tests covering all branches; 100% coverage

💭 Type of Change

  • New feature (adds functionality)

📋 Test Plan

All 1495 unit tests pass with 100% code coverage on modus-wc-time-input.tsx (statements, branches, functions, lines). Tests cover:

  • Native time input unchanged when pickerType is undefined
  • Text input with readonly when pickerType is set
  • 24-hour and 12-hour display formatting (midnight, noon, PM edge cases)
  • Column counts for 12-hour, 24-hour, with/without seconds
  • Hour selection: AM mode (non-12, 12→midnight), PM mode (non-12, 12→stay-12)
  • Minute and second selection
  • AM/PM toggling: PM→AM, AM→PM, no-op (AM when already AM)
  • Datalist: option selection, "Other" → free text entry
  • Dropdown: open/close via click, Escape key, outside click
  • Disabled/readOnly inputs don't open dropdown
  • Popper cleanup on disconnectedCallback

✅ Self Code Review Checklist

  • My code is clean and readable
  • I followed standard conventions
  • Component code is WCAG 2.2 compliant (if applicable)
  • I have made theme files changes (if applicable)
  • I have made documentation changes (if applicable)
  • I have made Storybook changes including usage documentation (if applicable)
  • I have tested the component thoroughly in Storybook including RTL rendering (if applicable)

🔗 Work Item

Issue #

Open in Web Open in Cursor 

…us-wc-time-input

- Add pickerType?: 'picker' | 'datalist' prop; when undefined, native browser time picker is preserved (backwards compatible)
- Add use12Hour?: boolean prop for 12-hour AM/PM format display in picker columns
- picker type: renders side-by-side scrollable columns (hours, minutes, optional seconds, optional AM/PM)
- datalist type: renders flat popper panel from datalistOptions with hardcoded 'Other' option for free-text entry
- Use @popperjs/core with placement: bottom-start, strategy: fixed, offset [0, 4] and flip modifier
- Close dropdown on outside click (@listen('click', { target: 'document' })) and Escape key
- When pickerType is set, render type="text" readonly input to suppress native picker
- Add dropdown panel SCSS with design tokens: border-radius 16px, primary-pale selected highlight (#DCEDF9)
- Add WithPicker, WithPickerSeconds, WithPickerDatalist stories
- Add comprehensive unit and snapshot tests covering picker/datalist rendering, selection, AM/PM toggling, and dropdown state

Co-authored-by: Elisha Sam Peter Prabhu <ElishaSamPeterPrabhu@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Blazor Story Preview

Preview is available at: https://trimble-oss.github.io/modus-wc-2.0/pr-preview/pr-1201/blazor/

- SCSS: replace #ffffff with #fff and rgba() with rgb() to satisfy stylelint color rules
- Spec: replace (instance as any) casts with bracket notation instance['prop'] following codebase convention
- Spec: remove unnecessary 'as HTMLButtonElement' assertions on querySelectorAll('button') results
- Run prettier on spec and tsx files

Co-authored-by: Elisha Sam Peter Prabhu <ElishaSamPeterPrabhu@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Storybook Preview

Preview is available at: https://trimble-oss.github.io/modus-wc-2.0/pr-preview/pr-1201/

@ElishaSamPeterPrabhu ElishaSamPeterPrabhu added the feature The PR raised is to add a feature label Jun 25, 2026
SCSS/design tokens (from Figma node 44494:96164):
- Panel padding: 8px (--t-spacing/2) all sides
- Column gap: 12px between picker columns
- Column max-height: 220px (6 items × 40px – 5 × 4px overlap = correct height matching 236px total panel)
- Item margin-bottom: -4px (last child: 0) matching Figma negative overlap pattern
- Item line-height: 24px
- Colors mapped to --modus-wc-color-base-200 (border), --modus-wc-color-base-content (text), --rounded-box (radius)
- Datalist panel: overflow hidden instead of explicit padding

Coverage (100% on all metrics):
- Add tests for disconnectedCallback popper cleanup
- Add tests for handleFreeInputChange and handleFreeInputBlur
- Add tests for handlePickerHour AM branches (hour=12→midnight, hour≠12→direct)
- Add tests for handlePickerSecond
- Add tests for handlePickerAmPm no-op (AM when AM) and PM→AM
- Add tests for disabled/readOnly click early return
- Add tests for empty value display
- Simplify parseTimeValue to destructuring with defaults; mark unreachable defaults and setTimeout with istanbul ignore next

Co-authored-by: Elisha Sam Peter Prabhu <ElishaSamPeterPrabhu@users.noreply.github.com>
- Make renderPickerColumn generic <T extends number | string> to fix
  type mismatch between handlers (number) and AM/PM handler (string)
- Explicitly type ampmItems value as 'AM' | 'PM' literal union
- Fix pre-existing modus-wc-autocomplete.spec.ts cast via unknown
  to unblock stencil build (unrelated to time-picker feature)

Co-authored-by: Elisha Sam Peter Prabhu <ElishaSamPeterPrabhu@users.noreply.github.com>
Co-authored-by: Elisha Sam Peter Prabhu <ElishaSamPeterPrabhu@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature The PR raised is to add a feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants