-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #35 from kodiak-packages/31-radio-button
Create Radio button
- Loading branch information
Showing
23 changed files
with
640 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.countryCode { | ||
width: 50px; | ||
} | ||
|
||
.countryCode input { | ||
text-align: center; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
--- | ||
name: Radio | ||
menu: Components | ||
route: /radio | ||
--- | ||
|
||
import { Playground, Props } from 'docz' | ||
import { Radio, Loader } from '../../index.ts' | ||
|
||
import reactImage from './docAssets/react.png' | ||
import dockerImage from './docAssets/docker.png' | ||
import pythonImage from './docAssets/python.png' | ||
|
||
# Radio | ||
|
||
## Examples | ||
|
||
### Basic usage | ||
|
||
Radio buttons are made up of two components working together. The `Radio.Group` and `Radio.Item` component. | ||
|
||
The `Radio.Group` component controls the name of the radio buttons and the onChange event. Each `Radio.Group` name property should be unique. The `Radio.Item` componet contains the value and label of the radio buttons. You add one `Radio.Item` per option. | ||
|
||
The `Radio.Item` component must be wrapped in a `Radio.Group` component to function properly. | ||
|
||
<Playground> | ||
<Radio.Group name="classes1" defaultValue="react"> | ||
<Radio.Item value="react" label="Introduction To React" /> | ||
<br /> | ||
<Radio.Item value="docker" label="Introduction To Docker" /> | ||
<br /> | ||
<Radio.Item value="python" label="Introduction To Python" /> | ||
</Radio.Group> | ||
</Playground> | ||
|
||
### Custom label with Icon | ||
|
||
The label property on the button component also accepts JSX. This allows you to display custom components in the radio button label, like icons. | ||
|
||
<Playground> | ||
<Radio.Group name="classes2" defaultValue="react"> | ||
<Radio.Item value="react" label={<React.Fragment><img src={reactImage} style={{ height: '20px', marginRight: '6px'}} />Introduction To React</React.Fragment>} /> | ||
<br /> | ||
<Radio.Item value="docker" label={<React.Fragment><img src={dockerImage} style={{ height: '20px', marginRight: '6px'}} />Introduction To Docker</React.Fragment>}/> | ||
<br /> | ||
<Radio.Item value="python" label={<React.Fragment><img src={pythonImage} style={{ height: '20px', marginRight: '6px'}} />Introduction To Python</React.Fragment>} /> | ||
</Radio.Group> | ||
</Playground> | ||
|
||
### Radio item with description | ||
|
||
<Playground> | ||
<Radio.Group name="classes3" defaultValue="react"> | ||
<Radio.Item value="react" label="Introduction To React" description="This course is for React newbies and anyone looking to build a solid foundation. It’s designed to teach you everything you need to start building web applications in React right away."/> | ||
<br /> | ||
<Radio.Item value="docker" label="Introduction To Docker" description="In this course we will take a simple Node.js app that connects to a MongoDB database and uses an Express web server, and how to properly “Dockerize” the app."/> | ||
<br /> | ||
<Radio.Item value="python" label="Introduction To Python" description="At the end of this course, you’ll have a great working knowledge of Python, fully capable of creating your own Python projects from scratch or jumping into an existing application."/> | ||
</Radio.Group> | ||
</Playground> | ||
|
||
### Disabled radio items | ||
|
||
<Playground> | ||
<Radio.Group name="classes4" defaultValue="react"> | ||
<Radio.Item isDisabled value="react" label="Introduction To React" description="This course is for React newbies and anyone looking to build a solid foundation. It’s designed to teach you everything you need to start building web applications in React right away."/> | ||
<br /> | ||
<Radio.Item isDisabled value="docker" label="Introduction To Docker" description="In this course we will take a simple Node.js app that connects to a MongoDB database and uses an Express web server, and how to properly “Dockerize” the app."/> | ||
<br /> | ||
<Radio.Item isDisabled value="python" label="Introduction To Python" description="At the end of this course, you’ll have a great working knowledge of Python, fully capable of creating your own Python projects from scratch or jumping into an existing application."/> | ||
</Radio.Group> | ||
</Playground> | ||
|
||
## API | ||
|
||
### Radio Group | ||
|
||
<Props of={Radio.Group} /> | ||
|
||
### Radio Item | ||
|
||
<Props of={Radio.Item} /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import React from 'react'; | ||
import { fireEvent, render } from '@testing-library/react'; | ||
|
||
import Radio from './Radio'; | ||
|
||
describe('Radio', () => { | ||
test('default snapshot', () => { | ||
const component = ( | ||
<Radio.Group name="default" defaultValue="test1"> | ||
<Radio.Item value="test1" label="Test option 1" /> | ||
<Radio.Item value="test2" label="Test option 2" /> | ||
<Radio.Item value="test3" label="Test option 3" /> | ||
</Radio.Group> | ||
); | ||
const { asFragment } = render(component); | ||
expect(asFragment()).toMatchSnapshot(); | ||
}); | ||
|
||
test('description snapshot', () => { | ||
const component = ( | ||
<Radio.Group name="default" defaultValue="test1"> | ||
<Radio.Item value="test1" label="Test option 1" description="Lalalalalalala" /> | ||
<Radio.Item value="test2" label="Test option 2" description="Lololololololo" /> | ||
<Radio.Item value="test3" label="Test option 3" description="Lelelelelelele" /> | ||
</Radio.Group> | ||
); | ||
const { asFragment } = render(component); | ||
expect(asFragment()).toMatchSnapshot(); | ||
}); | ||
|
||
test('onChange should trigger correctly', () => { | ||
const onChangeFn = jest.fn(); | ||
|
||
const component = ( | ||
<Radio.Group name="default" defaultValue="test1" onChange={onChangeFn}> | ||
<Radio.Item value="test1" label="Test option 1" /> | ||
<Radio.Item value="test2" label="Test option 2" /> | ||
<Radio.Item value="test3" label="Test option 3" /> | ||
</Radio.Group> | ||
); | ||
const { getByTestId } = render(component); | ||
|
||
const radioButton1 = getByTestId('radio-default-test1'); | ||
const radioButton2 = getByTestId('radio-default-test2'); | ||
const radioButton3 = getByTestId('radio-default-test3'); | ||
fireEvent.click(radioButton1); | ||
fireEvent.click(radioButton2); | ||
fireEvent.click(radioButton3); | ||
fireEvent.click(radioButton3); | ||
fireEvent.click(radioButton2); | ||
fireEvent.click(radioButton1); | ||
|
||
expect(onChangeFn).toHaveBeenCalledTimes(4); | ||
}); | ||
|
||
test('disabled should block onChange', () => { | ||
const onChangeFn = jest.fn(); | ||
|
||
const component = ( | ||
<Radio.Group name="default" defaultValue="test1" onChange={onChangeFn}> | ||
<Radio.Item isDisabled value="test1" label="Test option 1" /> | ||
<Radio.Item isDisabled value="test2" label="Test option 2" /> | ||
<Radio.Item isDisabled value="test3" label="Test option 3" /> | ||
</Radio.Group> | ||
); | ||
const { getByTestId } = render(component); | ||
|
||
const radioButton1 = getByTestId('radio-default-test1'); | ||
const radioButton2 = getByTestId('radio-default-test2'); | ||
const radioButton3 = getByTestId('radio-default-test3'); | ||
fireEvent.click(radioButton1); | ||
fireEvent.click(radioButton2); | ||
fireEvent.click(radioButton3); | ||
|
||
expect(onChangeFn).toHaveBeenCalledTimes(0); | ||
}); | ||
|
||
test('className prop', () => { | ||
const className = 'center'; | ||
const component = ( | ||
<Radio.Group name="default" defaultValue="test1"> | ||
<Radio.Item className={className} value="test1" label="Test option 1" /> | ||
<Radio.Item value="test2" label="Test option 2" /> | ||
<Radio.Item value="test3" label="Test option 3" /> | ||
</Radio.Group> | ||
); | ||
const { getByTestId } = render(component); | ||
const containerElement = getByTestId('default-test1-container'); | ||
|
||
const renderedClassNames = containerElement.className.split(' '); | ||
expect(renderedClassNames).toContain(className); | ||
// className in prop should be the last in the row | ||
expect(renderedClassNames.indexOf(className)).toBe(renderedClassNames.length - 1); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import RadioGroup from './RadioGroup/RadioGroup'; | ||
import RadioItem from './RadioItem/RadioItem'; | ||
|
||
export default { Group: RadioGroup, Item: RadioItem }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import React, { useState } from 'react'; | ||
|
||
export interface RadioContext { | ||
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void; | ||
selectedValue: string; | ||
groupRef?: React.Ref<HTMLInputElement>; | ||
name: string; | ||
} | ||
|
||
export interface Props { | ||
children: React.ReactNode; | ||
defaultValue: RadioContext['selectedValue']; | ||
name: string; | ||
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void; | ||
groupRef?: React.Ref<HTMLInputElement>; | ||
} | ||
|
||
export const radioContext = React.createContext<RadioContext | null>(null); | ||
|
||
const RadioGroup: React.FC<Props> = ({ | ||
children, | ||
defaultValue, | ||
onChange, | ||
name, | ||
groupRef, | ||
}: Props) => { | ||
const [selectedValue, setSelectedValue] = useState(defaultValue); | ||
|
||
const onRadioItemChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
setSelectedValue(e.target.value); | ||
if (onChange) { | ||
onChange(e); | ||
} | ||
}; | ||
|
||
return ( | ||
<radioContext.Provider value={{ selectedValue, onChange: onRadioItemChange, name, groupRef }}> | ||
{children} | ||
</radioContext.Provider> | ||
); | ||
}; | ||
|
||
export default RadioGroup; |
Oops, something went wrong.