Skip to content
This repository was archived by the owner on Jul 29, 2025. It is now read-only.

Commit 5108e76

Browse files
barteksekulaMatt Goo
authored andcommitted
feat(tab): Allow to render Tab as an anchor node (#928)
1 parent 1f7f872 commit 5108e76

File tree

3 files changed

+17
-3
lines changed

3 files changed

+17
-3
lines changed

packages/tab/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ isMinWidthIndicator | boolean | If true will display the `<TabIndicator />` to t
8787
previousIndicatorClientRect | ClientRect | The indicator's clientRect that was previously activated.
8888
onInteraction | Function | The function is called if the tab receives any interaction
8989
stacked | boolean | If true will display the tab icon and label to flow vertically instead of horizontally.
90+
tag | String | Customizes the tab tag (defaults to `'button'`). The only available options are 'button' or 'a'.
9091

9192
## Sass Mixins
9293

packages/tab/index.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,16 @@ import {MDCTabAdapter} from '@material/tab/adapter';
2929

3030
import TabRipple, {TabRippleProps} from './TabRipple';
3131

32-
export interface TabProps extends React.HTMLProps<HTMLButtonElement> {
32+
export interface TabProps
33+
extends React.HTMLProps<HTMLButtonElement | HTMLAnchorElement> {
3334
active?: boolean;
3435
focusOnActivate?: boolean;
3536
isFadingIndicator?: boolean;
3637
indicatorContent?: React.ReactNode;
3738
minWidth?: boolean;
3839
isMinWidthIndicator?: boolean;
3940
stacked?: boolean;
41+
tag?: 'button' | 'a';
4042
previousIndicatorClientRect?: ClientRect;
4143
onInteraction?: () => void;
4244
}
@@ -68,6 +70,7 @@ export default class Tab extends React.Component<TabProps, TabState> {
6870
minWidth: false,
6971
isMinWidthIndicator: false,
7072
stacked: false,
73+
tag: 'button',
7174
onInteraction: () => null,
7275
};
7376

@@ -195,6 +198,7 @@ export default class Tab extends React.Component<TabProps, TabState> {
195198
minWidth,
196199
onInteraction,
197200
stacked,
201+
tag: Tag,
198202
/* eslint-enable */
199203
children,
200204
isMinWidthIndicator,
@@ -203,7 +207,9 @@ export default class Tab extends React.Component<TabProps, TabState> {
203207
const {tabIndex, ['aria-selected']: ariaSelected} = this.state;
204208

205209
return (
206-
<button
210+
// https://github.com/Microsoft/TypeScript/issues/28892
211+
// @ts-ignore
212+
<Tag
207213
className={this.classes}
208214
role='tab'
209215
aria-selected={ariaSelected}
@@ -219,7 +225,7 @@ export default class Tab extends React.Component<TabProps, TabState> {
219225
</span>
220226
{isMinWidthIndicator ? null : this.renderIndicator()}
221227
<TabRipple ref={this.tabRippleRef} />
222-
</button>
228+
</Tag>
223229
);
224230
}
225231

test/unit/tab/index.test.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ test('adds the stacked class if props.stacked is true', () => {
2525
assert.isTrue(wrapper.hasClass('mdc-tab--stacked'));
2626
});
2727

28+
test('renders as anchor if props.tag is a and href is set', () => {
29+
const wrapper = mount(<Tab tag='a' href='/foobar' />);
30+
const node = wrapper.getDOMNode();
31+
assert.equal(node.tagName.toLowerCase(), 'a');
32+
assert.equal(node.getAttribute('href'), '/foobar');
33+
});
34+
2835
test('adds the active class if props.active is true on mount', () => {
2936
const wrapper = shallow(<Tab active />);
3037
assert.isTrue(wrapper.hasClass('mdc-tab--active'));

0 commit comments

Comments
 (0)