feat(time): add Time atom component#259
Conversation
egdev6
left a comment
There was a problem hiding this comment.
Thanks for the Time atom work. I’d request changes before merge because a few issues currently break the component contract and user-facing behavior.
Blocking items to fix:
Timeis not exported fromsrc/index.ts, so package consumers cannot import it from@stack-and-flow/design-system.handleContainerClickrefocuses Hours for any click inside the wrapper, so clicking Minutes/Seconds/AM-PM does not keep focus on the clicked segment.- 12h mode is not safe yet: the AM/PM segment is treated as free text / numeric stepping and can become invalid values like
1instead ofPM. onChangecan emit stale or unclamped values because the callback uses the raw value/old segment snapshot instead of the normalized next state.- Storybook docs need to follow the repo convention: JSDoc above
const metaand each story, notparameters.docs.description.component.
Please add focused regression tests for segment click focus, AM/PM keyboard/input behavior, and normalized onChange payloads. Also update the PR evidence once the component audit and visual review are addressed.
|
@FranRubioDev le puedes pedir a la IA que revise los comentario sobre tu rama |
Segment clicks no longer refocus Hours, AM/PM now toggles consistently via keyboard/steppers instead of relying on broken numeric parsing, and onChange emits the same clamped state that gets applied instead of a stale/unclamped snapshot.
Añade la story WithoutLabel para mostrar el componente Time sin etiqueta visible, útil cuando el contexto ya indica el propósito del campo.
egdev6
left a comment
There was a problem hiding this comment.
Thanks for the follow-up fixes. This is closer, but I still need to request changes because there are a few accessibility and behavior issues that block the Time atom contract.
Blocking items:
src/components/atoms/time/types.ts:8,types.ts:51,types.ts:79,Time.tsx:89-96: focus visibility still usesoutline-noneplus decorativeshadow-glow-*. Please use the sharedfocus-visible:focus-ring/ wrapper focus-ring pattern instead. Keyboard focus cannot depend on glow styling.src/components/atoms/time/useTime.ts:148-163,Time.tsx:76-82: 12h mode defines the hour minimum as1, but typed input can still accept00, and ARIA always exposesaria-valuemin={0}. Please derive min/max from the same segment rules, clamp lower bounds, and add boundary tests for00,0,12,23,59, and60.src/components/atoms/time/Time.tsx:76-87: AM/PM is rendered asrole="spinbutton"without a valid numeric value model oraria-valuetext. Please either model it with an appropriate non-spinbutton pattern, or provide valid spinbutton semantics plusaria-valuetext="AM|PM".
Also worth fixing in the same pass:
Time.tsx:118: the label points to${id}-hour, but the hour input does not render that id, so clicking the label will not focus the field.Time.tsx:182andindex.ts:1: this should follow the repo named export pattern (export const Time,export { Time } from './Time').Time.stories.tsx:5-28: Storybook docs should use the required## DescriptionJSDoc structure and explain why each story exists.Time.test.tsx:189-191: avoid asserting internal Tailwind classes likew-full; assert observable behavior or public API effects instead.
CI is green, but these are contract/accessibility issues rather than pipeline failures. Once the focus ring, 12h boundary handling, and AM/PM semantics are corrected, this should be much easier to approve.
|
Thanks for the latest fixes. This is much closer, but I still would not approve it yet. Remaining blockers I found on the current head (
Also, the prior note about avoiding internal Tailwind assertions is still open: CI being green is good, but these are component contract and accessibility boundary issues, so they still need a code fix. |
There was a problem hiding this comment.
Pull request overview
Adds a new Time atom to the Stack-and-Flow Design System: a segmented time input (HH:MM[:SS] + optional AM/PM) with optional steppers, optional clock icon, label + hint support, and an exported public API surface.
Changes:
- Introduces the
Timepresentational component anduseTimehook to handle segment state, focus, and keyboard interactions. - Adds CVA variants + prop/types definitions for sizing, variants, and hint/status styling.
- Adds a full Storybook story set and a comprehensive Vitest + Testing Library test suite; exports
Timefrom the package entrypoint.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/index.ts |
Re-exports Time from the root package API. |
src/components/atoms/time/types.ts |
Defines CVA variants, prop/types, and hint/segment types for Time. |
src/components/atoms/time/useTime.ts |
Implements all time-segment logic: parsing/clamping, focus management, keyboard controls, and stepper behavior. |
src/components/atoms/time/Time.tsx |
Renders the segmented inputs, label/hint UI, optional clock adornment, and optional steppers. |
src/components/atoms/time/Time.stories.tsx |
Adds Storybook coverage for variants, states, and configurations. |
src/components/atoms/time/Time.test.tsx |
Adds hook + component test coverage for behavior, ARIA attributes, and keyboard interactions. |
src/components/atoms/time/index.ts |
Public exports for the component and its types. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
Adds the
Timeatom component — a segmented time input supporting 12/24h, minute/second granularity, steppers, clock icon, and floating label.Closes #37
Review scope
src/components/atoms/time/Type of change
Workflow gates
Closes #NNNor maintainer approved an exception.status:approvedbefore implementation starts.In progress, branch/worktree recorded.<type>(<optional scope>): <description>..playwright-mcp,page-*.png,page-*.jpeg,*.md.playwright-output.Component evidence (required for component changes)
types.ts,use*.ts,Component.tsx,Component.test.tsx,Component.stories.tsx,index.ts.types.ts; JSX component has no state, CVA calls, or business logic.@defaultJSDoc intypes.ts(node scripts/verify-prop-default-docs.mjs).theme.css; no hardcoded colors or arbitrary color utilities.Accessibility evidence
Changes
src/components/atoms/time/types.ts@defaulttagssrc/components/atoms/time/useTime.tssrc/components/atoms/time/Time.tsxsrc/components/atoms/time/Time.stories.tsxsrc/components/atoms/time/Time.test.tsxsrc/components/atoms/time/index.tsValidation evidence
pnpm exec tsc --noEmit— passes