Skip to content

Commit

Permalink
Input: Add basic styling (#19376)
Browse files Browse the repository at this point in the history
  • Loading branch information
ecraig12345 authored Sep 2, 2021
1 parent cfddfa9 commit 2760f65
Show file tree
Hide file tree
Showing 12 changed files with 473 additions and 37 deletions.
1 change: 1 addition & 0 deletions apps/pr-deploy-site/just.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const dependencies = [
'@fluentui/react-charting',
'@fluentui/react-components',
'@fluentui/react-experiments',
'@fluentui/react-input',
'@fluentui/web-components',
'perf-test',
'theming-designer',
Expand Down
6 changes: 6 additions & 0 deletions apps/pr-deploy-site/pr-deploy-site.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ var siteInfo = [
icon: 'BarChart4',
title: 'Charting',
},
{
package: '@fluentui/react-input',
link: './react-input/storybook/index.html',
icon: 'TextField',
title: 'Input',
},
{
package: 'theming-designer',
link: './theming-designer/index.html',
Expand Down
119 changes: 119 additions & 0 deletions packages/react-input/Spec-styling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# `@fluentui/react-input`: Styling implementation notes

Input has multiple size and appearance variants. These tables were created based on the design spec to assist with initial implementation and help ensure everything is handled.

General abbreviations used:

- " = inherit from left
- ^ = inherit from above
- ^^ = inherit from 2 lines above

## Sizes

- padding and gap values are from (theoretical) `spacing.horizontal` unless otherwise specified
- bookend-related sizes are from separate bookends page (everything except L/R padding and spacing within inherits from default)
- interpretation:
- "spacing between icon before and content"/"spacing between content and icon after 1" => "spacing start/end to content"
- "spacing between icon after 1 and icon after 2" => "spacing within insideEnd" because we're not going to have two icon slots
- bookend "spacing between content and icon" => "spacing within bookend"
- omitted "focus indicator" b/c that's handled elsewhere

| Style | All |
| ------------- | ------------------- |
| v-align | vertically centered |
| border radius | medium |

| Style | medium | small | large |
| ----------------------------- | ---------------- | ------------------- | --------- |
| height | 32px | 24px | 40px |
| left/right padding | mNudge | sNudge | m |
| left/right padding in content | xxs | " | sNudge |
| bookends left/right padding | s | sNudge | m |
| content size | body1 (base.300) | caption1 (base.200) | base.400 |
| "icon" size | 20Regular | 16Regular | 24Regular |
| spacing start/end to content | xxs | " | sNudge |
| spacing within insideEnd | xs | " | " |
| spacing within bookend | xs | " | " |

### Sizes application

| Style | Slot | Notes |
| ----------------------------- | ---------------------------- | ---------------------------------------------------------------- |
| v-align | root, inputWrapper | ??? |
| height | root | ? as minHeight or height ? |
| border radius | bookends, inputWrapper, root | set where borders or shadow are defined; don't use if underlined |
| left/right padding | inputWrapper | padding |
| left/right padding in content | input | padding |
| bookends left/right padding | bookends | padding |
| content size | root, input | fontSize; doesn't inherit to input |
| "icon" size | n/a | no icons built in |
| spacing start/end to content | inputWrapper | display: flex (also to grow input), flex gap |
| spacing within insideEnd | insideEnd | display: flex, flex gap |
| spacing within bookends | bookends | display: flex, flex gap |

## Appearance colors and strokes

- italics = thick border
- interpreting "compound brand stroke 1 pressed" as compoundBrandStrokePressed
- appears that focus and keyboard focus styles are the same

| Style | All |
| ------------------------------------------ | ------------------------- |
| content | neutralForeground1 |
| content disabled | neutralForegroundDisabled |
| placeholder | neutralForeground4 |
| placeholder disabled | neutralForegroundDisabled |
| "icon" color | neutralForeground3 |
| "icon" color disabled | neutralForegroundDisabled |
| background disabled | transparentBackground |
| border disabled | neutralStrokeDisabled |
| in focus indicator (bottom border) | _compoundBrandStroke_ |
| in focus indicator (bottom border) pressed | _^Pressed_ |
| cursor disabled | not-allowed |

| Style | filledDarker | filledLighter | underline | outline |
| -------------------- | ------------------ | ------------------ | ------------------------ | -------------------- |
| shadow | shadow2 | " | none | " |
| background | neutralBackground3 | neutralBackground1 | transparentBackground | neutralBackground1 |
| border | transparentStroke | " | none | neutralStroke1 |
| border hover | ^Interactive | " | n/a | ^Hover |
| border pressed | ^ | " | n/a | ^^Pressed |
| border focused | ^ | " | n/a | n/a (neutralStroke1) |
| borderBottom | n/a | n/a | neutralStrokeAccessible | " |
| borderBottom hover | n/a | n/a | ^Hover | " |
| borderBottom pressed | n/a | n/a | _^^Pressed_ | " |
| borderBottom focused | n/a | n/a | n/a (in focus indicator) | " |

### Appearance application

| Style | Slot | Notes |
| -------------------------- | ------------------- | -------------------------------------------------------- |
| content color | input | other things have their own colors |
| placeholder color | input | `::placeholder` |
| "icon" color | insideStart/End | |
| shadow | root | encompasses bookends; requires rounding root corners |
| background | inputWrapper, input | bookends have separate background; input doesn't inherit |
| border | inputWrapper | |
| border hover | TODO inputWrapper | `:hover` |
| border pressed | TODO | |
| border focused | TODO inputWrapper | `:focus-within` |
| borderBottom | inputWrapper | |
| borderBottom hover | TODO inputWrapper | `:hover` |
| borderBottom pressed | TODO | |
| borderBottom focused | n/a | handled by focus indicator |
| in focus indicator | TODO | |
| in focus indicator pressed | TODO | |
| cursor | root, input | |

## Bookend appearance (TODO)

| Style | filled | brand | transparent |
| --------------- | ------------------ | ------------------------ | --------------------- |
| background | neutralBackground6 | brandBackground | transparentBackground |
| content (+icon) | neutralForeground2 | neutralForegroundOnBrand | neutralForeground2 |
| border | transparentStroke | none | transparentStroke |
| inner border | n/a | n/a | neutralStroke3 |

- Inner border ("border right") color is applied separately to before/after bookends.
- Others are applied in obvious way to both bookends.
- All borders are thin (1px).
7 changes: 7 additions & 0 deletions packages/react-input/bundle-size/Input.fixture.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Input } from '@fluentui/react-input';

console.log(Input);

export default {
name: 'Input',
};
14 changes: 11 additions & 3 deletions packages/react-input/etc/react-input.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ import type { ObjectShorthandProps } from '@fluentui/react-utilities';
import * as React_2 from 'react';

// @public
export const Input: React_2.ForwardRefExoticComponent<Pick<InputProps, "input" | "slot" | "style" | "title" | "inputWrapper" | "bookendBefore" | "bookendAfter" | "insideStart" | "insideEnd" | "children" | "as" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "placeholder" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "key"> & React_2.RefAttributes<HTMLElement>>;
export const Input: React_2.FunctionComponent<InputProps>;

// @public (undocumented)
export interface InputCommons {
appearance?: 'outline' | 'underline' | 'filledDarker' | 'filledLighter';
// (undocumented)
inline?: boolean;
size?: 'small' | 'medium' | 'large';
}

// @public
export interface InputProps extends ComponentProps<Partial<InputSlots>> {
export interface InputProps extends InputCommons, Omit<ComponentProps<Partial<InputSlots>>, 'children'> {
}

// @public
Expand All @@ -31,7 +39,7 @@ export type InputSlots = {
};

// @public
export interface InputState extends ComponentState<InputSlots> {
export interface InputState extends InputCommons, ComponentState<InputSlots> {
}

// @public
Expand Down
2 changes: 2 additions & 0 deletions packages/react-input/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"license": "MIT",
"scripts": {
"build": "just-scripts build",
"bundle-size": "bundle-size measure",
"clean": "just-scripts clean",
"code-style": "just-scripts code-style",
"just": "just-scripts",
Expand All @@ -22,6 +23,7 @@
"test": "jest",
"docs": "api-extractor run --config=config/api-extractor.local.json --local",
"build:local": "tsc -p . --module esnext --emitDeclarationOnly && node ../../scripts/typescript/normalize-import --output dist/react-input/src && yarn docs",
"bundle:storybook": "just-scripts storybook:build",
"storybook": "start-storybook"
},
"devDependencies": {
Expand Down
Loading

0 comments on commit 2760f65

Please sign in to comment.