diff --git a/packages/tab/README.md b/packages/tab/README.md
index 107292b85..c0a65e7e5 100644
--- a/packages/tab/README.md
+++ b/packages/tab/README.md
@@ -78,6 +78,7 @@ class MyApp extends React.Component {
Prop Name | Type | Description
--- | --- | ---
active | boolean | If true will activate the tab and indicator.
+focusOnActivate | boolean | If true will focus itself when activated. Defaults to `true`.
className | string | Classes to appear on className attribute of root element.
isFadingIndicator | boolean | Enables a fading indicator, instead of sliding (default).
indicatorContent | element | Element that will appear within the `` element.
diff --git a/packages/tab/index.tsx b/packages/tab/index.tsx
index cef0fa5af..f9c9104db 100644
--- a/packages/tab/index.tsx
+++ b/packages/tab/index.tsx
@@ -31,6 +31,7 @@ import TabRipple, {TabRippleProps} from './TabRipple';
export interface TabProps extends React.HTMLProps {
active?: boolean;
+ focusOnActivate?: boolean;
isFadingIndicator?: boolean;
indicatorContent?: React.ReactNode;
minWidth?: boolean;
@@ -59,6 +60,7 @@ export default class Tab extends React.Component {
static defaultProps: Partial = {
active: false,
+ focusOnActivate: true,
className: '',
isFadingIndicator: false,
indicatorContent: null,
@@ -76,9 +78,11 @@ export default class Tab extends React.Component {
};
componentDidMount() {
+ const {active, focusOnActivate} = this.props;
this.foundation = new MDCTabFoundation(this.adapter);
this.foundation.init();
- if (this.props.active) {
+ this.foundation.setFocusOnActivate(focusOnActivate);
+ if (active) {
this.foundation.activate();
}
}
@@ -88,10 +92,14 @@ export default class Tab extends React.Component {
}
componentDidUpdate(prevProps: TabProps) {
- if (this.props.active !== prevProps.active) {
- if (this.props.active) {
+ const {active, focusOnActivate, previousIndicatorClientRect} = this.props;
+ if (focusOnActivate !== prevProps.focusOnActivate) {
+ this.foundation.setFocusOnActivate(focusOnActivate);
+ }
+ if (active !== prevProps.active) {
+ if (active) {
// If active state is updated through props, previousIndicatorClientRect must also be passed through props
- this.activate(this.props.previousIndicatorClientRect);
+ this.activate(previousIndicatorClientRect);
} else {
this.deactivate();
}
@@ -176,6 +184,7 @@ export default class Tab extends React.Component {
const {
/* eslint-disable */
active,
+ focusOnActivate,
previousIndicatorClientRect,
className,
isFadingIndicator,
diff --git a/test/unit/tab/index.test.tsx b/test/unit/tab/index.test.tsx
index 5787a66d5..92797aed7 100644
--- a/test/unit/tab/index.test.tsx
+++ b/test/unit/tab/index.test.tsx
@@ -65,6 +65,56 @@ test('if props.active updates to false, foundation.deactivate is called', () =>
td.verify(wrapper.instance().deactivate(), {times: 1});
});
+test('calls foundation.setFocusOnActivate when props.focusOnActivate changes from false to true', () => {
+ const wrapper = shallow();
+ wrapper.instance().foundation.setFocusOnActivate = td.func();
+ wrapper.setProps({focusOnActivate: true});
+ td.verify(wrapper.instance().foundation.setFocusOnActivate(true), {times: 1});
+});
+
+test('calls foundation.setFocusOnActivate when props.focusOnActivate changes from true to false', () => {
+ const wrapper = shallow();
+ wrapper.instance().foundation.setFocusOnActivate = td.func();
+ wrapper.setProps({focusOnActivate: false});
+ td.verify(wrapper.instance().foundation.setFocusOnActivate(false), {times: 1});
+});
+
+test('when props.focusOnActivate is true, an active tab should be focused on mount', () => {
+ const div = document.createElement('div');
+ document.body.append(div);
+ const wrapper = mount(, {attachTo: div});
+ assert.equal(document.activeElement, wrapper.getDOMNode());
+ div.remove();
+});
+
+test('when props.focusOnActivate is true and active is changed to true, the tab should be focused', () => {
+ const div = document.createElement('div');
+ document.body.append(div);
+ const wrapper = mount(, {attachTo: div});
+ assert.notEqual(document.activeElement, wrapper.getDOMNode());
+ wrapper.setProps({active: true});
+ assert.equal(document.activeElement, wrapper.getDOMNode());
+ div.remove();
+});
+
+test('when props.focusOnActivate is false, an active tab should not be focused on mount', () => {
+ const div = document.createElement('div');
+ document.body.append(div);
+ const wrapper = mount(, {attachTo: div});
+ assert.notEqual(document.activeElement, wrapper.getDOMNode());
+ div.remove();
+});
+
+test('when props.focusOnActivate is false and active is changed to true, the tab should not be focused', () => {
+ const div = document.createElement('div');
+ document.body.append(div);
+ const wrapper = mount(, {attachTo: div});
+ assert.notEqual(document.activeElement, wrapper.getDOMNode());
+ wrapper.setProps({active: true});
+ assert.notEqual(document.activeElement, wrapper.getDOMNode());
+ div.remove();
+});
+
test('#adapter.addClass adds class to state.classList', () => {
const wrapper = shallow();
wrapper.instance().adapter.addClass('test-class');