Skip to content

feat(duration-input): add experimental duration input#3783

Draft
neil-krichi wants to merge 2 commits intomainfrom
feature-duration-input
Draft

feat(duration-input): add experimental duration input#3783
neil-krichi wants to merge 2 commits intomainfrom
feature-duration-input

Conversation

@neil-krichi
Copy link
Copy Markdown
Contributor

@neil-krichi neil-krichi commented Mar 27, 2026

Summary

  • add an experimental DurationInput field in f0 with a minutes-based public API to ease Gamma migration
  • support both controlled and uncontrolled usage, and keep className internal-only to match package conventions
  • validate the component against the manual compensation allocation flow in factorial using the real packaged F0 build

Testing

  • pnpm exec vitest run --project=unit src/experimental/Forms/Fields/DurationInput/__tests__/DurationInput.test.tsx
  • pnpm tsc
  • pnpm lint
  • pnpm jest src/modules/attendance/components/ClockIn/TabsBreakdown/CompensationPannel/FlexibleCompensationAllocation/AllocationInputs.spec.tsx --runInBand in factorial/frontend

Factorial is conducting an analysis on the impact of the used skills. This was autogenerated, please don't delete:

  • factorial-f0
  • factorial-pr

Copilot AI review requested due to automatic review settings March 27, 2026 10:43
@github-actions github-actions bot added feat react Changes affect packages/react labels Mar 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 27, 2026

✅ No New Circular Dependencies

No new circular dependencies detected. Current count: 0

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 27, 2026

🔍 Visual review for your branch is published 🔍

Here are the links to:

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 27, 2026

📦 Alpha Package Version Published

Use pnpm i github:factorialco/f0#npm/alpha-pr-3783 to install the package

Use pnpm i github:factorialco/f0#b1290d9a07079b8d01cb3a1390683bff6d9239d1 to install this specific commit

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 27, 2026

Coverage Report for packages/react

Status Category Percentage Covered / Total
🔵 Lines 44.61% 10584 / 23724
🔵 Statements 43.91% 10906 / 24833
🔵 Functions 36.72% 2401 / 6537
🔵 Branches 36.19% 6790 / 18757
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/react/src/experimental/Forms/Fields/exports.ts 100% 100% 100% 100%
packages/react/src/experimental/Forms/Fields/DurationInput/DurationInput.tsx 95.77% 78.26% 100% 95.71% 45-48, 67-70, 74-77
packages/react/src/experimental/Forms/Fields/DurationInput/index.tsx 100% 100% 100% 100%
Generated in workflow #12286 for commit 8f3c4f5 by the Vitest Coverage Report Action

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an experimental DurationInput field to the React package’s experimental Forms Fields, using a minutes-based value API to support Gamma migration.

Changes:

  • Introduces DurationInput component that renders hours/minutes inputs and emits total minutes.
  • Adds Storybook stories for common states (filled, empty, error, readonly, disabled).
  • Adds unit tests covering rendering, normalization, clearing, and controlled updates; exports the field from the experimental Fields entrypoint.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/react/src/experimental/Forms/Fields/exports.ts Re-exports the new experimental field from the Forms Fields entrypoint.
packages/react/src/experimental/Forms/Fields/DurationInput/index.tsx Barrel export for the new field.
packages/react/src/experimental/Forms/Fields/DurationInput/DurationInput.tsx Implements the DurationInput component (hours/minutes UI + minutes-based API).
packages/react/src/experimental/Forms/Fields/DurationInput/stories/DurationInput.stories.tsx Adds Storybook stories for the new field.
packages/react/src/experimental/Forms/Fields/DurationInput/tests/DurationInput.test.tsx Adds focused unit coverage for core behaviors.

Comment on lines +148 to +152

const nextDuration = splitDuration(value, hideMinutes)
setHours(nextDuration.hours)
setMinutes(nextDuration.minutes)
}, [value, hideMinutes, hours, minutes])
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

The state-sync effect runs whenever hours/minutes change and always reconciles local state back to value. Because value is optional, using the component without a controlled value (i.e. value === undefined) will cause any user typing to be immediately overwritten back to empty strings. Consider making the component explicitly controlled (require value/onChange) or support uncontrolled usage by skipping reconciliation when value is undefined and only syncing local state when the controlled value actually changes (e.g. via a controllable-state helper).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch. I updated the component to avoid reconciling local state when value is undefined, so uncontrolled usage no longer resets typed input. I also added a regression test covering uncontrolled typing and normalization.

| "required"
| "readonly"
| "size"
| "className"
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

This component’s public props currently expose className via InputFieldProps. In packages/react/AGENTS.md it’s a documented convention that public components should not accept className (use a private-prop pattern instead). Consider removing className from the exported props or making it internal-only.

Suggested change
| "className"

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed. I removed className from the public props and switched the component to the private-props wrapper pattern so className stays internal-only, matching the package convention.

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

Labels

feat react Changes affect packages/react

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants