diff --git a/packages/components/src/components/button/_button.scss b/packages/components/src/components/button/_button.scss
index 4b9719d560cf..903e0b420eda 100644
--- a/packages/components/src/components/button/_button.scss
+++ b/packages/components/src/components/button/_button.scss
@@ -96,12 +96,12 @@
}
&:focus {
- color: $text-04;
+ color: $inverse-01;
background-color: $interactive-03;
}
&:active {
- background-color: $active-primary;
+ color: $inverse-01;
}
&:disabled,
@@ -112,6 +112,7 @@
&.#{$prefix}--btn--disabled:focus {
background: transparent;
color: $disabled;
+ outline: none;
& > .#{$prefix}--btn__icon path {
fill: $disabled;
@@ -161,6 +162,7 @@
color: $disabled;
background: transparent;
border-color: transparent;
+ outline: none;
.#{$prefix}--btn__icon path {
fill: $disabled;
diff --git a/packages/components/src/components/checkbox/_checkbox.scss b/packages/components/src/components/checkbox/_checkbox.scss
index dc81de9a2d67..df09d8a15e55 100644
--- a/packages/components/src/components/checkbox/_checkbox.scss
+++ b/packages/components/src/components/checkbox/_checkbox.scss
@@ -18,7 +18,7 @@
@mixin checkbox {
// Spacing between checkboxes
.#{$prefix}--form-item.#{$prefix}--checkbox-wrapper {
- margin-bottom: rem(8px);
+ margin-bottom: $carbon--spacing-02;
}
// Spacing above collection of checkboxes
@@ -26,9 +26,10 @@
margin-top: rem(3px);
}
- // Remove spacing above collection of checkboxes if label is present
+ // Shift collection of checkboxes up if label is present
+ // to account for the 2px top margin for the first checkbox
.#{$prefix}--label + .#{$prefix}--form-item.#{$prefix}--checkbox-wrapper {
- margin-top: 0;
+ margin-top: -#{$carbon--spacing-01};
}
// Spacing below collection of checkboxes
diff --git a/packages/components/src/components/data-table/_data-table-action.scss b/packages/components/src/components/data-table/_data-table-action.scss
index 0b71c9637a9c..fc7b7ec8d31f 100644
--- a/packages/components/src/components/data-table/_data-table-action.scss
+++ b/packages/components/src/components/data-table/_data-table-action.scss
@@ -17,11 +17,12 @@
//TOOLBAR
//-------------------------------------------------
.#{$prefix}--table-toolbar {
- display: flex;
- width: 100%;
background: $ui-01;
+ display: flex;
height: $layout-04;
+ overflow: hidden;
position: relative; //need for batch actions
+ width: 100%;
}
.#{$prefix}--toolbar-content {
diff --git a/packages/components/src/components/date-picker/_date-picker.scss b/packages/components/src/components/date-picker/_date-picker.scss
index 9089d50b2b5f..426ec2a2eaa2 100644
--- a/packages/components/src/components/date-picker/_date-picker.scss
+++ b/packages/components/src/components/date-picker/_date-picker.scss
@@ -40,6 +40,7 @@
.#{$prefix}--date-picker-input__wrapper {
display: flex;
align-items: center;
+ position: relative;
~ .#{$prefix}--form-requirement {
max-height: rem(200px);
@@ -130,6 +131,9 @@
fill: $icon-01;
cursor: pointer;
z-index: 1;
+ // vertically center icon within parent container on IE11
+ top: 50%;
+ transform: translateY(-50%);
}
.#{$prefix}--date-picker__icon ~ .#{$prefix}--date-picker__input {
diff --git a/packages/components/src/components/radio-button/_radio-button.scss b/packages/components/src/components/radio-button/_radio-button.scss
index 6b92b000c6de..14afdc9deef2 100644
--- a/packages/components/src/components/radio-button/_radio-button.scss
+++ b/packages/components/src/components/radio-button/_radio-button.scss
@@ -26,6 +26,11 @@
margin-top: rem(6px);
}
+ // Remove spacing above collection of radio buttons if label is present
+ .#{$prefix}--label + .#{$prefix}--form-item .#{$prefix}--radio-button-group {
+ margin-top: 0;
+ }
+
// vertical radio button
.#{$prefix}--radio-button-group--vertical {
flex-direction: column;
@@ -37,6 +42,7 @@
.#{$prefix}--radio-button__label {
margin-right: 0;
+ line-height: carbon--mini-units(2.5);
}
.#{$prefix}--radio-button__label:not(:last-of-type) {
diff --git a/packages/components/src/components/slider/_slider.scss b/packages/components/src/components/slider/_slider.scss
index c0fea05b77ee..d1d4bbc40ce5 100644
--- a/packages/components/src/components/slider/_slider.scss
+++ b/packages/components/src/components/slider/_slider.scss
@@ -101,13 +101,13 @@
&:focus {
// 20px / 14px = 1.4285714286
transform: translate(-50%, -50%) scale(1.4285714286);
- box-shadow: inset 0 0 0 2px $interactive-01, inset 0 0 0 3px $ui-01;
- background-color: $interactive-01;
+ box-shadow: inset 0 0 0 2px $interactive-04, inset 0 0 0 3px $ui-01;
+ background-color: $interactive-04;
}
&:active {
transform: translate(-50%, -50%) scale(1.4285714286);
- box-shadow: inset 0 0 0 2px $interactive-01;
+ box-shadow: inset 0 0 0 2px $interactive-04;
}
}
@@ -130,7 +130,7 @@
}
.#{$prefix}--slider__thumb:focus ~ .#{$prefix}--slider__filled-track {
- background-color: $interactive-01;
+ background-color: $interactive-04;
}
// Disabled state
diff --git a/packages/components/src/components/toggle/_toggle.scss b/packages/components/src/components/toggle/_toggle.scss
index 3a9beb2dd4b0..d7be5bc525cc 100644
--- a/packages/components/src/components/toggle/_toggle.scss
+++ b/packages/components/src/components/toggle/_toggle.scss
@@ -315,6 +315,9 @@
margin-left: carbon--rem(56px);
@include type-style('body-short-01');
user-select: none;
+ // top offset needed to vertically center absolutely positioned flex child in IE11
+ top: 50%;
+ transform: translateY(-50%);
}
//----------------------------------------------
@@ -435,6 +438,19 @@
.#{$prefix}--toggle__check {
fill: $disabled-02;
}
+
+ //----------------------------------------------
+ // Skeleton
+ // ---------------------------------------------
+
+ .#{$prefix}--toggle__label.#{$prefix}--skeleton {
+ flex-direction: column;
+ align-items: flex-start;
+
+ .#{$prefix}--toggle__label-text {
+ margin-bottom: $carbon--spacing-03;
+ }
+ }
}
@include exports('toggle') {
diff --git a/packages/react/src/components/Breadcrumb/Breadcrumb.Skeleton.js b/packages/react/src/components/Breadcrumb/Breadcrumb.Skeleton.js
index 93f5c2e5207b..3003edf25be1 100644
--- a/packages/react/src/components/Breadcrumb/Breadcrumb.Skeleton.js
+++ b/packages/react/src/components/Breadcrumb/Breadcrumb.Skeleton.js
@@ -14,9 +14,7 @@ export default class BreadcrumbSkeleton extends React.Component {
render() {
const item = (
+
{
);
expect(wrapper).toMatchSnapshot();
});
+ it('should set an appropriate unique id', () => {
+ const wrapper = mount(
+
+ );
+ expect(typeof wrapper.find('Search').prop('id')).toBe('string');
+ });
});
diff --git a/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap b/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap
index d58c1dcf3fed..13849aa5af7b 100644
--- a/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap
+++ b/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap
@@ -528,7 +528,9 @@ exports[`DataTable selection -- radio buttons should render 1`] = `
onSelect={[Function]}
radio={true}
>
-
+ |
-
+ |
-
+ |
-
+ |
-
+ |
-
+ |
- {this.state.labelText}
+ {this.state.labelText}
{
if (matches(evt, [keys.Enter, keys.Space])) {
@@ -106,7 +105,7 @@ export default function FileUploaderDropContainer(props) {
}
}}
{...other}>
-
+
{labelText}
{
const className = cx(`${prefix}--list-box__selection`, {
[`${prefix}--tag--filter`]: selectionCount,
@@ -29,13 +31,19 @@ const ListBoxSelection = ({
});
const handleOnClick = event => {
event.stopPropagation();
+ if (disabled) {
+ return;
+ }
clearSelection(event);
};
const handleOnKeyDown = event => {
event.stopPropagation();
+ if (disabled) {
+ return;
+ }
// When a user hits ENTER, we'll clear the selection
- if (event.keyCode === 13) {
+ if (match(event, keys.Enter)) {
clearSelection(event);
}
};
@@ -44,7 +52,7 @@ const ListBoxSelection = ({
{
mount( );
expect(mockProps.translateWithId).toHaveBeenCalledWith('clear.all');
});
+
+ it('should call clearSelection when clicked', () => {
+ const wrapper = mount( );
+ wrapper.simulate('click');
+ expect(mockProps.clearSelection).toHaveBeenCalled();
+ });
+
+ it('should call clearSelection on Enter keydown', () => {
+ const wrapper = mount( );
+ wrapper.simulate('keydown', {
+ key: 'Enter',
+ keyCode: 13,
+ which: 13,
+ });
+ expect(mockProps.clearSelection).toHaveBeenCalled();
+ });
+
+ it('should not clearSelection on click when disabled', () => {
+ const wrapper = mount( );
+ wrapper.simulate('click');
+ expect(mockProps.clearSelection).toHaveBeenCalledTimes(0);
+ });
+
+ it('should not call clearSelection on Enter keydown when disabled', () => {
+ const wrapper = mount( );
+ wrapper.simulate('keydown', {
+ key: 'Enter',
+ keyCode: 13,
+ which: 13,
+ });
+ expect(mockProps.clearSelection).toHaveBeenCalledTimes(0);
+ });
});
diff --git a/packages/react/src/components/ListBox/__tests__/__snapshots__/ListBoxField-test.js.snap b/packages/react/src/components/ListBox/__tests__/__snapshots__/ListBoxField-test.js.snap
index cbcc02d46305..f38cfc0fa158 100644
--- a/packages/react/src/components/ListBox/__tests__/__snapshots__/ListBoxField-test.js.snap
+++ b/packages/react/src/components/ListBox/__tests__/__snapshots__/ListBoxField-test.js.snap
@@ -23,7 +23,7 @@ exports[`ListBoxField should render 1`] = `
onClick={[Function]}
onKeyDown={[Function]}
role="button"
- tabIndex="0"
+ tabIndex={0}
title="Clear selected item"
>
@@ -85,7 +85,7 @@ exports[`ListBoxField should set \`aria-owns\` based when expanded 1`] = `
onClick={[Function]}
onKeyDown={[Function]}
role="button"
- tabIndex="0"
+ tabIndex={0}
title="Clear selected item"
>
diff --git a/packages/react/src/components/ListBox/__tests__/__snapshots__/ListBoxSelection-test.js.snap b/packages/react/src/components/ListBox/__tests__/__snapshots__/ListBoxSelection-test.js.snap
index 5813bf7356db..77dba1927ce6 100644
--- a/packages/react/src/components/ListBox/__tests__/__snapshots__/ListBoxSelection-test.js.snap
+++ b/packages/react/src/components/ListBox/__tests__/__snapshots__/ListBoxSelection-test.js.snap
@@ -32,7 +32,7 @@ exports[`ListBoxSelection should render 1`] = `
onClick={[Function]}
onKeyDown={[Function]}
role="button"
- tabIndex="0"
+ tabIndex={0}
title="translation"
>
@@ -100,7 +100,7 @@ exports[`ListBoxSelection should render 2`] = `
onClick={[Function]}
onKeyDown={[Function]}
role="button"
- tabIndex="0"
+ tabIndex={0}
title="translation"
>
3
diff --git a/packages/react/src/components/Modal/Modal-story.js b/packages/react/src/components/Modal/Modal-story.js
index 119d51318561..9e25feda0a69 100644
--- a/packages/react/src/components/Modal/Modal-story.js
+++ b/packages/react/src/components/Modal/Modal-story.js
@@ -11,6 +11,7 @@ import { action } from '@storybook/addon-actions';
import { withKnobs, boolean, text } from '@storybook/addon-knobs';
import Modal from '../Modal';
+import TextInput from '../TextInput';
import { settings } from 'carbon-components';
const { prefix } = settings;
@@ -74,4 +75,31 @@ storiesOf('Modal', module)
`,
},
}
+ )
+ .add(
+ 'Trap Focus',
+ () => (
+ <>
+
+
+
+
+ >
+ ),
+ {
+ info: {
+ text: `
+ Specify a selector for the primary element to focus when opening a modal.
+ `,
+ },
+ }
);
diff --git a/packages/react/src/components/Modal/Modal.js b/packages/react/src/components/Modal/Modal.js
index 3e84f43f150d..b525b81976e6 100644
--- a/packages/react/src/components/Modal/Modal.js
+++ b/packages/react/src/components/Modal/Modal.js
@@ -220,12 +220,15 @@ export default class Modal extends Component {
}
initialFocus = focusContainerElement => {
- const primaryFocusElement = focusContainerElement
- ? focusContainerElement.querySelector(this.props.selectorPrimaryFocus)
+ const containerElement = focusContainerElement || this.innerModal.current;
+ const primaryFocusElement = containerElement
+ ? containerElement.querySelector(this.props.selectorPrimaryFocus)
: null;
+
if (primaryFocusElement) {
return primaryFocusElement;
}
+
return this.button && this.button.current;
};
diff --git a/packages/react/src/components/MultiSelect/FilterableMultiSelect.js b/packages/react/src/components/MultiSelect/FilterableMultiSelect.js
index 960b699ed6c0..fa368bbfaaa8 100644
--- a/packages/react/src/components/MultiSelect/FilterableMultiSelect.js
+++ b/packages/react/src/components/MultiSelect/FilterableMultiSelect.js
@@ -358,6 +358,7 @@ export default class FilterableMultiSelect extends React.Component {
clearSelection={clearSelection}
selectionCount={selectedItem.length}
translateWithId={translateWithId}
+ disabled={disabled}
/>
)}
)}
)}
diff --git a/packages/react/src/components/OverflowMenu/OverflowMenu.js b/packages/react/src/components/OverflowMenu/OverflowMenu.js
index bf45f2170e6b..0b858f483e46 100644
--- a/packages/react/src/components/OverflowMenu/OverflowMenu.js
+++ b/packages/react/src/components/OverflowMenu/OverflowMenu.js
@@ -535,7 +535,6 @@ class OverflowMenu extends Component {
aria-expanded={this.state.open}
className={overflowMenuClasses}
onKeyDown={this.handleKeyPress}
- onBlur={this.handleBlur}
onClick={this.handleClick}
aria-label={ariaLabel}
id={id}
diff --git a/packages/react/src/components/Toggle/Toggle-story.js b/packages/react/src/components/Toggle/Toggle-story.js
index 9f475b019550..41599f86fbd5 100644
--- a/packages/react/src/components/Toggle/Toggle-story.js
+++ b/packages/react/src/components/Toggle/Toggle-story.js
@@ -12,10 +12,14 @@ import { withKnobs, text, boolean } from '@storybook/addon-knobs';
import Toggle from '../Toggle';
import ToggleSkeleton from '../Toggle/Toggle.Skeleton';
+const a11yProps = () => ({
+ labelText: text('Label toggle input control (labelText)', ''),
+ ['aria-label']: text('ARIA label of the toggle (aria-label)', ''),
+});
+
const toggleProps = () => ({
+ ...a11yProps(),
className: 'some-class',
- labelText: text('Label for toggle button input (labelText)', ''),
- ['aria-label']: text('ARIA label of the toggle (aria-label)', ''),
labelA: text('Label for untoggled state (labelA)', 'Off'),
labelB: text('Label for toggled state (labelB)', 'On'),
disabled: boolean('Disabled (disabled)', false),
@@ -60,7 +64,7 @@ storiesOf('Toggle', module)
},
}
)
- .add('skeleton', () => , {
+ .add('skeleton', () => , {
info: {
text: `
Placeholder skeleton state to use when content is loading.
diff --git a/packages/react/src/components/Toggle/Toggle.Skeleton.js b/packages/react/src/components/Toggle/Toggle.Skeleton.js
index 64988791d254..8c63537625c3 100644
--- a/packages/react/src/components/Toggle/Toggle.Skeleton.js
+++ b/packages/react/src/components/Toggle/Toggle.Skeleton.js
@@ -5,14 +5,36 @@
* LICENSE file in the root directory of this source tree.
*/
+import PropTypes from 'prop-types';
import React from 'react';
import { settings } from 'carbon-components';
const { prefix } = settings;
export default class ToggleSkeleton extends React.Component {
+ static propTypes = {
+ /**
+ * Provide an id that unique represents the underlying
+ */
+ id: PropTypes.string,
+
+ /**
+ * Provide the text that will be read by a screen reader when visiting this
+ * control
+ * `aria-label` is always required but will be null if `labelText` is also
+ * provided
+ */
+ labelText: PropTypes.string,
+ ['aria-label']: PropTypes.string.isRequired,
+ };
+
+ static defaultProps = {
+ ['aria-label']: 'Toggle is loading',
+ };
+
render() {
- const { id } = this.props;
+ const { id, labelText } = this.props;
+
return (
| | | | | | | |