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

Typescript Selection Controls (Switch, Checkbox, Radio) #679

Merged
merged 5 commits into from
Oct 15, 2020
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
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* eslint-disable no-undef */

import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { render, cleanup, fireEvent, screen } from '@testing-library/react'
import '@testing-library/jest-dom'
import 'jest-styled-components'
Expand All @@ -16,7 +15,11 @@ const StyledCheckbox = styled(Checkbox)`
clip-path: unset;
`

const ControlledCheckbox = ({ onChange }) => {
type ControlledProps = {
onChange: () => void
}

const ControlledCheckbox = ({ onChange }: ControlledProps) => {
const [checked, setChecked] = useState(true)
return (
<Checkbox
Expand All @@ -29,9 +32,6 @@ const ControlledCheckbox = ({ onChange }) => {
/>
)
}
ControlledCheckbox.propTypes = {
onChange: PropTypes.func.isRequired,
}

describe('Checkbox', () => {
it('Can extend the css for the component', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,37 @@
/* eslint camelcase: "off" */
// @ts-nocheck
import React, { forwardRef } from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import {
checkbox,
checkbox_outline, // eslint-disable-line camelcase
checkbox_indeterminate, // eslint-disable-line camelcase
} from '@equinor/eds-icons'
import type { IconData } from '@equinor/eds-icons'

import { checkbox as tokens } from './Checkbox.tokens'
import { typographyTemplate } from '../../_common/templates'

const { color, enabled } = tokens

const StyledCheckbox = styled.label`
type StyledCheckboxProps = {
disabled: boolean
}

const StyledCheckbox = styled.label<StyledCheckboxProps>`
display: inline-flex;
align-items: center;
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
`
type StyledIconPathProps = {
icon: IconData
name: string
}

const StyledPath = styled.path.attrs(({ icon }) => ({
const StyledPath = styled.path.attrs<StyledIconPathProps>(({ icon }) => ({
fillRule: 'evenodd',
clipRule: 'evenodd',
d: icon.svgPathData,
}))``
}))<StyledIconPathProps>``

const Input = styled.input.attrs(({ type = 'checkbox' }) => ({
type,
Expand Down Expand Up @@ -65,7 +73,9 @@ const Svg = styled.svg.attrs(({ height, width, fill }) => ({
fill,
}))``

const InputWrapper = styled.span`
type StyledInputWrapperProps = { disabled: boolean }

const InputWrapper = styled.span<StyledInputWrapperProps>`
display: inline-flex;
border-radius: 50%;
padding: ${enabled.padding};
Expand All @@ -79,7 +89,18 @@ const LabelText = styled.span`
${typographyTemplate(enabled.typography)}
`

export const Checkbox = forwardRef((props, ref) => {
type Props = {
/** Label for the checkbox */
label: string
/** If true, the checkbox will be disabled */
disabled?: boolean
/** If true, the checkbox appears indeterminate. Important! You'll have to
* set the native element to indeterminate yourself.
*/
indeterminate?: boolean
} & Omit<JSX.IntrinsicElements['input'], 'disabled'>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange syntax, need to figure out as you said 🤔


export const Checkbox = forwardRef<HTMLInputElement, Props>((props, ref) => {
const { label, disabled, indeterminate, className, ...rest } = props

const iconSize = 24
Expand All @@ -100,7 +121,7 @@ export const Checkbox = forwardRef((props, ref) => {
fill={disabled ? color.disabled : color.primary}
aria-hidden
>
<StyledPath icon={checkbox_indeterminate} />
<StyledPath icon={checkbox_indeterminate} name="indeterminate" />
</Svg>
) : (
<Svg
Expand All @@ -121,22 +142,3 @@ export const Checkbox = forwardRef((props, ref) => {
})

Checkbox.displayName = 'eds-checkbox'

Checkbox.propTypes = {
/** Label for the checkbox */
label: PropTypes.string.isRequired,
/** If true, the checkbox will be disabled */
disabled: PropTypes.bool,
/** If true, the checkbox appears indeterminate. Important! You'll have to
* set the native element to indeterminate yourself.
*/
indeterminate: PropTypes.bool,
/** Additional class names */
className: PropTypes.string,
}

Checkbox.defaultProps = {
disabled: false,
indeterminate: false,
className: undefined,
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/* eslint-disable no-undef */

import React from 'react'
import { render, cleanup, fireEvent, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-nocheck
import { tokens } from '@equinor/eds-tokens'

const {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
/* eslint camelcase: "off" */
// @ts-nocheck
import React, { forwardRef } from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import {
radio_button_selected, // eslint-disable-line camelcase
radio_button_unselected, // eslint-disable-line camelcase
} from '@equinor/eds-icons'
import type { IconData } from '@equinor/eds-icons'
import { radio as tokens } from './Radio.tokens'
import { typographyTemplate } from '../../_common/templates'

Expand Down Expand Up @@ -46,18 +45,24 @@ const Input = styled.input.attrs(({ type = 'radio' }) => ({
display: inline;
}
`
type StyledRadioProps = Pick<Props, 'disabled'>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is Pick?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typescript has a lot of nifty utility types 👌


const StyledRadio = styled.label`
const StyledRadio = styled.label<StyledRadioProps>`
display: inline-flex;
align-items: center;
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
`

const StyledPath = styled.path.attrs(({ icon }) => ({
type StyledIconPathProps = {
icon: IconData
name: string
}

const StyledPath = styled.path.attrs<StyledIconPathProps>(({ icon }) => ({
fillRule: 'evenodd',
clipRule: 'evenodd',
d: icon.svgPathData,
}))``
}))<StyledIconPathProps>``

const Svg = styled.svg.attrs(({ height, width, fill }) => ({
name: null,
Expand All @@ -71,7 +76,9 @@ const LabelText = styled.span`
${typographyTemplate(enabled.typography)}
`

const InputWrapper = styled.span`
type StyledInputWrapperProps = { disabled: boolean }

const InputWrapper = styled.span<StyledInputWrapperProps>`
display: inline-flex;
border-radius: 50%;
padding: ${enabled.padding};
Expand All @@ -80,8 +87,14 @@ const InputWrapper = styled.span`
disabled ? 'transparent' : color.hover};
}
`
type Props = {
/** Label for the radio */
label: string
/** If true, the radio button will be disabled */
disabled?: boolean
} & JSX.IntrinsicElements['input']

export const Radio = forwardRef(
export const Radio = forwardRef<HTMLInputElement, Props>(
({ label, disabled = false, className, ...rest }, ref) => {
const iconSize = 24
return (
Expand All @@ -106,17 +119,3 @@ export const Radio = forwardRef(
)

Radio.displayName = 'eds-radio'

Radio.propTypes = {
/** Label for the radio */
label: PropTypes.string.isRequired,
/** If true, the radio button will be disabled */
disabled: PropTypes.bool,
/** Additional class names */
className: PropTypes.string,
}

Radio.defaultProps = {
disabled: false,
className: undefined,
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// @ts-nocheck
import React, { forwardRef } from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { switchControl as tokens } from './Switch.tokens'
import type { Size } from './Switch.types'

const { enabled, disabled: _disabled } = tokens

type StyledProps = Pick<Props, 'disabled'>

const BaseInput = styled.input.attrs(({ type = 'checkbox' }) => ({
type,
}))`
}))<StyledProps>`
border: 0;
clip: rect(0 0 0 0);
height: 1px;
Expand Down Expand Up @@ -59,28 +60,23 @@ const DefaultInput = styled(BaseInput)`
}
`

export const Input = forwardRef(({ disabled, size, ...rest }, ref) => {
return (
<>
{size === 'small' ? (
<SmallInput {...rest} ref={ref} disabled={disabled} />
) : (
<DefaultInput {...rest} ref={ref} disabled={disabled} />
)}
</>
)
})

Input.displayName = 'eds-switch-input'
type Props = {
size?: Size
disabled?: boolean
} & React.HTMLAttributes<HTMLInputElement>

Input.propTypes = {
// If true, the component will be disabled
disabled: PropTypes.bool,
// Switch size, use the small version with caution
size: PropTypes.oneOf(['default', 'small']),
}
export const Input = forwardRef<HTMLInputElement, Props>(
({ size = 'default', ...rest }, ref) => {
return (
<>
{size === 'small' ? (
<SmallInput {...rest} ref={ref} />
) : (
<DefaultInput {...rest} ref={ref} />
)}
</>
)
},
)

Input.defaultProps = {
disabled: false,
size: 'default',
}
Input.displayName = 'eds-switch-input'
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// @ts-nocheck
import React from 'react'
import React, { ReactNode } from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { switchControl as tokens } from './Switch.tokens'
import type { Size } from './Switch.types'

const { enabled, disabled: _disabled } = tokens

const BaseInputWrapper = styled.span`
type StyledProps = Pick<Props, 'isDisabled'>

const BaseInputWrapper = styled.span<StyledProps>`
width: ${enabled.clickSize};
height: ${enabled.clickSize};
border-radius: 50%;
Expand All @@ -29,8 +31,17 @@ const InputWrapperSmall = styled(BaseInputWrapper)`
isDisabled ? 'transparent' : enabled.hover.background};
}
`
type Props = {
children: ReactNode
isDisabled?: boolean
size?: Size
}

export const InputWrapper = ({ children, isDisabled, size }) => {
export const InputWrapper = ({
children,
isDisabled,
size = 'default',
}: Props): JSX.Element => {
return (
<>
{size === 'small' ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-nocheck
import { tokens } from '@equinor/eds-tokens'

const {
Expand Down
Loading