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

Input: Add styling #19376

Merged
merged 11 commits into from
Sep 2, 2021
Merged

Input: Add styling #19376

merged 11 commits into from
Sep 2, 2021

Conversation

ecraig12345
Copy link
Member

@ecraig12345 ecraig12345 commented Aug 12, 2021

Pull request checklist

Description of changes

Initial implementation of Input styling. Prop naming is tentative subject to review.

Note that this DOES NOT handle hover styling, focus styling, or bookends.

Live demo here!

I currently have a single story with a bunch of knobs to try different states. This will be updated to separate stories later. I also added a temporary entry on the PR deploy site for Input (will be removed once it's exported from react-components).

@fabricteam
Copy link
Collaborator

fabricteam commented Aug 12, 2021

📊 Bundle size report

Package & Exports Baseline (minified/GZIP) PR Change
react-input
Input
0 B
0 B
31.636 kB
11.312 kB
🆕 New entry

🤖 This report was generated against cfddfa922c3931371abb7c0e047783e5b49b33c0

@codesandbox-ci
Copy link

codesandbox-ci bot commented Aug 12, 2021

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 b4041ae:

Sandbox Source
Fluent UI React Starter Configuration

@size-auditor
Copy link

size-auditor bot commented Aug 12, 2021

Asset size changes

Size Auditor did not detect a change in bundle size for any component!

Baseline commit: cfddfa922c3931371abb7c0e047783e5b49b33c0 (build)

@fabricteam
Copy link
Collaborator

fabricteam commented Aug 12, 2021

Perf Analysis (@fluentui/react)

No significant results to display.

All results

Scenario Render type Master Ticks PR Ticks Iterations Status
Avatar mount 970 962 5000
BaseButton mount 967 995 5000
Breadcrumb mount 2597 2571 1000
ButtonNext mount 461 466 5000
Checkbox mount 1567 1623 5000
CheckboxBase mount 1381 1372 5000
ChoiceGroup mount 5012 5069 5000
ComboBox mount 1080 1017 1000
CommandBar mount 10318 10215 1000
ContextualMenu mount 6247 6385 1000
DefaultButton mount 1196 1215 5000
DetailsRow mount 3826 4002 5000
DetailsRowFast mount 3957 3873 5000
DetailsRowNoStyles mount 3622 3680 5000
Dialog mount 2226 2194 1000
DocumentCardTitle mount 165 153 1000
Dropdown mount 3430 3376 5000
FluentProviderNext mount 7065 7095 5000
FocusTrapZone mount 1855 1824 5000
FocusZone mount 1788 1828 5000
IconButton mount 1874 1891 5000
Label mount 346 332 5000
Layer mount 1848 1876 5000
Link mount 484 469 5000
MakeStyles mount 1803 1778 50000
MenuButton mount 1556 1558 5000
MessageBar mount 2023 2031 5000
Nav mount 3501 3423 1000
OverflowSet mount 1123 1172 5000
Panel mount 2124 2114 1000
Persona mount 866 867 1000
Pivot mount 1468 1417 1000
PrimaryButton mount 1334 1380 5000
Rating mount 8352 8125 5000
SearchBox mount 1403 1413 5000
Shimmer mount 2875 2686 5000
Slider mount 2068 2033 5000
SpinButton mount 5352 5266 5000
Spinner mount 426 427 5000
SplitButton mount 3275 3251 5000
Stack mount 508 529 5000
StackWithIntrinsicChildren mount 1659 1686 5000
StackWithTextChildren mount 4971 4939 5000
SwatchColorPicker mount 10774 10736 5000
Tabs mount 1470 1476 1000
TagPicker mount 2726 2784 5000
TeachingBubble mount 11920 12052 5000
Text mount 449 440 5000
TextField mount 1458 1440 5000
ThemeProvider mount 1247 1209 5000
ThemeProvider virtual-rerender 603 587 5000
Toggle mount 850 848 5000
buttonNative mount 116 105 5000

Perf Analysis (@fluentui/react-northstar)

Perf tests with no regressions
Scenario Current PR Ticks Baseline Ticks Ratio
TreeWith60ListItems.default 200 167 1.2:1
FlexMinimalPerf.default 310 266 1.17:1
ReactionMinimalPerf.default 423 383 1.1:1
PortalMinimalPerf.default 178 163 1.09:1
ImageMinimalPerf.default 409 381 1.07:1
AttachmentMinimalPerf.default 164 155 1.06:1
LayoutMinimalPerf.default 402 378 1.06:1
MenuMinimalPerf.default 898 851 1.06:1
TextMinimalPerf.default 369 347 1.06:1
AnimationMinimalPerf.default 437 418 1.05:1
CarouselMinimalPerf.default 492 469 1.05:1
ChatMinimalPerf.default 705 669 1.05:1
ListMinimalPerf.default 562 536 1.05:1
ListNestedPerf.default 605 575 1.05:1
RefMinimalPerf.default 234 222 1.05:1
SkeletonMinimalPerf.default 385 365 1.05:1
ChatDuplicateMessagesPerf.default 315 304 1.04:1
DividerMinimalPerf.default 375 362 1.04:1
TextAreaMinimalPerf.default 538 518 1.04:1
TreeMinimalPerf.default 851 822 1.04:1
ButtonMinimalPerf.default 185 179 1.03:1
HeaderMinimalPerf.default 381 370 1.03:1
ToolbarMinimalPerf.default 1004 972 1.03:1
TooltipMinimalPerf.default 1072 1041 1.03:1
RadioGroupMinimalPerf.default 478 468 1.02:1
ChatWithPopoverPerf.default 381 376 1.01:1
DropdownManyItemsPerf.default 722 716 1.01:1
DropdownMinimalPerf.default 3107 3080 1.01:1
GridMinimalPerf.default 374 372 1.01:1
HeaderSlotsPerf.default 810 804 1.01:1
ItemLayoutMinimalPerf.default 1272 1259 1.01:1
LoaderMinimalPerf.default 718 713 1.01:1
MenuButtonMinimalPerf.default 1711 1690 1.01:1
StatusMinimalPerf.default 726 716 1.01:1
CustomToolbarPrototype.default 3945 3916 1.01:1
ButtonSlotsPerf.default 569 569 1:1
DatepickerMinimalPerf.default 5513 5497 1:1
DialogMinimalPerf.default 800 798 1:1
FormMinimalPerf.default 433 435 1:1
InputMinimalPerf.default 1291 1297 1:1
ListWith60ListItems.default 674 672 1:1
PopupMinimalPerf.default 605 603 1:1
ProviderMinimalPerf.default 1043 1042 1:1
SplitButtonMinimalPerf.default 4373 4360 1:1
TableMinimalPerf.default 424 422 1:1
VideoMinimalPerf.default 650 652 1:1
CheckboxMinimalPerf.default 2792 2812 0.99:1
EmbedMinimalPerf.default 4251 4295 0.99:1
ProviderMergeThemesPerf.default 1634 1645 0.99:1
SegmentMinimalPerf.default 359 362 0.99:1
AttachmentSlotsPerf.default 1099 1122 0.98:1
AvatarMinimalPerf.default 196 201 0.98:1
ButtonOverridesMissPerf.default 1709 1748 0.98:1
IconMinimalPerf.default 642 653 0.98:1
TableManyItemsPerf.default 1989 2026 0.98:1
LabelMinimalPerf.default 395 407 0.97:1
RosterPerf.default 1261 1302 0.97:1
SliderMinimalPerf.default 1622 1686 0.96:1
AlertMinimalPerf.default 279 295 0.95:1
ListCommonPerf.default 652 692 0.94:1
CardMinimalPerf.default 574 617 0.93:1
BoxMinimalPerf.default 342 375 0.91:1
AccordionMinimalPerf.default 150 167 0.9:1

export const Input: React_2.FunctionComponent<InputProps>;

// @public (undocumented)
export interface InputCommons {
Copy link
Member

@GeoffCoxMSFT GeoffCoxMSFT Aug 31, 2021

Choose a reason for hiding this comment

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

Nit: InputCommonProps? or CommonInputProps?

Copy link
Member Author

Choose a reason for hiding this comment

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

I was copying the ___Commons convention from a few of the other converged components, for things shared between props and state. So I'd probably prefer to keep it as-is, but I don't feel super strongly about it.

/**
* Input Props
*/
export interface InputProps extends ComponentProps<Partial<InputSlots>> {}
Copy link
Member

Choose a reason for hiding this comment

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

Question - when moving to React hooks, many teams choose to move from interface to type declarations for their props and use type intersections over extends. Are interfaces giving us something that types would not? When I see interfaces I always think a class will implement it.

Copy link
Member Author

Choose a reason for hiding this comment

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

IIRC we discussed this but didn't come to a solid conclusion about which convention we wanted (and the discussion apparently happened before we started documenting things in RFCs). There may be some specific reason that type is commonly used for slots, but I can't remember offhand. @layershifter do you remember?

Copy link
Member

@layershifter layershifter Sep 1, 2021

Choose a reason for hiding this comment

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

There may be some specific reason that type is commonly used for slots, but I can't remember offhand. @layershifter do you remember?

When TS emits type declarations sometimes it inlines type declarations (microsoft/TypeScript#37151), so in general interfaces are preferred for in case.

We have seen extreme cases where this duplication has inflated declaration files from 7KB to 700KB. That’s quite a lot of redundant code to download and parse.

Through experimentation, we discovered potential techniques to prevent inlining of type declarations, such as:

  • prefer interface instead of type (interfaces are not inlined)
  • If an interface needed by a declaration is not exported, tsc will refuse to inline the type and will generate a clear error (e.g., TS4023: Exported variable has or is using name from external module but cannot be named.)

https://www.techatbloomberg.com/blog/10-insights-adopting-typescript-at-scale/

Copy link
Member Author

Choose a reason for hiding this comment

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

Interesting, thanks! Incidentally this diff (the old version) shows an example of expanded types. 😬 https://github.com/microsoft/fluentui/pull/19376/files#diff-805da48a70295edd847bed2a0dda92910c21f9f0185fa238bc342d167ae4407b

packages/react-input/Spec.md Outdated Show resolved Hide resolved
packages/react-input/Spec.md Outdated Show resolved Hide resolved
packages/react-input/Spec.md Outdated Show resolved Hide resolved
import { getNativeElementProps, useId } from '@fluentui/react-utilities';
import { InputProps } from './Input.types';
import { ArgTypes } from '@storybook/react';
// prevent terrible reload times by using deep imports :(
Copy link
Member

Choose a reason for hiding this comment

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

😢

@@ -2,12 +2,16 @@

exports[`Input renders a default state 1`] = `
<div>
<div
<span
Copy link
Member

Choose a reason for hiding this comment

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

Is it expected to have spans there? Why not divs?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's intentional (there's a comment about this in renderInput). If the input is inline within a p there will be nesting errors if I use div.

In a previous version of the implementation I used div by default and span if inline was true, but someone suggested just using span always since it (probably?) doesn't make much practical difference (all the elements either have display explicitly set, or are within a flex layout). I'm open to suggestions here though, and could go back to that if there's some reason it would be better.

packages/react-input/src/components/Input/useInput.ts Outdated Show resolved Hide resolved
m: '12px',
};
const contentSizes = {
// TODO(sharing) shouldn't these be in the theme?
Copy link
Member

Choose a reason for hiding this comment

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

Is it the same as react-text/src/typographyStyles/typographyStyles.ts? Should we reuse typographyStyles?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's similar but doesn't quite cover all the cases--the design for Input specifies large as using 400 size but I'm pretty sure it still uses regular font weight. Though it's possible that was an oversight. (Incidentally...WHY did we have to use numeric size names that look like font weights...?? I know this is more of a complaint for design and probably too late. 😞)

Copy link
Member Author

Choose a reason for hiding this comment

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

Also the individual typography styles actually aren't exported at the moment. Should we change that (@andrefcdias)? In this case it's not feasible/desirable to use the full text components like Body. (Either way, since it's a change in a separate package I think I'll leave this as-is for this PR.)

@@ -7,7 +7,7 @@ import type { InputProps } from './Input.types';
/**
* Input component
*/
export const Input = React.forwardRef<HTMLElement, InputProps>((props, ref) => {
export const Input: React.FunctionComponent<InputProps> = React.forwardRef((props, ref) => {
Copy link
Member

Choose a reason for hiding this comment

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

I don't think that this typing is correct as React.FunctionComponent does not have ref on it's interface:

Type '{ foo: string; ref: RefObject<unknown>; }' is not assignable to type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.
  Property 'ref' does not exist on type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.

TypeScript playground

Copy link
Member Author

Choose a reason for hiding this comment

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

InputProps has ref through inheritance. I strongly prefer an explicit type for the component here because it makes the public API cleaner.

Copy link
Contributor

@smhigley smhigley left a comment

Choose a reason for hiding this comment

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

Just one small change for placeholder styles, otherwise looks good to me!

</div>
<Input {...props} insideStart={<SearchIcon />} insideEnd={<DismissIcon />} />
Copy link
Contributor

Choose a reason for hiding this comment

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

Not necessarily something to change now and in this PR, but in the future I think all our storybook examples should be accessible by default (i.e. have a visible label and no placeholder), with potentially one example of less-accessible variations like not having a visible label.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup I plan to follow up on this when I make a more finished version of the stories

@ecraig12345
Copy link
Member Author

Going to merge this once the build passes and follow up on open discussions in later PRs.

@ecraig12345 ecraig12345 merged commit 2760f65 into microsoft:master Sep 2, 2021
@ecraig12345 ecraig12345 deleted the input-styling branch September 2, 2021 22:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants