-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
rfc: "No action" / default property value standardization #23304
rfc: "No action" / default property value standardization #23304
Conversation
📊 Bundle size report🤖 This report was generated against ed3ff0780a3bd1ab263a5cd88861b6a353c3dd30 |
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 702650b:
|
Asset size changesSize Auditor did not detect a change in bundle size for any component! Baseline commit: ed3ff0780a3bd1ab263a5cd88861b6a353c3dd30 (build) |
Can you provide an example of a current component that needs this kind of modification right now @andrefcdias? I'm still not 100% sure I'm following your modifications request. The way I see the value returned from If the state value should include the value interface OptionalType {
optional?: string
}
interface NonOptionalType {
optional: string | undefined
}
const t: Required<OptionalType> = {optional: undefined} // error 🚨
const t2: Required<NonOptionalType> = {optional: undefined} // fine ✅ |
This RFC originated from addressing this issue #22855 (PR: #23254). I noted that there wasn't a standard across our components for what the default value should be for when we do nothing with said value. While in It's a fact that there's no standard default value and that quite possibly there's no string value to rule them all, by fitting all use cases. As such, JS standards seem like the appropriate approach to unify behavior and improve DX by avoiding unnecessary documentation reading. I think that your solution is good, @bsunderhus, as it addresses the problem of standardizing what value represents a no action scenario. However, that comes at the cost of forcing users to initialize a state with all props with the value interface OptionalType {
optional1?: string
optional2?: string
optional3?: string
optional4?: string
optional5?: string
}
interface NonOptionalType {
optional1: string | undefined
optional2: string | undefined
optional3: string | undefined
optional4: string | undefined
optional5: string | undefined
}
const t: OptionalType = { // fine ✅
optional3: "cool-value"
}
const t2: NonOptionalType = { // error 🚨
optional3: "cool-value"
}
const t3: WorkingNonOptionalType = { // fine ✅
optional1: undefined,
optional2: undefined,
optional3: "cool-value",
optional4: undefined,
optional5: undefined
} |
This RFC aims to achieve a standardization of the default values as, as stated in it, there's a plethora of words used and, if we can achieve a standard, the user doesn't need to check documentation. Also, the current discussions have been around the consequences of the proposal, which is definitely not a blocker for the main topic, so feel free to propose other ideas on how to address the underlying naming problem of default values to avoid the cons you mentioned. |
Can I try to summarise this RFC to two statements? (to ensure that my understanding is correct)
@andrefcdias Is it accurate? If so I think that it's a good change that we need to make. Where I agree with @behowell that we may not need changes to
Another approach to consider is something like RequiredAllowingUndefined. In this case we will still need to enumerate all properties on const state3: RequiredAllowingUndefined<Props> = { font: undefined } However I don't see obvious benefits in this approach as it will only increase bundle size. |
That is a great summary to it @layershifter, I'll be adding it to the RFC as it's much better explained and to the point. Thanks! Also, I think @bsunderhus's proposal is probably the way to go as standardizing is the main concern of the RFC. Thoughts? |
Ok, so as I understand now, the main thing to decide here is about the public API: whether we include a named value for a prop's default, or only have I think this boils down to a stylistic choice. And with all stylistic choices, both options have valid reasons for and against, and can be a source of endless debate 🙂. I still generally think it's better to leave things as they are (more reasoning below), but I understand if you disagree. I'm going to be on vacation for the next two weeks, so I won't be able to respond during that time. I'll remove my review from the PR to not block further progress. In general, I think when a prop has a union value, the API is clearer if you have names for all possible variants including the default one. That way it's more straightforward to document what happens for each variant: the documentation lists all of the possible values, and then says which one is the default. I would usually expect that We could review the "off"/"none"/etc. type values and try to standardize them, but I don't think that full alignment across all props is necessary, since they don't all mean the same thing anyways. For example, something not being focusable I'm not entirely opposed to using
This feels like the criteria is being based on an implementation detail. For what it's worth, I'd say that root: {
- fontFamily: tokens.fontFamilyBase,
// ...
},
+ base: { fontFamily: tokens.fontFamilyBase },
monospace: { fontFamily: tokens.fontFamilyMonospace },
numeric: { fontFamily: tokens.fontFamilyNumeric }, state.root.className = mergeClasses(
styles.root,
+ state.font === 'base' && styles.base,
state.font === 'monospace' && styles.monospace,
state.font === 'numeric' && styles.numeric,
// ...
); That's not to say that's a preferable way to do it, but just to illustrate that it is an implementation detail whether a given value applies styles or not. And implementation details shouldn't drive the API design. |
I feel like the point is being missed @behowell. For that specific case you mentioned "base" is currently being applied by default, but that's not the intended behavior. By default You're correct when saying that criteria will be based on implementation, but not in the specific way you mention. The rule would be:
This RFC is not attempting to change the behavior of any props whose default value is meaningful, like the default values used in tl;dr: If your prop default does nothing, even considering root defined styles, it gets no default value. |
👍 To clarify: I support that change as it has sense, but I think that RFC is too much focused on implementation details in hooks (that are unstable). I would separate these parts and focus on changes to components' props for now as all other changes could be done later. |
I've gone ahead and removed the hook changes, leaving only the standardization of the value. |
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 I'm fine with approving this now that it has removed the implementation details on hooks. Thanks for doing this!
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.
@andrefcdias FYI: I updated the link to preview.
New Behavior
This RFC aims to standardize what values we use in our components for cases where a prop value results in no action, i.e. defaults that apply no styles.
Currently, the approach we follow for all components is to use a string value like 'off', 'none' or 'default' for default values of a prop.
PREVIEW 🔍
Related Issue(s)
#23254