|
1 | | -import React from 'react' |
2 | | -import PropTypes from 'prop-types' |
3 | 1 | import classnames from 'classnames' |
| 2 | +import PropTypes from 'prop-types' |
| 3 | +import React from 'react' |
4 | 4 | import styled from 'styled-components' |
5 | | -import {COMMON, get} from './constants' |
| 5 | +import {COMMON, get, SystemCommonProps} from './constants' |
| 6 | +import sx, {SxProp} from './sx' |
6 | 7 | import theme from './theme' |
7 | | -import sx from './sx' |
| 8 | +import {ComponentProps} from './utils/types' |
| 9 | +import * as History from 'history' |
8 | 10 |
|
9 | 11 | const ITEM_CLASS = 'UnderlineNav-item' |
10 | 12 | const SELECTED_CLASS = 'selected' |
11 | 13 |
|
12 | | -function UnderlineNavBase({actions, className, align, children, full, label, theme, ...rest}) { |
13 | | - const classes = classnames(className, 'UnderlineNav', align && `UnderlineNav--${align}`, full && 'UnderlineNav--full') |
14 | | - return ( |
15 | | - <nav className={classes} aria-label={label} {...rest}> |
16 | | - <div className="UnderlineNav-body">{children}</div> |
17 | | - {actions && <div className="UnderlineNav-actions">{actions}</div>} |
18 | | - </nav> |
19 | | - ) |
20 | | -} |
21 | | - |
22 | | -const UnderlineNav = styled(UnderlineNavBase)` |
| 14 | +const UnderlineNavBase = styled.nav` |
23 | 15 | display: flex; |
24 | 16 | justify-content: space-between; |
25 | 17 | border-bottom: 1px solid #eaecef; |
@@ -52,10 +44,33 @@ const UnderlineNav = styled(UnderlineNavBase)` |
52 | 44 | ${sx}; |
53 | 45 | ` |
54 | 46 |
|
55 | | -UnderlineNav.Link = styled.a.attrs(props => ({ |
| 47 | +export type UnderlineNavProps = { |
| 48 | + actions?: React.ReactNode |
| 49 | + align?: 'right' |
| 50 | + full?: boolean |
| 51 | + label?: string |
| 52 | +} & ComponentProps<typeof UnderlineNavBase> |
| 53 | + |
| 54 | +function UnderlineNav({actions, className, align, children, full, label, theme, ...rest}: UnderlineNavProps) { |
| 55 | + const classes = classnames(className, 'UnderlineNav', align && `UnderlineNav--${align}`, full && 'UnderlineNav--full') |
| 56 | + return ( |
| 57 | + <UnderlineNavBase className={classes} aria-label={label} theme={theme} {...rest}> |
| 58 | + <div className="UnderlineNav-body">{children}</div> |
| 59 | + {actions && <div className="UnderlineNav-actions">{actions}</div>} |
| 60 | + </UnderlineNavBase> |
| 61 | + ) |
| 62 | +} |
| 63 | + |
| 64 | +type StyledUnderlineNavLinkProps = { |
| 65 | + to?: History.LocationDescriptor |
| 66 | + selected?: boolean |
| 67 | +} & SystemCommonProps & |
| 68 | + SxProp |
| 69 | + |
| 70 | +const UnderlineNavLink = styled.a.attrs<StyledUnderlineNavLinkProps>(props => ({ |
56 | 71 | activeClassName: typeof props.to === 'string' ? 'selected' : '', |
57 | 72 | className: classnames(ITEM_CLASS, props.selected && SELECTED_CLASS, props.className) |
58 | | -}))` |
| 73 | +}))<StyledUnderlineNavLinkProps>` |
59 | 74 | padding: ${get('space.3')} ${get('space.2')}; |
60 | 75 | margin-right: ${get('space.3')}; |
61 | 76 | font-size: ${get('fontSizes.1')}; |
@@ -105,18 +120,18 @@ UnderlineNav.propTypes = { |
105 | 120 | ...sx.propTypes |
106 | 121 | } |
107 | 122 |
|
108 | | -UnderlineNav.Link.defaultProps = { |
| 123 | +UnderlineNavLink.defaultProps = { |
109 | 124 | theme |
110 | 125 | } |
111 | 126 |
|
112 | | -UnderlineNav.Link.propTypes = { |
113 | | - as: PropTypes.oneOfType([PropTypes.string, PropTypes.elementType]), |
| 127 | +UnderlineNavLink.propTypes = { |
114 | 128 | href: PropTypes.string, |
115 | 129 | selected: PropTypes.bool, |
116 | 130 | ...COMMON.propTypes, |
117 | 131 | ...sx.propTypes |
118 | 132 | } |
119 | 133 |
|
120 | | -UnderlineNav.Link.displayName = 'UnderlineNav.Link' |
| 134 | +UnderlineNavLink.displayName = 'UnderlineNav.Link' |
121 | 135 |
|
122 | | -export default UnderlineNav |
| 136 | +export type UnderlineNavLinkProps = ComponentProps<typeof UnderlineNavLink> |
| 137 | +export default Object.assign(UnderlineNav, {Link: UnderlineNavLink}) |
0 commit comments