Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DateTime: Create TimeInput component and integrate into TimePicker #60613

Open
wants to merge 15 commits into
base: trunk
Choose a base branch
from

Conversation

bogiii
Copy link

@bogiii bogiii commented Apr 9, 2024

What?

  • Introduces a simple TimeInput component
  • Integrates the TimeInput into TimePicker component

Why?

Before these changes, there was no option to use the simple time input component.

Before After
Screenshot 2024-04-11 at 12 11 18 Screenshot 2024-04-11 at 12 11 29

How?

Here are more details: #52734

Testing Instructions

  • Go to TimeInput component: http://localhost:50240/?path=/docs/components-timeinput--docs
  • Play with applying different combination of arguments

--

  • Go to TimePicker component: http://localhost:50240/?path=/docs/components-timepicker--docs
  • Check if everything work on same way as before this changes

Unit tests: Good old unit tests found a bug, which is resolved. ✅

Testing Instructions for Keyboard

Screenshots or screencast

Screen Capture on 2024-04-11 at 12-42-03

@github-actions github-actions bot added the First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository label Apr 9, 2024
Copy link

github-actions bot commented Apr 9, 2024

👋 Thanks for your first Pull Request and for helping build the future of Gutenberg and WordPress, @bogiii! In case you missed it, we'd love to have you join us in our Slack community.

If you want to learn more about WordPress development in general, check out the Core Handbook full of helpful information.

@bogiii bogiii changed the title DateTime: Add TimeInput component WIP: DateTime: Add TimeInput component Apr 9, 2024
@bogiii bogiii changed the title WIP: DateTime: Add TimeInput component DateTime: Create TimeInput component and integrate into TimePicker Apr 11, 2024
@bogiii bogiii marked this pull request as ready for review April 11, 2024 21:31
@bogiii bogiii requested a review from ajitbohra as a code owner April 11, 2024 21:31
Copy link

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @bogiii.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Unlinked contributors: bogiii.


To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link
Member

@mirka mirka left a comment

Choose a reason for hiding this comment

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

Thank you for your patience here! Nice refactor, and thank you for adding tests. I did a first-pass review and wrote some comments.

Have you looked into the e2e failures? They seem relevant.

Comment on lines +183 to +184
hours={ Number( hours ) }
minutes={ Number( minutes ) }
Copy link
Member

Choose a reason for hiding this comment

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

Any reason why this is split into two props?

I think it would be more straightforward if it was one value prop that matched the first argument of the onChange callback. Most components in this package follow that pattern.

We don't need to worry about re-renders because this is tiny, and most consumers won't stabilize their onChange functions anyway.

docs: { canvas: { sourceState: 'shown' } },
},
args: {
is12Hour: true,
Copy link
Member

Choose a reason for hiding this comment

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

We generally want the default story to reflect the component defaults, so let's remove this one. We can show that state in another story if you want to highlight it (no strong opinion).

is12Hour,
hours: entryHours = new Date().getHours(),
minutes: entryMinutes = new Date().getMinutes(),
minutesStep = 1,
Copy link
Member

@mirka mirka Apr 26, 2024

Choose a reason for hiding this comment

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

Is this step prop a strong requirement? If consumers want to override props on the underlying elements, it can be unsustainable to keep adding ad hoc props to the root like this.

I think it's something to triage/address as a separate issue.

<TimeInput hours={ 0 } minutes={ 0 } onChange={ onChangeSpy } />
);

const hoursInput = screen.getByLabelText( 'Hours' );
Copy link
Member

Choose a reason for hiding this comment

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

We generally want to use *ByRole() queries wherever possible, since it can also surface accessibility issues.

const amButton = screen.getByText( 'AM' );
const pmButton = screen.getByText( 'PM' );

expect( amButton ).toHaveClass( 'is-primary' );
Copy link
Member

Choose a reason for hiding this comment

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

We generally want to assert these states through the accessibility tree rather than through styles. And through this test I noticed that this switcher is not screen reader accessible, so I posted an issue here #61163.

This is a pre-existing issue so we don't have to fix it in this PR, but let's maybe add a TODO comment here to flag that it should be fixed.

Comment on lines +24 to +26
onChange: ( obj ) => {
action( 'onChange' )( obj );
},
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
onChange: ( obj ) => {
action( 'onChange' )( obj );
},
onChange: action( 'onChange' ),

Equivalent?

Comment on lines +15 to +17
argTypes: {
onChange: { action: 'onChange', control: { type: null } },
},
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
argTypes: {
onChange: { action: 'onChange', control: { type: null } },
},
argTypes: {
onChange: { action: 'onChange', control: { type: null } },
value: { control: { type: null } },
},

We've usually been null-ing out the Storybook control for the value prop. In this case I think it's especially good because when the value control can take arbitrary user-generated values, any out-of-bounds value (let's say 100) can be rendered directly into the input field for the component, and that's weird 😅 And it's overkill to add value-clamping logic before it hits the input's own min/max validation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository [Package] Components /packages/components [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants