-
Notifications
You must be signed in to change notification settings - Fork 2.8k
RFCish: Manual check of vNext props consistency #19775
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
Conversation
|
||
## Nit: Explicit component type declaration | ||
|
||
> Some components declare their type explicity, others do 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.
From @ecraig12345 in HackMD:
At least IMO it's strongly preferable to have explicit type declarations, and this is one of the things I'd like to write a conformance test for. (Also the & React.RefAttributes part isn't needed because it's included in ComponentProps somewhere.) It's a cleaner API from a consumer standpoint and sometimes shows up MUCH cleaner in API reports by preventing unnecessary type expansion.
It can be simplified to: export const Accordion: React.FunctionComponent<AccordionProps> = React.forwardRef((props, ref) => ...)
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.
from Guest Rodriquez in HackMD:
#19614 (comment)
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.
from Guest Weaver in HackMD:
Please use at least ForwardRefExoticComponent
|
||
## Slots and HTML attributes | ||
|
||
> Only Accordian and Menu components use ComponentProps<> with slots currently. |
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.
from @ecraig12345 in HackMD:
Maybe this should be obvious but I'm not totally clear on what you mean here, sorry. Can you give an example of what it looks like in a component that doesn't use 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.
This isn't a consistency problem per se. I think we want to make sure that the types of each of the slots make sense. As the components using the ComponentPropsCompat are converted to using ComponentProps and start having slots then we will want to check the consistency.
secondaryContent?: React.HTMLAttributes<HTMLElement>; | ||
``` | ||
|
||
## Compat and HTML attributes |
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.
from @ecraig12345 in HackMD:
This should also be addressed by the simplified prop merging issues
|
||
## Property overrides of native properties | ||
|
||
> Several components declare properties that are also declared by extending from the DOM types (e.g. React.HtmlAttributes<T>). |
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.
from @ecraig12345 in HackMD:
This is an interesting one, and a very good case for conformance testing. There are a couple sub-cases:
- Explicitly declaring (as original type) for documentation purposes => probably fine (example: people get confused if the docs for Link don't explicitly mention
href
) - Explicitly declaring as limited sub-type => TBD if this is okay. If we allow it, it should be paired with Omit on the native props.
- Accidental reuse of name for a different purpose => should come up with a different name (example: for Input I wanted to use
size
but had to rename it since that's a native input prop with different meaning)
|
||
checked, children, color, defaultChecked, disabled, href, image, name, onClick, open, ref, target, type, value | ||
|
||
> Several components use declar properties that are also HTML element names. |
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.
from @ecraig12345 in HackMD:
Are you aware of any cases where this would cause conflicts?
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 don't think it would cause a compile or runtime issue, but it could confuse users who might think it has to be set to an HTML element.
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 fce4728:
|
Asset size changesSize Auditor did not detect a change in bundle size for any component! Baseline commit: 90d9972fef1d2d76b0c28e360b05455a1a602915 (build) |
📊 Bundle size reportUnchanged fixtures
|
Perf Analysis (
|
Scenario | Render type | Master Ticks | PR Ticks | Iterations | Status |
---|---|---|---|---|---|
Panel | mount | 2439 | 1430 | 1000 | Possible regression |
All results
Scenario | Render type | Master Ticks | PR Ticks | Iterations | Status |
---|---|---|---|---|---|
Avatar | mount | 938 | 939 | 5000 | |
BaseButton | mount | 960 | 944 | 5000 | |
Breadcrumb | mount | 2768 | 2783 | 1000 | |
ButtonNext | mount | 461 | 466 | 5000 | |
Checkbox | mount | 1578 | 1614 | 5000 | |
CheckboxBase | mount | 1434 | 1341 | 5000 | |
ChoiceGroup | mount | 4934 | 4948 | 5000 | |
ComboBox | mount | 1040 | 1036 | 1000 | |
CommandBar | mount | 10955 | 10906 | 1000 | |
ContextualMenu | mount | 7210 | 6936 | 1000 | |
DefaultButton | mount | 1236 | 1243 | 5000 | |
DetailsRow | mount | 3984 | 3888 | 5000 | |
DetailsRowFast | mount | 3890 | 4116 | 5000 | |
DetailsRowNoStyles | mount | 3698 | 3775 | 5000 | |
Dialog | mount | 2568 | 2503 | 1000 | |
DocumentCardTitle | mount | 161 | 153 | 1000 | |
Dropdown | mount | 3434 | 3388 | 5000 | |
FluentProviderNext | mount | 7741 | 7779 | 5000 | |
FluentProviderWithTheme | mount | 372 | 384 | 10 | |
FluentProviderWithTheme | virtual-rerender | 100 | 101 | 10 | |
FluentProviderWithTheme | virtual-rerender-with-unmount | 510 | 512 | 10 | |
FocusTrapZone | mount | 1881 | 1916 | 5000 | |
FocusZone | mount | 1896 | 1927 | 5000 | |
IconButton | mount | 1810 | 1839 | 5000 | |
Label | mount | 353 | 345 | 5000 | |
Layer | mount | 3139 | 3104 | 5000 | |
Link | mount | 472 | 481 | 5000 | |
MakeStyles | mount | 1892 | 1875 | 50000 | |
MenuButton | mount | 1533 | 1541 | 5000 | |
MessageBar | mount | 2110 | 2143 | 5000 | |
Nav | mount | 3436 | 3426 | 1000 | |
OverflowSet | mount | 1161 | 1148 | 5000 | |
Panel | mount | 2439 | 1430 | 1000 | Possible regression |
Persona | mount | 865 | 868 | 1000 | |
Pivot | mount | 1494 | 1465 | 1000 | |
PrimaryButton | mount | 1336 | 1338 | 5000 | |
Rating | mount | 8093 | 8089 | 5000 | |
SearchBox | mount | 1374 | 1369 | 5000 | |
Shimmer | mount | 2702 | 2662 | 5000 | |
Slider | mount | 2044 | 2051 | 5000 | |
SpinButton | mount | 5262 | 5262 | 5000 | |
Spinner | mount | 452 | 446 | 5000 | |
SplitButton | mount | 3323 | 3311 | 5000 | |
Stack | mount | 522 | 532 | 5000 | |
StackWithIntrinsicChildren | mount | 1696 | 1698 | 5000 | |
StackWithTextChildren | mount | 4766 | 4763 | 5000 | |
SwatchColorPicker | mount | 10941 | 10857 | 5000 | |
Tabs | mount | 1517 | 1501 | 1000 | |
TagPicker | mount | 2780 | 2735 | 5000 | |
TeachingBubble | mount | 13825 | 14162 | 5000 | |
Text | mount | 459 | 417 | 5000 | |
TextField | mount | 1446 | 1436 | 5000 | |
ThemeProvider | mount | 1249 | 1256 | 5000 | |
ThemeProvider | virtual-rerender | 608 | 627 | 5000 | |
ThemeProvider | virtual-rerender-with-unmount | 1999 | 1967 | 5000 | |
Toggle | mount | 856 | 833 | 5000 | |
buttonNative | mount | 129 | 109 | 5000 |
Perf Analysis (@fluentui/react-northstar
)
Perf tests with no regressions
Scenario | Current PR Ticks | Baseline Ticks | Ratio |
---|---|---|---|
AttachmentMinimalPerf.default | 193 | 162 | 1.19:1 |
AlertMinimalPerf.default | 320 | 278 | 1.15:1 |
ButtonMinimalPerf.default | 195 | 178 | 1.1:1 |
RefMinimalPerf.default | 246 | 225 | 1.09:1 |
TreeWith60ListItems.default | 190 | 174 | 1.09:1 |
ImageMinimalPerf.default | 393 | 369 | 1.07:1 |
RadioGroupMinimalPerf.default | 484 | 451 | 1.07:1 |
ChatDuplicateMessagesPerf.default | 323 | 306 | 1.06:1 |
AttachmentSlotsPerf.default | 1156 | 1097 | 1.05:1 |
DividerMinimalPerf.default | 387 | 367 | 1.05:1 |
DropdownManyItemsPerf.default | 735 | 701 | 1.05:1 |
FlexMinimalPerf.default | 311 | 297 | 1.05:1 |
HeaderSlotsPerf.default | 804 | 773 | 1.04:1 |
ListWith60ListItems.default | 683 | 659 | 1.04:1 |
ProviderMinimalPerf.default | 1125 | 1081 | 1.04:1 |
CarouselMinimalPerf.default | 498 | 484 | 1.03:1 |
FormMinimalPerf.default | 421 | 408 | 1.03:1 |
LabelMinimalPerf.default | 407 | 395 | 1.03:1 |
SliderMinimalPerf.default | 1687 | 1643 | 1.03:1 |
ButtonSlotsPerf.default | 576 | 567 | 1.02:1 |
EmbedMinimalPerf.default | 4431 | 4357 | 1.02:1 |
GridMinimalPerf.default | 361 | 354 | 1.02:1 |
LayoutMinimalPerf.default | 388 | 381 | 1.02:1 |
ListNestedPerf.default | 587 | 578 | 1.02:1 |
LoaderMinimalPerf.default | 743 | 726 | 1.02:1 |
PortalMinimalPerf.default | 188 | 185 | 1.02:1 |
ReactionMinimalPerf.default | 393 | 384 | 1.02:1 |
TextMinimalPerf.default | 353 | 346 | 1.02:1 |
AnimationMinimalPerf.default | 431 | 428 | 1.01:1 |
DatepickerMinimalPerf.default | 5933 | 5873 | 1.01:1 |
HeaderMinimalPerf.default | 374 | 370 | 1.01:1 |
ItemLayoutMinimalPerf.default | 1275 | 1263 | 1.01:1 |
ListCommonPerf.default | 672 | 668 | 1.01:1 |
ListMinimalPerf.default | 547 | 543 | 1.01:1 |
MenuButtonMinimalPerf.default | 1700 | 1677 | 1.01:1 |
ProviderMergeThemesPerf.default | 1752 | 1735 | 1.01:1 |
SplitButtonMinimalPerf.default | 4280 | 4246 | 1.01:1 |
CustomToolbarPrototype.default | 4094 | 4062 | 1.01:1 |
AccordionMinimalPerf.default | 158 | 158 | 1:1 |
ButtonOverridesMissPerf.default | 1812 | 1808 | 1:1 |
ChatWithPopoverPerf.default | 404 | 402 | 1:1 |
InputMinimalPerf.default | 1379 | 1377 | 1:1 |
PopupMinimalPerf.default | 608 | 610 | 1:1 |
SegmentMinimalPerf.default | 355 | 355 | 1:1 |
TableMinimalPerf.default | 403 | 404 | 1:1 |
TreeMinimalPerf.default | 811 | 810 | 1:1 |
VideoMinimalPerf.default | 641 | 644 | 1:1 |
BoxMinimalPerf.default | 359 | 363 | 0.99:1 |
ChatMinimalPerf.default | 684 | 689 | 0.99:1 |
CheckboxMinimalPerf.default | 2858 | 2888 | 0.99:1 |
DialogMinimalPerf.default | 791 | 795 | 0.99:1 |
DropdownMinimalPerf.default | 3296 | 3318 | 0.99:1 |
TableManyItemsPerf.default | 1887 | 1911 | 0.99:1 |
ToolbarMinimalPerf.default | 935 | 945 | 0.99:1 |
TooltipMinimalPerf.default | 1031 | 1041 | 0.99:1 |
AvatarMinimalPerf.default | 200 | 204 | 0.98:1 |
CardMinimalPerf.default | 553 | 563 | 0.98:1 |
MenuMinimalPerf.default | 868 | 889 | 0.98:1 |
SkeletonMinimalPerf.default | 358 | 367 | 0.98:1 |
IconMinimalPerf.default | 604 | 617 | 0.98:1 |
StatusMinimalPerf.default | 671 | 690 | 0.97:1 |
TextAreaMinimalPerf.default | 492 | 506 | 0.97:1 |
RosterPerf.default | 1169 | 1213 | 0.96:1 |
PopoverSurfaceProps | ||
|
||
```ts | ||
extends ComponentPropsCompat, |
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.
ComponentPropsCompat
has been removed from Popover
since #19767
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.
Good to know. As expected, this document will age out quickly as beta work continues.
|
||
> Some components have mutually exclusive booleans and others use discriminated unions. | ||
> Some components define a color property that are a set of colors, others are a set semantic names. | ||
> Some naming is inconsistent (e.g. noArrow, pointing) |
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.
funnily enough, noArrow
was used both in Popover
and Tooltip
initially, I wonder what requirement resulted in the divergence @behowell ?
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.
The design for Tooltip was changed to not have an arrow by default, so I inverted the property naming so its default value would still be false.
I think I asked design to follow up about whether Popover's default should also change to not have an arrow, but I'm not sure if that happened.
AvatarProps | ||
|
||
```ts | ||
activeDisplay: 'ring' | 'shadow' | 'glow' | 'ring-shadow' | 'ring-glow'; |
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 wondering if there should be two props here: One for that lets you specify 'ring' and maybe future values and another for 'shadow' | 'glow'. Are these specific appearances or is this union trying to cover the permutations of two different things?
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.
Per chat with Levi, we should break these up if they are enumerating permutations. I'll follow up with Avatar owner to find out.
|
||
**Proposed WorkItems** | ||
|
||
- [ ] Update all vNext component props to use types and intersections. |
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.
Could you add an example of what the final result would look like in code ?
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 the best example would be a PR :)
|
||
- Avoid re-declaring a native property and redefining its type. | ||
- Avoid naming properties that conflict with native prop names. | ||
- Provide a suffix of 'slot' to properties that provide a slot. |
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 that this worth a separate RFC as it that affects all components. This a huge breaking change even for beta as there are already customers that are using v9 components.
We should clearly understand motivation, pros and cons of this proposal. This affects not only us, but also customers that will develop reusable components as they should follow similar patterns.
For example, to cons I can add bundle size/memory concern that should be validated first.
JSX props are compiled to JS objects:
<Button iconSlot={<div />} />
// ⬇⬇⬇
React.createElement(Button, { iconSlot: React.createElement('div') })
- properties of such objects cannot be mangled by Terser, this means that "iconSlot" will stay in minified JS
- (is it valid?) properties of objects in memory will be longer
So, Slot
suffix will add additional 4 bytes to every slot's usage, at least for bundle size. 4 bytes is nothing, but in terms of huge apps with thousands of components/slots usages it's something.
For example, 1k definitions for slots will result in 4000 bytes in minified code, that gives us almost 4kB for nothing ¯_(ツ)_/¯
Yes, GZIP will compress this, but browsers will still parse uncompressed code.
Pull request checklist
$ yarn change
Description of changes
This is a PR to allow conversation/comments on the vNext props consistency. It isn't intended to be checked in.
Focus areas to test
(optional)