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 Caret to TypeScript #1030

Merged
merged 3 commits into from
Feb 9, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions .changeset/poor-buckets-cheer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/components": patch
---

Migrate `Caret` to TypeScript
58 changes: 41 additions & 17 deletions src/Caret.js → src/Caret.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@ import PropTypes from 'prop-types'
import {style} from 'styled-system'
import theme from './theme'

type Location =
| 'top'
| 'top-left'
| 'top-right'
| 'right'
| 'right-top'
| 'right-bottom'
| 'bottom'
| 'bottom-left'
| 'bottom-right'
| 'left'
| 'left-top'
| 'left-bottom'

type Alignment = 'top' | 'right' | 'bottom' | 'left'

const oppositeEdge = {
top: 'Bottom',
right: 'Left',
Expand All @@ -17,12 +33,12 @@ const perpendicularEdge = {
left: 'Top'
}

function getEdgeAlign(location) {
function getEdgeAlign(location: Location): Alignment[] {
const [edge, align] = location.split('-')
return [edge, align]
return [edge as Alignment, align as Alignment]
}

function getPosition(edge, align, spacing) {
function getPosition(edge: Alignment, align: Alignment, spacing: number) {
const opposite = oppositeEdge[edge].toLowerCase()
const perp = perpendicularEdge[edge].toLowerCase()
return {
Expand All @@ -35,23 +51,22 @@ const getBg = style({prop: 'bg', key: 'colors'})
const getBorderColor = style({prop: 'borderColor', key: 'colors'})
const getBorderWidth = style({prop: 'borderWidth', key: 'borderWidths', scale: [0, 1]})

function Caret(props) {
export type CaretProps = {
bg?: string
borderColor?: string
borderWidth?: string
size?: number
location?: Location
}

function Caret(props: CaretProps) {
const {bg} = getBg(props)
const {borderColor} = getBorderColor(props)
const {borderWidth} = getBorderWidth(props)
const {size, location} = props
const {size = 8, location = 'bottom'} = props
const [edge, align] = getEdgeAlign(location)
const perp = perpendicularEdge[edge]

const style = {
pointerEvents: 'none',
position: 'absolute',
...getPosition(edge, align, size),
// if align is set (top|right|bottom|left),
// then we don't need an offset margin
[`margin${perp}`]: align ? null : -size
}

// note: these arrays represent points in the form [x, y]
const a = [-size, 0]
const b = [0, size]
Expand All @@ -71,7 +86,18 @@ function Caret(props) {
}[edge]

return (
<svg width={size * 2} height={size * 2} style={style}>
<svg
width={size * 2}
height={size * 2}
style={{
pointerEvents: 'none',
position: 'absolute',
...getPosition(edge, align, size),
// if align is set (top|right|bottom|left),
// then we don't need an offset margin
[`margin${perp}`]: align ? null : -size
}}
>
<g transform={transform}>
<path d={triangle} fill={bg} />
<path d={line} fill="none" stroke={borderColor} strokeWidth={borderWidth} />
Expand Down Expand Up @@ -99,8 +125,6 @@ Caret.defaultProps = {
bg: 'white',
borderColor: 'gray.2',
borderWidth: 1,
location: 'bottom',
size: 8,
theme
}

Expand Down
8 changes: 4 additions & 4 deletions src/__tests__/Caret.js → src/__tests__/Caret.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import {Caret} from '..'
import Caret, {CaretProps} from '../Caret'
import {render, checkExports} from '../utils/testing'
import theme from '../theme'
import {render as HTMLRender, cleanup} from '@testing-library/react'
Expand All @@ -25,13 +25,13 @@ describe('Caret', () => {

it('renders cardinal directions', () => {
for (const location of ['top', 'right', 'bottom', 'left']) {
expect(render(<Caret location={location} theme={theme} />)).toMatchSnapshot()
expect(render(<Caret location={location as CaretProps['location']} theme={theme} />)).toMatchSnapshot()
}
for (const location of ['top-left', 'top-right', 'bottom-left', 'bottom-right']) {
expect(render(<Caret location={location} theme={theme} />)).toMatchSnapshot()
expect(render(<Caret location={location as CaretProps['location']} theme={theme} />)).toMatchSnapshot()
}
for (const location of ['left-top', 'left-bottom', 'right-top', 'right-bottom']) {
expect(render(<Caret location={location} theme={theme} />)).toMatchSnapshot()
expect(render(<Caret location={location as CaretProps['location']} theme={theme} />)).toMatchSnapshot()
}
})
})