-
-
Notifications
You must be signed in to change notification settings - Fork 47
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
[NumberField] Component and Hook #186
Conversation
6992248
to
023fe9d
Compare
585d357
to
c0f561a
Compare
Rebased on HEAD. It seems to fix Circle CI, I don't know why. |
71b21fe
to
4aa63f6
Compare
It might be subjective, but the scrubber feels too sensitive. Changing value on every pixel of pointer movement may be too fast. Figma seems to update the value every two pixels (or perhaps they take pixel density into consideration?). We could make this configurable by adding the |
@michaldudak yeah you're right, previously it was 2px but I must have changed something that reverted it back to 1px. Will fix. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested on Chrome, Safari, Safari iOS, and Chrome iOS. Feedback/thoughts so far:
ScrubAreaCursor
is missing from the docs anatomy section.- Seems like we don't have the teleport threshold thingy prop on
ScrubAreaCursor
yet? Are you planning to add that? - Should scrubbing start from where the pointer was when scrubbing began, or when the pointer direction changes during scrubbing? Idk how to explain wtf I'm on about here 🤣 It's noticeable when
min
andmax
are set. If you setmax
, then scrub way beyond themax
value, you need to scrub all the way back down before the value decrements. Perhaps it could begin decrementing immediately when the pointer direction changes? - The
largeStep
logic seems odd to me. I expected it to just increment/decrement the value by whatever thelargeStep
value is? smallStep
doesn't seem to be working for me. Nothing happens when I holdcmd
and then increment/decrement.
Still to test: formatting options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really good 👌
value, | ||
onChange, | ||
allowWheelScrub, | ||
render: renderProp, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
render: renderProp, | |
render = defaultRender, |
I can't see renderProp
being used anywhere else. I see this patterns used everywhere. If there isn't a valid reason I would propose going with this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We went with the ??
fallback because it avoids requiring a default when generating docs which is too difficult with the generic BaseUiCommonComponentProps
due to the polymorphic components.
} = props; | ||
const render = renderProp ?? defaultRender; | ||
|
||
const numberField = useNumberField(props); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const numberField = useNumberField(props); | |
const numberField = useNumberField(props); |
We usually invoke the hooks with the ownerState
, this makes sure that the default values for the props are also included. It may not make a difference in this component, but if we change the default value of some prop, it may break unexpectedly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, ownerState
is a partially derived version of useNumberField
's return value, so it can't be called with it. The default values of the hook just match the component.
@@ -0,0 +1 @@ | |||
export { default as clamp } from '@mui/utils/clamp'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do the utils changes in a separate PR? It will make the review easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think at this stage, it's easier if the utils are kept in this PR. To keep it working before rebasing, I'd have to import directly from @mui/utils
temporarily, right? I can remember to do utils separately for next time.
// We need to hide the input value during SSR to avoid a potential mismatch between the server | ||
// rendered value and the client rendered value when their locales differ. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Flash from server's formatting to the user's one. If the server matches the client, there's no flash. This indeed may be better.
👍
99d4bb0
to
7866e25
Compare
Decisions from a recent call:
|
Can you elaborate more here? The We might be missing props similar to |
Ok yeah my first thought was
No this was just a note I took from our call, not sure what you meant when you were talking about formatting, internationalisation, and functions. I remember you saying some piece of work around internationalisation is still incomplete? |
Alright, will change 👍
Yeah there were some bugs remaining with the parsing and validation functions, but I should have fixed most of them in the recent commits. However these are only internal and not part of any API. |
return ( | ||
<NumberField value={value} onChange={setValue}> | ||
<NumberField.Group> | ||
<NumberField.Decrement>−</NumberField.Decrement> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious, why not -
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
&minus is wider and looks more in proportion with +
😅
import { mergeReactProps } from '../utils/mergeReactProps'; | ||
|
||
/** | ||
* @ignore - internal hook. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we want to expose it like the other hooks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No as it's just an internal hook to place some of the functionality in its own hook
Bifurcate tests Docs stylelint Attempt test fix Ignore perf test in JSDOM Use skip Docs Format Update docs Relocate ScrubArea logic Memo return value Unit tests for parsing and formatting Skip test in browser Tests Relocate pointerDownEvent Remove floating point errors Docs Update allowed chars Bug fixes and feedback Remove autoFocus destructure Remove clamp requirement logic Allow currency symbols Move context menu handler Avoid calling handlers while disabled Unsubscribe from visualViewport Add description to useNumberField Docs Use mergeReactProps Use altKey for smallStep Fix cursor rendering
75cf7b3
to
c8cc076
Compare
c618708
to
1c231b4
Compare
Closes #185
Closes #224
Preview: https://deploy-preview-186--base-ui.netlify.app/base-ui/react-number-field/
TODO:
teleportDistance
(or other name) prop to loop closer to the input compared to the viewport.displayName
to Contexts.Intl.NumberFormat
usage.inputMode="numeric"
prop for iOS when appropriate, which doesn't show a negative sign in the software keyboard, it must be "text".inputMode
is "text".ScrubArea
logic into theuseNumberField
hook, or possibly a separate hook. Depends how granular the tree-shaking could possibly be for this functionality.