-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c287807
commit 51f1140
Showing
10 changed files
with
422 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# BaseField | ||
|
||
<div class="callout callout-alert"> | ||
This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. | ||
</div> | ||
|
||
`BaseField` is an internal (i.e., not exported in the `index.js`) primitive component used for building more complex fields like `TextField`. It provides error handling and focus styles for field components. It does _not_ handle layout of the component aside from wrapping the field in a `Flex` wrapper. | ||
|
||
## Usage | ||
|
||
`BaseField` is primarily used as a hook rather than a component: | ||
|
||
```js | ||
function useExampleField( props ) { | ||
const { | ||
as = 'input', | ||
...baseProps, | ||
} = useBaseField( props ); | ||
|
||
const inputProps = { | ||
as, | ||
// more cool stuff here | ||
} | ||
|
||
return { inputProps, ...baseProps }; | ||
} | ||
|
||
function ExampleField( props, forwardRef ) { | ||
const { | ||
preFix, | ||
affix, | ||
disabled, | ||
inputProps, | ||
...baseProps | ||
} = useExampleField( props ); | ||
|
||
return ( | ||
<View { ...baseProps } disabled={ disabled }> | ||
{preFix} | ||
<View | ||
autocomplete="off" | ||
{ ...inputProps } | ||
disabled={ disabled } | ||
/> | ||
{affix} | ||
</View> | ||
); | ||
} | ||
``` | ||
|
||
## Props | ||
|
||
### `error`: `boolean` | ||
|
||
Renders an error style around the component. | ||
|
||
### `disabled`: `boolean` | ||
|
||
Whether the field is disabled. | ||
|
||
### `isClickable`: `boolean` | ||
|
||
Renders a `cursor: pointer` on hover; | ||
|
||
### `isFocused`: `boolean` | ||
|
||
Renders focus styles around the component. | ||
|
||
### `isInline`: `boolean` | ||
|
||
Renders a component that can be inlined in some text. | ||
|
||
### `isSubtle`: `boolean` | ||
|
||
Renders a subtle variant of the component. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import { createComponent } from '../ui/utils'; | ||
import { useBaseField } from './hook'; | ||
|
||
/** | ||
* `BaseField` is a primitive component used to create form element components (e.g. `TextInput`). | ||
*/ | ||
export default createComponent( { | ||
as: 'div', | ||
useHook: useBaseField, | ||
name: 'BaseField', | ||
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { cx } from 'emotion'; | ||
|
||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useMemo } from '@wordpress/element'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { useContextSystem } from '../ui/context'; | ||
import { useControlGroupContext } from '../ui/control-group'; | ||
import { useFlex } from '../flex'; | ||
import * as styles from './styles'; | ||
|
||
/** | ||
* @typedef OwnProps | ||
* @property {boolean} [error=false] Renders an error. | ||
* @property {boolean} [disabled] Whether the field is disabled. | ||
* @property {boolean} [isClickable=false] Renders a `cursor: pointer` on hover. | ||
* @property {boolean} [isFocused=false] Renders focus styles. | ||
* @property {boolean} [isInline=false] Renders as an inline element (layout). | ||
* @property {boolean} [isSubtle=false] Renders a subtle variant. | ||
*/ | ||
|
||
/** @typedef {import('../Flex/useFlex').FlexProps & OwnProps} Props */ | ||
|
||
/** | ||
* @param {import('@wp-g2/create-styles').ViewOwnProps<Props, 'div'>} props | ||
*/ | ||
export function useBaseField( props ) { | ||
const { | ||
className, | ||
error = false, | ||
isClickable = false, | ||
isFocused = false, | ||
isInline = false, | ||
isSubtle = false, | ||
// eslint-disable-next-line no-unused-vars | ||
defaultValue, // extract this because useFlex doesn't accept it | ||
...flexProps | ||
} = useContextSystem( props, 'BaseField' ); | ||
|
||
const { styles: controlGroupStyles } = useControlGroupContext(); | ||
|
||
const classes = useMemo( | ||
() => | ||
cx( | ||
styles.BaseField, | ||
controlGroupStyles, | ||
isClickable && styles.clickable, | ||
isFocused && styles.focus, | ||
isSubtle && styles.subtle, | ||
error && styles.error, | ||
error && isFocused && styles.errorFocus, | ||
isInline && styles.inline, | ||
className | ||
), | ||
[ | ||
className, | ||
controlGroupStyles, | ||
error, | ||
isInline, | ||
isClickable, | ||
isFocused, | ||
isSubtle, | ||
] | ||
); | ||
|
||
return useFlex( { ...flexProps, className: classes } ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { default as BaseField } from './component'; | ||
|
||
export { useBaseField } from './hook'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { css } from 'emotion'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { CONFIG, COLORS, reduceMotion } from '../utils'; | ||
import { safariOnly } from '../utils/browsers'; | ||
|
||
export const BaseField = css` | ||
background: ${ CONFIG.controlBackgroundColor }; | ||
border-radius: ${ CONFIG.controlBorderRadius }; | ||
border: 1px solid; | ||
border-color: ${ CONFIG.controlBorderColor }; | ||
box-shadow: ${ CONFIG.controlBoxShadow }; | ||
display: flex; | ||
flex: 1; | ||
font-size: ${ CONFIG.fontSize }; | ||
outline: none; | ||
padding: 0 8px; | ||
position: relative; | ||
transition: border-color ${ CONFIG.transitionDurationFastest } ease; | ||
${ reduceMotion( 'transition' ) } | ||
width: 100%; | ||
&[disabled] { | ||
opacity: 0.6; | ||
} | ||
&:hover { | ||
border-color: ${ CONFIG.controlBorderColorHover }; | ||
} | ||
&:focus, | ||
&[data-focused='true'] { | ||
border-color: ${ COLORS.admin }; | ||
box-shadow: ${ CONFIG.controlBoxShadowFocus }; | ||
} | ||
`; | ||
|
||
export const clickable = css` | ||
cursor: pointer; | ||
`; | ||
|
||
export const focus = css` | ||
border-color: ${ COLORS.admin }; | ||
box-shadow: ${ CONFIG.controlBoxShadowFocus }; | ||
&:hover { | ||
border-color: ${ COLORS.admin }; | ||
} | ||
`; | ||
|
||
export const subtle = css` | ||
background-color: transparent; | ||
&:hover, | ||
&:active, | ||
&:focus, | ||
&[data-focused='true'] { | ||
background: ${ CONFIG.controlBackgroundColor }; | ||
} | ||
`; | ||
|
||
export const error = css` | ||
border-color: ${ CONFIG.controlDestructiveBorderColor }; | ||
&:hover, | ||
&:active { | ||
border-color: ${ CONFIG.controlDestructiveBorderColor }; | ||
} | ||
&:focus, | ||
&[data-focused='true'] { | ||
border-color: ${ CONFIG.controlDestructiveBorderColor }; | ||
box-shadow: 0 0 0, 0.5px, ${ CONFIG.controlDestructiveBorderColor }; | ||
} | ||
`; | ||
|
||
export const errorFocus = css` | ||
border-color: ${ CONFIG.controlDestructiveBorderColor }; | ||
box-shadow: 0 0 0, 0.5px, ${ CONFIG.controlDestructiveBorderColor }; | ||
&:hover { | ||
border-color: ${ CONFIG.controlDestructiveBorderColor }; | ||
} | ||
`; | ||
|
||
export const inline = css` | ||
display: inline-flex; | ||
vertical-align: baseline; | ||
width: auto; | ||
${ safariOnly` | ||
vertical-align: middle; | ||
` } | ||
`; |
77 changes: 77 additions & 0 deletions
77
packages/components/src/base-field/test/__snapshots__/index.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`props should render correctly 1`] = ` | ||
.emotion-0 { | ||
display: -webkit-box; | ||
display: -webkit-flex; | ||
display: -ms-flexbox; | ||
display: flex; | ||
-webkit-align-items: center; | ||
-webkit-box-align: center; | ||
-ms-flex-align: center; | ||
align-items: center; | ||
-webkit-flex-direction: row; | ||
-ms-flex-direction: row; | ||
flex-direction: row; | ||
-webkit-box-pack: justify; | ||
-webkit-justify-content: space-between; | ||
-ms-flex-pack: justify; | ||
justify-content: space-between; | ||
width: 100%; | ||
background: #fff; | ||
border-radius: 2px; | ||
border: 1px solid; | ||
border-color: #757575; | ||
box-shadow: transparent; | ||
display: -webkit-box; | ||
display: -webkit-flex; | ||
display: -ms-flexbox; | ||
display: flex; | ||
-webkit-flex: 1; | ||
-ms-flex: 1; | ||
flex: 1; | ||
font-size: 13px; | ||
outline: none; | ||
padding: 0 8px; | ||
position: relative; | ||
-webkit-transition: border-color 100ms ease; | ||
transition: border-color 100ms ease; | ||
width: 100%; | ||
} | ||
.emotion-0 > * + *:not(marquee) { | ||
margin-left: calc(4px * 2); | ||
} | ||
.emotion-0 > * { | ||
min-width: 0; | ||
} | ||
@media ( prefers-reduced-motion:reduce ) { | ||
.emotion-0 { | ||
-webkit-transition-duration: 0ms; | ||
transition-duration: 0ms; | ||
} | ||
} | ||
.emotion-0[disabled] { | ||
opacity: 0.6; | ||
} | ||
.emotion-0:hover { | ||
border-color: #757575; | ||
} | ||
.emotion-0:focus, | ||
.emotion-0[data-focused='true'] { | ||
border-color: theme:var( --wp-admin-theme-color,#00669b); | ||
theme-dark10: var( --wp-admin-theme-color-darker-10,#007cba); | ||
box-shadow: 0 0 0,0.5px,[object Object]; | ||
} | ||
<div | ||
class="components-flex components-base-field emotion-0 emotion-1 emotion-2" | ||
data-wp-c16t="true" | ||
data-wp-component="BaseField" | ||
/> | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { render } from '@testing-library/react'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { BaseField } from '../index'; | ||
|
||
describe( 'props', () => { | ||
test( 'should render correctly', () => { | ||
const { container } = render( <BaseField /> ); | ||
expect( container.firstChild ).toMatchSnapshot(); | ||
} ); | ||
} ); |
Oops, something went wrong.