Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate UnderlineNav to TypeScript #1014

Merged
merged 3 commits into from
Feb 4, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"@styled-system/prop-types": "5.1.2",
"@styled-system/props": "5.1.4",
"@styled-system/theme-get": "5.1.2",
"@types/history": "4.7.8",
"@types/styled-components": "5.1.7",
"@types/styled-system": "5.1.10",
"@types/styled-system__css": "5.0.14",
Expand Down
59 changes: 37 additions & 22 deletions src/UnderlineNav.js → src/UnderlineNav.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import PropTypes from 'prop-types'
import React from 'react'
import styled from 'styled-components'
import {COMMON, get} from './constants'
import {COMMON, get, SystemCommonProps} from './constants'
import sx, {SxProp} from './sx'
import theme from './theme'
import sx from './sx'
import {ComponentProps} from './utils/types'
import * as History from 'history'

const ITEM_CLASS = 'UnderlineNav-item'
const SELECTED_CLASS = 'selected'

function UnderlineNavBase({actions, className, align, children, full, label, theme, ...rest}) {
const classes = classnames(className, 'UnderlineNav', align && `UnderlineNav--${align}`, full && 'UnderlineNav--full')
return (
<nav className={classes} aria-label={label} {...rest}>
<div className="UnderlineNav-body">{children}</div>
{actions && <div className="UnderlineNav-actions">{actions}</div>}
</nav>
)
}

const UnderlineNav = styled(UnderlineNavBase)`
const UnderlineNavBase = styled.nav`
display: flex;
justify-content: space-between;
border-bottom: 1px solid #eaecef;
Expand Down Expand Up @@ -52,10 +44,33 @@ const UnderlineNav = styled(UnderlineNavBase)`
${sx};
`

UnderlineNav.Link = styled.a.attrs(props => ({
export type UnderlineNavProps = {
actions?: React.ReactNode
align?: 'right'
full?: boolean
label?: string
} & ComponentProps<typeof UnderlineNavBase>

function UnderlineNav({actions, className, align, children, full, label, theme, ...rest}: UnderlineNavProps) {
const classes = classnames(className, 'UnderlineNav', align && `UnderlineNav--${align}`, full && 'UnderlineNav--full')
return (
<UnderlineNavBase className={classes} aria-label={label} theme={theme} {...rest}>
<div className="UnderlineNav-body">{children}</div>
{actions && <div className="UnderlineNav-actions">{actions}</div>}
</UnderlineNavBase>
)
}

type StyledUnderlineNavLinkProps = {
to?: History.LocationDescriptor
selected?: boolean
} & SystemCommonProps &
SxProp

const UnderlineNavLink = styled.a.attrs<StyledUnderlineNavLinkProps>(props => ({
activeClassName: typeof props.to === 'string' ? 'selected' : '',
className: classnames(ITEM_CLASS, props.selected && SELECTED_CLASS, props.className)
}))`
}))<StyledUnderlineNavLinkProps>`
padding: ${get('space.3')} ${get('space.2')};
margin-right: ${get('space.3')};
font-size: ${get('fontSizes.1')};
Expand Down Expand Up @@ -105,18 +120,18 @@ UnderlineNav.propTypes = {
...sx.propTypes
}

UnderlineNav.Link.defaultProps = {
UnderlineNavLink.defaultProps = {
theme
}

UnderlineNav.Link.propTypes = {
as: PropTypes.oneOfType([PropTypes.string, PropTypes.elementType]),
UnderlineNavLink.propTypes = {
href: PropTypes.string,
selected: PropTypes.bool,
...COMMON.propTypes,
...sx.propTypes
}

UnderlineNav.Link.displayName = 'UnderlineNav.Link'
UnderlineNavLink.displayName = 'UnderlineNav.Link'

export default UnderlineNav
export type UnderlineNavLinkProps = ComponentProps<typeof UnderlineNavLink>
export default Object.assign(UnderlineNav, {Link: UnderlineNavLink})
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ describe('UnderlineNav.Link', () => {
})

it('adds activeClassName={SELECTED_CLASS} when it gets a "to" prop', () => {
const Mock = jest.fn(() => <div />)
render(<UnderlineNav.Link as={Mock} to="#" />)
expect(Mock.mock.calls[0][0].to).toEqual('#')
expect(Mock.mock.calls[0][0].activeClassName).toEqual('selected')
const Link = ({theme, ...props}: any) => <div {...props} />
expect(render(<UnderlineNav.Link as={Link} to="#" />)).toMatchSnapshot()
})
})
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`UnderlineNav.Link adds activeClassName={SELECTED_CLASS} when it gets a "to" prop 1`] = `
.c0 {
padding: 16px 8px;
margin-right: 16px;
font-size: 14px;
line-height: 1.5;
color: #586069;
text-align: center;
border-bottom: 2px solid transparent;
-webkit-text-decoration: none;
text-decoration: none;
}

.c0:hover,
.c0:focus {
color: #24292e;
-webkit-text-decoration: none;
text-decoration: none;
border-bottom-color: #e1e4e8;
-webkit-transition: 0.2s ease;
transition: 0.2s ease;
}

.c0:hover .UnderlineNav-octicon,
.c0:focus .UnderlineNav-octicon {
color: #6a737d;
}

.c0.selected {
color: #24292e;
border-bottom-color: #f66a0a;
}

.c0.selected .UnderlineNav-octicon {
color: #6a737d;
}

<div
activeClassName="selected"
className="c0 UnderlineNav-item"
to="#"
/>
`;

exports[`UnderlineNav.Link renders consistently 1`] = `
.c0 {
padding: 16px 8px;
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1820,6 +1820,11 @@
dependencies:
"@types/node" "*"

"@types/history@4.7.8":
version "4.7.8"
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934"
integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==

"@types/hoist-non-react-statics@*":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
Expand Down