Skip to content

Commit

Permalink
add RadioButton
Browse files Browse the repository at this point in the history
  • Loading branch information
Barry127 committed Nov 18, 2020
1 parent f2b3787 commit 7aed772
Show file tree
Hide file tree
Showing 16 changed files with 906 additions and 10 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"cSpell.words": [
"Coffescript",
"Consolas",
"Don'ts",
"Dont",
Expand Down
2 changes: 1 addition & 1 deletion pages/docs/components/Form/CheckBox.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ render(<Controlled />);
CheckBoxes can be disabled.

```js live
<CheckBox checked disabled>
<CheckBox indeterminate disabled>
Disabled
</CheckBox>
```
Expand Down
7 changes: 7 additions & 0 deletions pages/docs/components/Form/Form.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ const FullForm = () => {
const [tc, setTc] = useState(false);
const [news, setNews] = useState(true);

const radioOptions = [
{ label: 'Javascript', value: 'js' },
{ label: 'Typescript', value: 'ts' },
{ label: 'Coffescript', value: 'coffee' }
];

function toggleAll() {
if (tc && news) {
setTc(false);
Expand All @@ -35,6 +41,7 @@ const FullForm = () => {
<Form onSubmit={(ev) => ev.preventDefault()}>
<TextInput label="Username" icon={user} />
<PasswordInput label="Password" icon={lock} />
<RadioGroup label="Flavour" options={radioOptions} name="flavour" />
<Toggle label="Toggle" />
<TextArea label="Comment" />
<FormField>
Expand Down
55 changes: 55 additions & 0 deletions pages/docs/components/Form/RadioButton.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Description, Meta, Props } from 'docsComponents';

<Meta title="RadioButton" />

# RadioButton

<Description of="RadioButton" />

## Props

<Props of="RadioButton" />

## Examples

### Basic

A basic usage of RadioButton.

```js live
<RadioButton>Hello World!</RadioButton>
```

### Disabled

Radio Buttons can be disabled.

```js live
<RadioButton disabled>Disabled</RadioButton>
```

### Size

Radio Buttons can have different sizes.

```js live
<Row gutter={1}>
<Col span={24}>
<RadioButton size="sm">Small</RadioButton>
</Col>
<Col span={24}>
<RadioButton size="md">Medium</RadioButton>
</Col>
<Col span={24}>
<RadioButton size="lg">Large</RadioButton>
</Col>
</Row>
```

### Error

A Radio Button can indicate it has an error.

```js live
<RadioButton hasError>Text indicating error</RadioButton>
```
128 changes: 128 additions & 0 deletions pages/docs/components/Form/RadioGroup.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { Description, Meta, Props } from 'docsComponents';

<Meta title="RadioGroup" />

# RadioGroup

<Description of="RadioGroup" />

## Props

<Props of="RadioGroup" />

## Examples

### Basic

A basic usage of RadioGroup.

```js live withRender
const options = [
{ label: 'Javascript', value: 'js' },
{ label: 'Typescript', value: 'ts' },
{ label: 'Coffescript', value: 'coffee' }
];

render(<RadioGroup name="language-1" options={options} />);
```

### Controlled

RadioGroup is designed to be used as a controlled input.

```js live withRender
const options = [
{ label: 'Javascript', value: 'js' },
{ label: 'Typescript', value: 'ts' },
{ label: 'Coffescript', value: 'coffee' }
];

const Controlled = (props) => {
const [value, setValue] = useState('ts');
return (
<>
<RadioGroup
{...props}
value={value}
onChange={(ev) => setValue(ev.target.value)}
/>
<Block>
Value: <i>{value}</i>
</Block>
</>
);
};

render(<Controlled name="language-2" options={options} />);
```

### Inline

A RadioGroup can be Inline

```js live withRender
const options = [
{ label: 'Javascript', value: 'js' },
{ label: 'Typescript', value: 'ts' },
{ label: 'Coffescript', value: 'coffee' }
];

render(<RadioGroup inline name="language" options={options} />);
```

### Disabled

Options inside a RadioGroup can be disabled.

```js live withRender
const options = [
{ label: 'Javascript', value: 'js' },
{ label: 'Typescript', value: 'ts' },
{ label: 'Coffescript', value: 'coffee', disabled: true }
];

render(<RadioGroup name="language-3" options={options} />);
```

### Size

RadioGroups can have different sizes.

```js live withRender
const options = [
{ label: 'Javascript', value: 'js' },
{ label: 'Typescript', value: 'ts' },
{ label: 'Coffescript', value: 'coffee' }
];

render(
<Row gutter={1}>
<Col span={8}>
<H4>Small</H4>
<RadioGroup size="sm" name="language-4" options={options} />
</Col>
<Col span={8}>
<H4>Medium</H4>
<RadioGroup size="md" name="language-5" options={options} />
</Col>
<Col span={8}>
<H4>Large</H4>
<RadioGroup size="lg" name="language-6" options={options} />
</Col>
</Row>
);
```

### Error

Options inside a RadioGroup can indicate to have an error.

```js live withRender
const options = [
{ label: 'Javascript', value: 'js' },
{ label: 'Typescript', value: 'ts' },
{ label: 'Coffescript', value: 'coffee', hasError: true }
];

render(<RadioGroup name="language-7" options={options} />);
```
2 changes: 2 additions & 0 deletions pages/docs/nav.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
"FormField": "/docs/components/Form/FormField",
"NativeSelect": "/docs/components/Form/NativeSelect",
"PasswordInput": "/docs/components/Form/PasswordInput",
"RadioButton": "/docs/components/Form/RadioButton",
"RadioGroup": "/docs/components/Form/RadioGroup",
"TextArea": "/docs/components/Form/TextArea",
"TextInput": "/docs/components/Form/TextInput",
"Toggle": "/docs/components/Form/Toggle",
Expand Down
16 changes: 9 additions & 7 deletions scripts/templates/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ export const ${name} = forwardRef<
HTMLDivElement,
${name}Props
>(({ children, className, ...props }, ref) => (
<div {...props} className={clsx('mvn--${dashify(name)}', classes.${dashify(
name
)}, className)} ref={ref}>
<div {...props} className={clsx('mvn--${dashify(name)}', ${
dashify(name).includes('-')
? "classes['" + dashify(name) + "']"
: 'classes.' + dashify(name)
}, className)} ref={ref}>
{children}
</div>
));
Expand Down Expand Up @@ -57,21 +59,21 @@ describe('${name}', () => {
it('sets className', () => {
render(
<${name} className="${name.toLowerCase()}-class">Hello world!</${name}>
<${name} className="${dashify(name)}-class">Hello world!</${name}>
);
const element = document.querySelector('.mvn--${dashify(name)}')
expect(element).toHaveClass('${name.toLowerCase()}-class');
expect(element).toHaveClass('${dashify(name)}-class');
});
it('passes props', () => {
render(
<${name} id="${name}Id" data-test="${name.toLowerCase()}-data">
<${name} id="${name}Id" data-test="${dashify(name)}-data">
Hello world!
</${name}>
);
const element = document.querySelector('.mvn--${dashify(name)}')
expect(element).toHaveAttribute('id', '${name}Id');
expect(element).toHaveAttribute('data-test', '${name.toLowerCase()}-data');
expect(element).toHaveAttribute('data-test', '${dashify(name)}-data');
});
it.skip('', () => {});
Expand Down
2 changes: 1 addition & 1 deletion src/components/Form/CheckBox/CheckBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export const CheckBox = forwardRef<HTMLInputElement, CheckBoxProps>(
);

export interface CheckBoxProps
extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {
extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {
/** Wether the CheckBox is checked */
checked?: boolean;

Expand Down
2 changes: 1 addition & 1 deletion src/components/Form/CheckBox/check-box.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@

&:disabled {
& + .box {
background-color: var(--mvn-color-background);
background-color: var(--mvn-grey1);
background-image: none;
pointer-events: none;

Expand Down
93 changes: 93 additions & 0 deletions src/components/Form/RadioButton/RadioButton.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { render } from '@testing-library/react';
import React, { createRef } from 'react';
import { RadioButton } from './RadioButton';

describe('RadioButton', () => {
it('renders an input radio element and sets child text', () => {
render(<RadioButton>Hello world!</RadioButton>);
const container = document.querySelector('.mvn--radio-button');
const input = document.querySelector('input');
expect(container).toBeInTheDocument();
expect(input).toBeInTheDocument();
expect(input).toHaveAttribute('type', 'radio');
expect(container).toHaveTextContent('Hello world!');
});

it('sets className', () => {
render(
<RadioButton className="radio-button-class">Hello world!</RadioButton>
);
const element = document.querySelector('.mvn--radio-button');
expect(element).toHaveClass('radio-button-class');
});

it('passes props', () => {
render(
<RadioButton id="RadioButtonId" data-test="radio-button-data">
Hello world!
</RadioButton>
);
const element = document.querySelector('input');
expect(element).toHaveAttribute('id', 'RadioButtonId');
expect(element).toHaveAttribute('data-test', 'radio-button-data');
});

describe('disabled', () => {
it('is not disabled by default', () => {
render(<RadioButton />);
const input = document.querySelector('input');
expect(input).not.toHaveAttribute('disabled');
});

it('sets disabled', () => {
render(<RadioButton disabled />);
const input = document.querySelector('input');
expect(input).toHaveAttribute('disabled');
});
});

describe('hasError', () => {
it('has no error styling by default', () => {
render(<RadioButton />);
const container = document.querySelector('.mvn--radio-button');
expect(container).not.toHaveClass('has-error');
});

it('sets error styling', () => {
render(<RadioButton hasError>Error Text</RadioButton>);
const container = document.querySelector('.mvn--radio-button');
expect(container).toHaveClass('has-error');
});
});

describe('size', () => {
it('is md by default', () => {
render(<RadioButton />);
const container = document.querySelector('.mvn--radio-button');
expect(container).toHaveClass('md');
expect(container).not.toHaveClass('sm');
expect(container).not.toHaveClass('lg');
});

it('sets sm', () => {
render(<RadioButton size="sm" />);
const container = document.querySelector('.mvn--radio-button');
expect(container).toHaveClass('sm');
});

it('sets lg', () => {
render(<RadioButton size="lg" />);
const container = document.querySelector('.mvn--radio-button');
expect(container).toHaveClass('lg');
});
});

describe('forwarding ref', () => {
it('sets ref', () => {
const ref = createRef<HTMLInputElement>();
render(<RadioButton ref={ref} />);
const element = document.querySelector('input');
expect(ref.current).toBe(element);
});
});
});
Loading

0 comments on commit 7aed772

Please sign in to comment.