6 changed files with 343 additions and 0 deletions
@ -0,0 +1,88 @@ |
|||||
|
import React from 'react' |
||||
|
import PropTypes from 'prop-types' |
||||
|
import { Radio as InformedRadio } from 'informed' |
||||
|
import styled from 'styled-components' |
||||
|
import { Label, Text } from 'components/UI' |
||||
|
import { Box } from 'rebass' |
||||
|
|
||||
|
const Wrapper = styled(Box)` |
||||
|
/* The container */ |
||||
|
.container { |
||||
|
display: block; |
||||
|
position: relative; |
||||
|
padding-left: 30px; |
||||
|
cursor: pointer; |
||||
|
user-select: none; |
||||
|
} |
||||
|
|
||||
|
/* Hide the browser's default radio button */ |
||||
|
.container input { |
||||
|
position: absolute; |
||||
|
opacity: 0; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
/* Create a custom radio button */ |
||||
|
.selection { |
||||
|
position: absolute; |
||||
|
top: 1px; |
||||
|
left: 0; |
||||
|
height: 16px; |
||||
|
width: 16px; |
||||
|
border: 1px solid ${props => props.theme.colors.gray}; |
||||
|
border-radius: 50%; |
||||
|
} |
||||
|
|
||||
|
/* On mouse-over, add an orange border color */ |
||||
|
.container:hover input ~ .selection { |
||||
|
border: 1px solid ${props => props.theme.colors.lightningOrange}; |
||||
|
} |
||||
|
|
||||
|
/* When the radio button is checked, make the border orange */ |
||||
|
.container input:checked ~ .selection { |
||||
|
border: 1px solid ${props => props.theme.colors.lightningOrange}; |
||||
|
} |
||||
|
|
||||
|
/* Create the indicator (the dot/circle - hidden when not checked) */ |
||||
|
.selection:after { |
||||
|
content: ''; |
||||
|
position: absolute; |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
/* Show the indicator (dot/circle) when checked */ |
||||
|
.container input:checked ~ .selection:after { |
||||
|
display: block; |
||||
|
} |
||||
|
|
||||
|
/* Style the indicator (dot/circle) */ |
||||
|
.container .selection:after { |
||||
|
top: 3px; |
||||
|
left: 3px; |
||||
|
width: 8px; |
||||
|
height: 8px; |
||||
|
border-radius: 50%; |
||||
|
background: ${props => props.theme.colors.lightningOrange}; |
||||
|
} |
||||
|
` |
||||
|
const Radio = ({ value, label, description, fontWeight, onChange, onBlur, ...rest }) => ( |
||||
|
<Wrapper> |
||||
|
<Label htmlFor={value} className="container" fontWeight="light" mb={3} {...rest}> |
||||
|
<Text>{label}</Text> |
||||
|
<InformedRadio value={value} id={value} onChange={onChange} onBlur={onBlur} /> |
||||
|
<span className="selection" /> |
||||
|
{description && ( |
||||
|
<Text mt={2} color="gray"> |
||||
|
{description} |
||||
|
</Text> |
||||
|
)} |
||||
|
</Label> |
||||
|
</Wrapper> |
||||
|
) |
||||
|
Radio.propTypes = { |
||||
|
value: PropTypes.string.isRequired, |
||||
|
label: PropTypes.node, |
||||
|
description: PropTypes.node |
||||
|
} |
||||
|
|
||||
|
export default Radio |
@ -0,0 +1,3 @@ |
|||||
|
import { RadioGroup } from 'informed' |
||||
|
|
||||
|
export default RadioGroup |
@ -0,0 +1,24 @@ |
|||||
|
import React from 'react' |
||||
|
import renderer from 'react-test-renderer' |
||||
|
import { dark } from 'themes' |
||||
|
import { ThemeProvider } from 'styled-components' |
||||
|
import { Form, Radio, RadioGroup } from 'components/UI' |
||||
|
|
||||
|
describe('component.UI.Radio', () => { |
||||
|
it('should render correctly', () => { |
||||
|
const tree = renderer |
||||
|
.create( |
||||
|
<ThemeProvider theme={dark}> |
||||
|
<Form> |
||||
|
<RadioGroup field="radio"> |
||||
|
<Radio value="item1" label="Item 1" description="Radio buttons" /> |
||||
|
<Radio value="item2" label="Item 2" description="can have an optional title" /> |
||||
|
<Radio value="item3" label="Item 3" description="and description" /> |
||||
|
</RadioGroup> |
||||
|
</Form> |
||||
|
</ThemeProvider> |
||||
|
) |
||||
|
.toJSON() |
||||
|
expect(tree).toMatchSnapshot() |
||||
|
}) |
||||
|
}) |
@ -0,0 +1,207 @@ |
|||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP |
||||
|
|
||||
|
exports[`component.UI.Radio should render correctly 1`] = ` |
||||
|
.c2 { |
||||
|
font-size: 13px; |
||||
|
color: #ffffff; |
||||
|
line-height: 1.4; |
||||
|
} |
||||
|
|
||||
|
.c3 { |
||||
|
margin-top: 8px; |
||||
|
font-size: 13px; |
||||
|
color: #959595; |
||||
|
line-height: 1.4; |
||||
|
} |
||||
|
|
||||
|
.c1 { |
||||
|
margin-bottom: 16px; |
||||
|
width: 100%; |
||||
|
font-size: 13px; |
||||
|
color: #ffffff; |
||||
|
color: #ffffff; |
||||
|
font-weight: 300; |
||||
|
display: block; |
||||
|
} |
||||
|
|
||||
|
.c0 .container { |
||||
|
display: block; |
||||
|
position: relative; |
||||
|
padding-left: 30px; |
||||
|
cursor: pointer; |
||||
|
-webkit-user-select: none; |
||||
|
-moz-user-select: none; |
||||
|
-ms-user-select: none; |
||||
|
user-select: none; |
||||
|
} |
||||
|
|
||||
|
.c0 .container input { |
||||
|
position: absolute; |
||||
|
opacity: 0; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.c0 .selection { |
||||
|
position: absolute; |
||||
|
top: 1px; |
||||
|
left: 0; |
||||
|
height: 16px; |
||||
|
width: 16px; |
||||
|
border: 1px solid #959595; |
||||
|
border-radius: 50%; |
||||
|
} |
||||
|
|
||||
|
.c0 .container:hover input ~ .selection { |
||||
|
border: 1px solid #fd9800; |
||||
|
} |
||||
|
|
||||
|
.c0 .container input:checked ~ .selection { |
||||
|
border: 1px solid #fd9800; |
||||
|
} |
||||
|
|
||||
|
.c0 .selection:after { |
||||
|
content: ''; |
||||
|
position: absolute; |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
.c0 .container input:checked ~ .selection:after { |
||||
|
display: block; |
||||
|
} |
||||
|
|
||||
|
.c0 .container .selection:after { |
||||
|
top: 3px; |
||||
|
left: 3px; |
||||
|
width: 8px; |
||||
|
height: 8px; |
||||
|
border-radius: 50%; |
||||
|
background: #fd9800; |
||||
|
} |
||||
|
|
||||
|
<form |
||||
|
className="" |
||||
|
onReset={[Function]} |
||||
|
onSubmit={[Function]} |
||||
|
> |
||||
|
<div |
||||
|
className="c0" |
||||
|
> |
||||
|
<label |
||||
|
className="container c1" |
||||
|
color="primaryText" |
||||
|
display="block" |
||||
|
fontSize="m" |
||||
|
fontWeight="light" |
||||
|
htmlFor="item1" |
||||
|
opacity={null} |
||||
|
width={1} |
||||
|
> |
||||
|
<div |
||||
|
className="c2" |
||||
|
color="primaryText" |
||||
|
fontSize="m" |
||||
|
> |
||||
|
Item 1 |
||||
|
</div> |
||||
|
<input |
||||
|
checked={false} |
||||
|
id="item1" |
||||
|
onBlur={[Function]} |
||||
|
onChange={[Function]} |
||||
|
type="radio" |
||||
|
value="item1" |
||||
|
/> |
||||
|
<span |
||||
|
className="selection" |
||||
|
/> |
||||
|
<div |
||||
|
className="c3" |
||||
|
color="gray" |
||||
|
fontSize="m" |
||||
|
> |
||||
|
Radio buttons |
||||
|
</div> |
||||
|
</label> |
||||
|
</div> |
||||
|
<div |
||||
|
className="c0" |
||||
|
> |
||||
|
<label |
||||
|
className="container c1" |
||||
|
color="primaryText" |
||||
|
display="block" |
||||
|
fontSize="m" |
||||
|
fontWeight="light" |
||||
|
htmlFor="item2" |
||||
|
opacity={null} |
||||
|
width={1} |
||||
|
> |
||||
|
<div |
||||
|
className="c2" |
||||
|
color="primaryText" |
||||
|
fontSize="m" |
||||
|
> |
||||
|
Item 2 |
||||
|
</div> |
||||
|
<input |
||||
|
checked={false} |
||||
|
id="item2" |
||||
|
onBlur={[Function]} |
||||
|
onChange={[Function]} |
||||
|
type="radio" |
||||
|
value="item2" |
||||
|
/> |
||||
|
<span |
||||
|
className="selection" |
||||
|
/> |
||||
|
<div |
||||
|
className="c3" |
||||
|
color="gray" |
||||
|
fontSize="m" |
||||
|
> |
||||
|
can have an optional title |
||||
|
</div> |
||||
|
</label> |
||||
|
</div> |
||||
|
<div |
||||
|
className="c0" |
||||
|
> |
||||
|
<label |
||||
|
className="container c1" |
||||
|
color="primaryText" |
||||
|
display="block" |
||||
|
fontSize="m" |
||||
|
fontWeight="light" |
||||
|
htmlFor="item3" |
||||
|
opacity={null} |
||||
|
width={1} |
||||
|
> |
||||
|
<div |
||||
|
className="c2" |
||||
|
color="primaryText" |
||||
|
fontSize="m" |
||||
|
> |
||||
|
Item 3 |
||||
|
</div> |
||||
|
<input |
||||
|
checked={false} |
||||
|
id="item3" |
||||
|
onBlur={[Function]} |
||||
|
onChange={[Function]} |
||||
|
type="radio" |
||||
|
value="item3" |
||||
|
/> |
||||
|
<span |
||||
|
className="selection" |
||||
|
/> |
||||
|
<div |
||||
|
className="c3" |
||||
|
color="gray" |
||||
|
fontSize="m" |
||||
|
> |
||||
|
and description |
||||
|
</div> |
||||
|
</label> |
||||
|
</div> |
||||
|
</form> |
||||
|
`; |
Loading…
Reference in new issue