* Style Search component for 5.3.

* Reset native select control styles.

* Fix styling of selected radio options.

* Fix bottom margin on select inputs in filters and pagination.

* Update DropdownButton styles for WP 5.3.

* Style DropdownButton arrow as a chevron.

* Fix tooltip arrow styling.

* Style TextControlWithAffixes for WP 5.3.

* Flatten pagination button style.

* Use SelectControl for StoreAlert snooze action.

* Remove 3D look and use chevron on SplitButton.

* Add changelog entry.

* Fix stylelint issues.

* Update test snapshots.

* Add TextControlWithAffixes disabled prop to documentation and proptypes.

* Use WP checkboxes in ReportTable columns.

* Fix TableCard header background colors.

* Add padding to EllipsisMenu toggle controls.

* Remove version-specific styles.

We require WP 5.3 as a minimum now.
This commit is contained in:
Jeff Stieler 2019-12-13 12:35:29 -05:00 committed by GitHub
parent 9a4369d984
commit 6a826600c2
19 changed files with 222 additions and 126 deletions

View File

@ -2,7 +2,7 @@
/**
* External dependencies
*/
import { IconButton } from '@wordpress/components';
import { CheckboxControl, IconButton } from '@wordpress/components';
import { applyFilters } from '@wordpress/hooks';
import { Component, createRef, Fragment } from '@wordpress/element';
import { compose } from '@wordpress/compose';
@ -231,22 +231,16 @@ class ReportTable extends Component {
this.trackTableSearch();
}
selectAllRows( event ) {
selectAllRows( checked ) {
const { ids } = this.props;
if ( event.target.checked ) {
this.setState( {
selectedRows: ids,
} );
} else {
this.setState( {
selectedRows: [],
} );
}
this.setState( {
selectedRows: checked ? ids : [],
} );
}
selectRow( i, event ) {
selectRow( i, checked ) {
const { ids } = this.props;
if ( event.target.checked ) {
if ( checked ) {
this.setState( ( { selectedRows } ) => ( {
selectedRows: uniq( [ ids[ i ], ...selectedRows ] ),
} ) );
@ -265,9 +259,7 @@ class ReportTable extends Component {
const { selectedRows } = this.state;
const isChecked = -1 !== selectedRows.indexOf( ids[ i ] );
return {
display: (
<input type="checkbox" onChange={ partial( this.selectRow, i ) } checked={ isChecked } />
),
display: <CheckboxControl onChange={ partial( this.selectRow, i ) } checked={ isChecked } />,
value: false,
};
}
@ -281,8 +273,7 @@ class ReportTable extends Component {
cellClassName: 'is-checkbox-column',
key: 'compare',
label: (
<input
type="checkbox"
<CheckboxControl
onChange={ this.selectAllRows }
aria-label={ __( 'Select All' ) }
checked={ isAllChecked }

View File

@ -4,7 +4,7 @@
*/
import { __ } from '@wordpress/i18n';
import { Component, Fragment } from '@wordpress/element';
import { IconButton, Button, Dashicon, Dropdown, NavigableMenu } from '@wordpress/components';
import { IconButton, Button, Dashicon, SelectControl } from '@wordpress/components';
import classnames from 'classnames';
import interpolateComponents from 'interpolate-components';
import { compose } from '@wordpress/compose';
@ -14,7 +14,7 @@ import moment from 'moment';
/**
* WooCommerce dependencies
*/
import { Card, DropdownButton } from '@woocommerce/components';
import { Card } from '@woocommerce/components';
import { getSetting } from '@woocommerce/wc-admin-settings';
/**
@ -83,83 +83,81 @@ class StoreAlerts extends Component {
// TODO: should "next X" be the start, or exactly 1X from the current date?
const snoozeOptions = [
{
newDate: moment()
value: moment()
.add( 4, 'hours' )
.unix(),
.unix()
.toString(),
label: __( 'Later Today', 'woocommerce-admin' ),
},
{
newDate: moment()
value: moment()
.add( 1, 'day' )
.hour( 9 )
.minute( 0 )
.second( 0 )
.millisecond( 0 )
.unix(),
.unix()
.toString(),
label: __( 'Tomorrow', 'woocommerce-admin' ),
},
{
newDate: moment()
value: moment()
.add( 1, 'week' )
.hour( 9 )
.minute( 0 )
.second( 0 )
.millisecond( 0 )
.unix(),
.unix()
.toString(),
label: __( 'Next Week', 'woocommerce-admin' ),
},
{
newDate: moment()
value: moment()
.add( 1, 'month' )
.hour( 9 )
.minute( 0 )
.second( 0 )
.millisecond( 0 )
.unix(),
.unix()
.toString(),
label: __( 'Next Month', 'woocommerce-admin' ),
},
];
const setReminderDate = ( snoozeOption, onClose ) => {
return () => {
onClose();
updateNote( alert.id, { status: 'snoozed', date_reminder: snoozeOption.newDate } );
const setReminderDate = snoozeOption => {
updateNote( alert.id, { status: 'snoozed', date_reminder: snoozeOption.value } );
const eventProps = {
alert_name: alert.name,
alert_title: alert.title,
snooze_duration: snoozeOption.newDate,
snooze_label: snoozeOption.label,
};
recordEvent( 'store_alert_snooze', eventProps );
const eventProps = {
alert_name: alert.name,
alert_title: alert.title,
snooze_duration: snoozeOption.value,
snooze_label: snoozeOption.label,
};
recordEvent( 'store_alert_snooze', eventProps );
};
const snooze = alert.is_snoozable && (
<Dropdown
<SelectControl
className="woocommerce-store-alerts__snooze"
position="bottom"
expandOnMobile
renderToggle={ ( { isOpen, onToggle } ) => (
<DropdownButton
onClick={ onToggle }
isOpen={ isOpen }
labels={ [ __( 'Remind Me Later', 'woocommerce-admin' ) ] }
/>
) }
renderContent={ ( { onClose } ) => (
<NavigableMenu className="components-dropdown-menu__menu">
{ snoozeOptions.map( ( option, idx ) => (
<Button
className="components-dropdown-menu__menu-item"
key={ idx }
onClick={ setReminderDate( option, onClose ) }
>
{ option.label }
</Button>
) ) }
</NavigableMenu>
) }
options={ [
{
label: __( 'Remind Me Later', 'woocommerce-admin' ),
value: '0',
},
...snoozeOptions,
] }
onChange={ value => {
if ( '0' === value ) {
return;
}
const reminderOption = snoozeOptions.find( option => option.value === value );
const reminderDate = {
value,
label: reminderOption && reminderOption.label,
};
setReminderDate( reminderDate );
} }
/>
);

View File

@ -39,6 +39,13 @@
min-height: 36px;
padding: 4px 16px;
@include breakpoint( '<782px' ) {
min-height: 36px;
font-size: 16px;
line-height: 1.625;
padding: 5px 16px;
}
+ .components-button {
margin-left: 10px;
}
@ -105,7 +112,6 @@
display: inline-flex;
align-items: center;
border: 1px solid $button-border;
border-bottom: 2px solid $button-border;
border-radius: 4px;
background: $button;
margin-left: 16px;
@ -131,6 +137,16 @@
text-align: center;
}
}
button:first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
button:last-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
.woocommerce-store-alerts.is-loading {
@ -195,9 +211,9 @@
.woocommerce-store-alerts__snooze {
display: inline-flex;
margin-left: 10px;
min-height: 34px;
.woocommerce-dropdown-button__labels {
min-height: 34px;
.components-select-control__input {
vertical-align: initial;
min-height: 36px;
}
}

View File

@ -23,6 +23,7 @@ $core-grey-dark-600: #40464d;
$core-grey-dark-700: #32373c;
$core-grey-dark-800: #23282d;
$core-grey-dark-900: #191e23;
$core-form-grey: #7e8993; // WP 5.3 form input border
$gray-text: $core-grey-dark-500;

View File

@ -101,10 +101,15 @@
input:focus,
select:focus,
button:focus {
color: $core-grey-dark-700;
border-color: $studio-woocommerce-purple-60;
box-shadow: 0 0 2px rgba($studio-woocommerce-purple-60, 0.8);
}
select:hover {
color: $core-grey-dark-700;
}
input[type='checkbox'] {
border-radius: 3px;
}
@ -135,10 +140,12 @@
input[type='radio']:checked::before {
font-size: 18px;
margin-left: 4px;
margin-top: 4px;
background-color: $studio-white;
}
select.components-select-control__input {
max-width: 100%;
}
}
body.woocommerce-page {

View File

@ -1,5 +1,6 @@
# 4.1.0 (Unreleased)
- Added `<ImageUpload />` component.
- Style form components for WordPress 5.3.
# 4.0.0

View File

@ -138,6 +138,10 @@
display: flex;
align-items: center;
}
.components-base-control__field {
margin-bottom: 0;
}
}
@include breakpoint( '<782px' ) {

View File

@ -11,21 +11,17 @@
&::after {
content: '';
background: transparent url(data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%23555%22%2F%3E%3C%2Fsvg%3E) no-repeat right 0 top 55%;
position: absolute;
right: 14px;
top: 50%;
transform: translateY(-50%);
width: 0;
height: 0;
border-style: solid;
border-width: 6px 6px 0 6px;
border-color: $core-grey-dark-500 transparent transparent transparent;
width: 32px;
height: 48px;
@include animate-transform;
}
&.is-open {
&::after {
transform: translateY(-50%) rotate(180deg);
transform: translateX(12px) translateY(2px) rotate(180deg);
}
}
@ -35,9 +31,18 @@
background-color: $core-grey-light-100;
}
&.components-button:focus:not(:disabled) {
border-color: $studio-woocommerce-purple-60;
box-shadow: 0 0 2px rgba($studio-woocommerce-purple-60, 0.8);
}
&.is-multi-line .woocommerce-dropdown-button__labels {
flex-direction: column;
}
&:not(:focus):not(.is-open) {
border-color: $core-form-grey;
}
}
.woocommerce-dropdown-button__labels {

View File

@ -48,6 +48,10 @@
outline: 2px solid transparent;
outline-offset: -2px;
}
.components-form-toggle {
margin-right: $gap-smaller;
}
}
.components-base-control__label,

View File

@ -25,7 +25,6 @@
display: inline-flex;
align-items: baseline;
border: 1px solid $button-border;
border-bottom: 2px solid $button-border;
border-radius: 4px;
background: $button;
@ -41,9 +40,16 @@
}
button:first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
border-right: 2px solid darken($button, 10%);
}
button:last-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.woocommerce-pagination__link {
padding: 4px;
}
@ -76,24 +82,26 @@
margin-top: $gap;
margin-left: 0;
}
.components-base-control {
margin-bottom: 0;
}
.components-base-control__field {
display: flex;
flex-direction: row;
align-items: baseline;
margin-bottom: 0;
}
.components-select-control__input {
width: 60px;
height: 34px;
box-shadow: none;
}
.components-base-control__field {
display: flex;
flex-direction: row;
align-items: baseline;
margin-bottom: 0;
}
.components-base-control__label {
margin-right: $spacing / 2;
.components-select-control__input {
width: 60px;
height: 34px;
box-shadow: none;
}
.components-base-control__label {
margin-right: $spacing / 2;
}
}
}

View File

@ -17,15 +17,16 @@
.woocommerce-select-control__control {
height: auto;
border-radius: 0;
border: 1px solid $core-grey-light-700;
font-size: 13px;
width: 100%;
padding: 3px 2px 3px 36px;
border: 1px solid $core-grey-light-700;
border-radius: 4px;
border-color: $core-form-grey;
&.is-active {
border-color: $input-active-border;
box-shadow: inset 0 0 0 $input-active-inner, 0 0 1px 2px $input-active-outer;
border-color: $studio-woocommerce-purple-60;
box-shadow: 0 0 2px rgba($studio-woocommerce-purple-60, 0.8);
}
}

View File

@ -49,7 +49,7 @@ const SplitButton = ( {
renderToggle={ ( { isOpen, onToggle } ) => {
return (
<IconButton
icon={ isOpen ? 'arrow-up' : 'arrow-down' }
icon={ isOpen ? 'arrow-up-alt2' : 'arrow-down-alt2' }
className={ classnames( 'woocommerce-split-button__menu-toggle', {
'is-active': isOpen,
} ) }

View File

@ -20,7 +20,6 @@
color: $core-grey-dark-500;
border-color: $core-grey-light-800;
background: $core-grey-light-200;
box-shadow: inset 0 -1px 0 $core-grey-light-800;
vertical-align: top;
}
@ -35,7 +34,7 @@
.woocommerce-split-button__menu-toggle {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
padding: $gap-smallest;
padding: $gap-smallest + 1;
height: 32px;
width: 32px;
}
@ -48,14 +47,12 @@
.woocommerce-split-button__menu-toggle.components-icon-button:not(:disabled):not([aria-disabled='true']):not(.is-default):hover {
background-color: $button-hover;
border-color: $core-grey-dark-200;
box-shadow: inset 0 -1px 0 $core-grey-light-800;
}
.woocommerce-split-button__menu-toggle.components-icon-button:not(:disabled):not([aria-disabled='true']):not(.is-default):focus,
.woocommerce-split-button__main-action.components-button:not(:disabled):not([aria-disabled='true']):not(.is-default):focus {
background-color: $button-hover;
border: 1px solid $core-grey-dark-500;
box-shadow: inset 0 -1px 0 $core-grey-dark-300, 0 0 0 2px #bfe7f3;
}
.woocommerce-split-button__main-action.components-button .gridicon,
@ -85,8 +82,6 @@
.components-button:not(:disabled):not([aria-disabled='true']):not(.is-default):hover {
background-color: $studio-white;
color: $wp-admin-sidebar;
box-shadow: inset 0 0 0 1px $core-grey-light-500, inset 0 0 0 2px $studio-white,
0 1px 1px rgba(25, 30, 35, 0.2);
}
}
@ -108,17 +103,14 @@
width: 20px;
}
.woocommerce-split-button__menu-toggle.is-active,
.woocommerce-split-button__menu-toggle.is-active:hover,
.woocommerce-split-button__menu-toggle.is-active > svg,
.woocommerce-split-button__menu-toggle.is-active:hover > svg {
background: initial;
}
.woocommerce-split-button__menu-toggle.is-active,
.woocommerce-split-button__menu-toggle.is-active:hover {
border-color: $core-grey-light-800;
}
.components-tooltip:not(.is-without-arrow):not(.is-mobile)::after {
border-color: $core-grey-dark-900;
}
}
.woocommerce-split-button.is-primary {
@ -127,7 +119,6 @@
background: $studio-pink-50;
color: $studio-white;
border-color: $studio-pink-60;
box-shadow: inset 0 -1px 0 $studio-pink-60;
}
.woocommerce-split-button__main-action.components-button:not(:disabled):not([aria-disabled='true']):not(.is-default):hover,
@ -135,14 +126,12 @@
color: $studio-white;
background-color: $studio-pink-60;
border-color: $studio-pink-70;
box-shadow: inset 0 -1px 0 $studio-pink-70;
}
.woocommerce-split-button__menu-toggle.components-icon-button:not(:disabled):not([aria-disabled='true']):not(.is-default):focus,
.woocommerce-split-button__main-action.components-button:not(:disabled):not([aria-disabled='true']):not(.is-default):focus {
color: $studio-white;
background-color: $studio-pink-60;
box-shadow: inset 0 -1px 0 $studio-pink-70, 0 0 0 2px $studio-pink-10;
border: 1px solid $studio-pink-70;
}

View File

@ -21,7 +21,7 @@ exports[`SplitButton it should render a simple split button 1`] = `
>
<svg
aria-hidden="true"
className="dashicon dashicons-arrow-down"
className="dashicon dashicons-arrow-down-alt2"
focusable="false"
height={20}
role="img"
@ -30,7 +30,7 @@ exports[`SplitButton it should render a simple split button 1`] = `
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15 8l-4.03 6L7 8h8z"
d="M5 6l5 5 5-5 2 1-7 7-7-7z"
/>
</svg>
</button>
@ -61,7 +61,7 @@ exports[`SplitButton it should render a split button with Foo as main label 1`]
>
<svg
aria-hidden="true"
className="dashicon dashicons-arrow-down"
className="dashicon dashicons-arrow-down-alt2"
focusable="false"
height={20}
role="img"
@ -70,7 +70,7 @@ exports[`SplitButton it should render a split button with Foo as main label 1`]
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15 8l-4.03 6L7 8h8z"
d="M5 6l5 5 5-5 2 1-7 7-7-7z"
/>
</svg>
</button>
@ -105,7 +105,7 @@ exports[`SplitButton it should render a split button with a menu label 1`] = `
>
<svg
aria-hidden="true"
className="dashicon dashicons-arrow-down"
className="dashicon dashicons-arrow-down-alt2"
focusable="false"
height={20}
role="img"
@ -114,7 +114,7 @@ exports[`SplitButton it should render a split button with a menu label 1`] = `
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15 8l-4.03 6L7 8h8z"
d="M5 6l5 5 5-5 2 1-7 7-7-7z"
/>
</svg>
</button>
@ -143,7 +143,7 @@ exports[`SplitButton it should render a split button with isPrimary theme 1`] =
>
<svg
aria-hidden="true"
className="dashicon dashicons-arrow-down"
className="dashicon dashicons-arrow-down-alt2"
focusable="false"
height={20}
role="img"
@ -152,7 +152,7 @@ exports[`SplitButton it should render a split button with isPrimary theme 1`] =
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15 8l-4.03 6L7 8h8z"
d="M5 6l5 5 5-5 2 1-7 7-7-7z"
/>
</svg>
</button>
@ -195,7 +195,7 @@ exports[`SplitButton it should render a split button with pencil as main button
>
<svg
aria-hidden="true"
className="dashicon dashicons-arrow-down"
className="dashicon dashicons-arrow-down-alt2"
focusable="false"
height={20}
role="img"
@ -204,7 +204,7 @@ exports[`SplitButton it should render a split button with pencil as main button
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15 8l-4.03 6L7 8h8z"
d="M5 6l5 5 5-5 2 1-7 7-7-7z"
/>
</svg>
</button>

View File

@ -207,7 +207,7 @@ th.woocommerce-table__item {
vertical-align: middle;
line-height: 1;
border: none;
background: transparent;
background: transparent !important;
box-shadow: none !important;
// @todo Add interactive styles

View File

@ -35,3 +35,4 @@ Name | Type | Default | Description
`onChange` | Function | `null` | (required) A function that receives the value of the input
`prefix` | ReactNode | `null` | Markup to be inserted at the beginning of the input
`suffix` | ReactNode | `null` | Markup to be appended at the end of the input
`disabled` | Boolean | `null` | Disables the field

View File

@ -23,12 +23,26 @@ export default withState( {
placeholder="Placeholder"
onChange={ value => setState( { first: value } ) }
/>
<TextControlWithAffixes
label="Disabled text field without affixes"
value={ first }
placeholder="Placeholder"
onChange={ value => setState( { first: value } ) }
disabled
/>
<TextControlWithAffixes
prefix="$"
label="Text field with a prefix"
value={ second }
onChange={ value => setState( { second: value } ) }
/>
<TextControlWithAffixes
prefix="$"
label="Disabled text field with a prefix"
value={ second }
onChange={ value => setState( { second: value } ) }
disabled
/>
<TextControlWithAffixes
prefix="Prefix"
suffix="Suffix"
@ -36,12 +50,27 @@ export default withState( {
value={ third }
onChange={ value => setState( { third: value } ) }
/>
<TextControlWithAffixes
prefix="Prefix"
suffix="Suffix"
label="Disabled text field with both affixes"
value={ third }
onChange={ value => setState( { third: value } ) }
disabled
/>
<TextControlWithAffixes
suffix="%"
label="Text field with a suffix"
value={ fourth }
onChange={ value => setState( { fourth: value } ) }
/>
<TextControlWithAffixes
suffix="%"
label="Disabled text field with a suffix"
value={ fourth }
onChange={ value => setState( { fourth: value } ) }
disabled
/>
<TextControlWithAffixes
prefix="$"
label="Text field with prefix and help text"
@ -49,5 +78,13 @@ export default withState( {
onChange={ value => setState( { fifth: value } ) }
help="This is some help text."
/>
<TextControlWithAffixes
prefix="$"
label="Disabled text field with prefix and help text"
value={ fifth }
onChange={ value => setState( { fifth: value } ) }
help="This is some help text."
disabled
/>
</div>
) );

View File

@ -6,6 +6,7 @@ import { Component } from '@wordpress/element';
import PropTypes from 'prop-types';
import { BaseControl } from '@wordpress/components';
import { withInstanceId } from '@wordpress/compose';
import classnames from 'classnames';
/**
* This component is essentially a wrapper (really a reimplementation) around the
@ -24,6 +25,7 @@ class TextControlWithAffixes extends Component {
prefix,
suffix,
type,
disabled,
...props
} = this.props;
@ -40,9 +42,15 @@ class TextControlWithAffixes extends Component {
describedby.push( `${ id }__suffix` );
}
const affixesClasses = classnames( 'text-control-with-affixes', {
'text-control-with-prefix': prefix,
'text-control-with-suffix': suffix,
disabled,
} );
return (
<BaseControl label={ label } id={ id } help={ help } className={ className }>
<div className="text-control-with-affixes">
<div className={ affixesClasses }>
{ prefix && (
<span
id={ `${ id }__prefix` }
@ -59,6 +67,7 @@ class TextControlWithAffixes extends Component {
value={ value }
onChange={ onChangeValue }
aria-describedby={ describedby.join( ' ' ) }
disabled={ disabled }
{ ...props }
/>
@ -114,6 +123,10 @@ TextControlWithAffixes.propTypes = {
* Markup to be appended at the end of the input.
*/
suffix: PropTypes.node,
/**
* Whether or not the input is disabled.
*/
disabled: PropTypes.bool,
};
export default withInstanceId( TextControlWithAffixes );

View File

@ -19,23 +19,43 @@
}
}
}
&.text-control-with-prefix input {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
&.text-control-with-suffix input {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
}
.text-control-with-affixes__prefix,
.text-control-with-affixes__suffix {
position: relative;
background: $studio-white;
border: 1px solid $core-grey-light-500;
border-width: 1px;
border-style: solid;
border-color: $core-form-grey;
color: $gray-text;
padding: 7px 14px;
white-space: nowrap;
flex: 1 0 auto;
font-size: 14px;
line-height: 1.5;
.disabled & {
background: rgba(255, 255, 255, 0.5);
border-color: rgba(222, 222, 222, 0.75);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.04);
color: rgba(51, 51, 51, 0.5);
}
}
.text-control-with-affixes__prefix {
border-right: none;
border-radius: 4px 0 0 4px;
& + input[type='email'],
& + input[type='password'],
@ -44,11 +64,11 @@
& + input[type='number'] {
&:disabled {
border-left-color: $core-grey-light-500;
border-right-width: 1px;
}
}
}
.text-control-with-affixes__suffix {
border-left: none;
border-radius: 0 4px 4px 0;
}