From 709041cc0fd3884892d2004d05c6f69d653a3427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Vep=C5=99ek?= Date: Thu, 19 Apr 2018 19:05:23 +0200 Subject: [PATCH] Update Radio component --- src/Radio/Radio.js | 140 ++ src/Radio/Radio.stories.js | 86 + .../__snapshots__/Radio.stories.storyshot | 945 +++++++ .../RadioButton.stories.storyshot | 339 +++ .../__snapshots__/index.test.js.snap | 2186 +++++++++++++++++ src/Radio/__tests__/index.test.js | 32 + src/Radio/index.js | 6 + src/_deprecated/Radio/Radio.js | 64 - src/_deprecated/Radio/Radio.stories.js | 47 - .../__snapshots__/Radio.stories.storyshot | 155 -- src/_deprecated/Radio/__tests__/index.test.js | 33 - src/_deprecated/Radio/index.js | 8 - src/index.js | 2 +- 13 files changed, 3735 insertions(+), 308 deletions(-) create mode 100644 src/Radio/Radio.js create mode 100644 src/Radio/Radio.stories.js create mode 100644 src/Radio/__snapshots__/Radio.stories.storyshot create mode 100644 src/Radio/__snapshots__/RadioButton.stories.storyshot create mode 100644 src/Radio/__tests__/__snapshots__/index.test.js.snap create mode 100644 src/Radio/__tests__/index.test.js create mode 100644 src/Radio/index.js delete mode 100644 src/_deprecated/Radio/Radio.js delete mode 100644 src/_deprecated/Radio/Radio.stories.js delete mode 100644 src/_deprecated/Radio/__snapshots__/Radio.stories.storyshot delete mode 100644 src/_deprecated/Radio/__tests__/index.test.js delete mode 100644 src/_deprecated/Radio/index.js diff --git a/src/Radio/Radio.js b/src/Radio/Radio.js new file mode 100644 index 0000000000..f83202a1f4 --- /dev/null +++ b/src/Radio/Radio.js @@ -0,0 +1,140 @@ +// @flow +import * as React from "react"; +import styled from "styled-components"; +import defaultTokens from "@kiwicom/orbit-design-tokens"; + +type Props = {| + label: string, + value?: string, + hasError: boolean, + disabled: boolean, + checked: boolean, + info?: React.Node, + onChange: (SyntheticEvent) => void, + theme: typeof defaultTokens, +|}; + +const Glyph = styled.span` + visibility: hidden; + width: 12px; + height: 12px; + background-color: ${({ theme, disabled }) => + disabled ? theme.colorIconCheckboxDisabled : theme.colorIconCheckbox}; + border-radius: ${({ theme }) => theme.borderRadiusCircle}; +`; + +const IconContainer = styled.div` + position: relative; + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: center; + background-color: ${({ theme }) => theme.backgroundInput}; + height: ${({ theme }) => theme.heightCheckbox}; + width: ${({ theme }) => theme.widthCheckbox}; + border-radius: ${({ theme }) => theme.borderRadiusCircle}; + overflow: hidden; + border: 1px solid ${({ tokens }) => tokens.borderColor}; + transform: scale(1); + transition: all ${({ theme }) => theme.durationFast} ease-in-out; + } +`; + +const TextContainer = styled.div` + display: flex; + flex-direction: column; + margin-left: ${({ theme }) => theme.spaceXSmall}; +`; + +const Info = styled.span` + font-size: ${({ theme }) => theme.fontSizeMessageForm}; + color: ${({ theme }) => theme.paletteInkLight}; // TODO create token + line-height: ${({ theme }) => theme.lineHeightText}; +`; + +const LabelText = styled.span` + font-weight: ${({ theme }) => theme.fontWeightNormal}; + font-size: ${({ theme }) => theme.fontSizeLabelForm}; + color: ${({ theme }) => theme.colorLabelForm}; + height: ${({ theme }) => theme.heightCheckbox}; + line-height: ${({ theme }) => theme.heightCheckbox}; +`; + +const Input = styled.input` + visibility: hidden; + display: none; + + &:checked ~ ${TextContainer} > ${LabelText} { + font-weight: ${({ theme }) => theme.fontWeightMedium}; + } + + &:checked + ${IconContainer} > ${Glyph} { + visibility: visible; + } +`; + +const Label = styled(({ tokens, disabled, theme, type, ...props }) => ( + +))` + font-family: ${({ theme }) => theme.fontFamily}; + display: flex; + flex-direction: row; + align-items: self-start; + opacity: ${({ disabled, theme }) => (disabled ? theme.opacityCheckboxDisabled : "1")}; + cursor: ${({ disabled }) => (disabled ? "default" : "pointer")}; + position: relative; + + &:hover ${IconContainer} { + border-color: ${({ disabled, theme }) => + disabled ? theme.borderColorInputHover : theme.paletteInkLight}; // TODO create token + } + &:active ${IconContainer} { + border-color: ${({ disabled, theme, tokens }) => + disabled ? tokens.borderColor : theme.paletteInkNormal}; // TODO create token + transform: ${({ disabled, theme }) => !disabled && `scale(${theme.modifierScaleButtonActive})`}; + } + &:focus { + outline: 0; + & ${IconContainer} { + box-shadow: 0 0 3px ${({ theme }) => theme.paletteBlueNormal}; // TODO create token + } + } +`; + +const Radio = (props: Props) => { + const { label, value, hasError, disabled, checked, onChange, theme, info } = props; + + const tokens = { + borderColor: + hasError && !disabled && !checked ? theme.borderColorInputError : theme.borderColorInput, + }; + + return ( + + ); +}; + +Radio.defaultProps = { + hasError: false, + disabled: false, + checked: false, + theme: defaultTokens, +}; + +export default Radio; diff --git a/src/Radio/Radio.stories.js b/src/Radio/Radio.stories.js new file mode 100644 index 0000000000..c57cedbf65 --- /dev/null +++ b/src/Radio/Radio.stories.js @@ -0,0 +1,86 @@ +// @flow +import * as React from "react"; +import { storiesOf, setAddon } from "@storybook/react"; +import { action } from "@storybook/addon-actions"; +import styles from "@sambego/storybook-styles"; +import chaptersAddon from "react-storybook-addon-chapters"; +import { withKnobs, text, boolean } from "@storybook/addon-knobs/react"; + +import Radio from "./Radio"; + +setAddon(chaptersAddon); + +storiesOf("Radio", module) + .addDecorator(withKnobs) + .addDecorator( + styles({ + padding: "20px", + }), + ) + .addWithChapters("Default", () => { + const label = text("Label", "Label"); + const checked = boolean("Checked", false); + return { + info: "Radio needs only label and onChange by default.", + chapters: [ + { + sections: [ + { + sectionFn: () => ( + + ), + }, + ], + }, + ], + }; + }) + .addWithChapters("With help", () => { + const label = text("Label", "Label"); + const value = text("Value", "value"); + const info = text("Info", "Additional information to this choice"); + return { + info: "Additionally you can add info to this component.", + chapters: [ + { + sections: [ + { + sectionFn: () => ( + + ), + }, + ], + }, + ], + }; + }) + .addWithChapters("Playground", () => { + const label = text("Label", "Label"); + const value = text("Value", "value"); + const checked = boolean("Checked", true); + const disabled = boolean("Disabled", true); + const hasError = boolean("hasError", false); + const info = text("Info", "Additional information for this choice"); + return { + info: "Playground of Radio", + chapters: [ + { + sections: [ + { + sectionFn: () => ( + + ), + }, + ], + }, + ], + }; + }); diff --git a/src/Radio/__snapshots__/Radio.stories.storyshot b/src/Radio/__snapshots__/Radio.stories.storyshot new file mode 100644 index 0000000000..1d1fe85d57 --- /dev/null +++ b/src/Radio/__snapshots__/Radio.stories.storyshot @@ -0,0 +1,945 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Storyshots Radio Default 1`] = ` +
+
+
+
+

+ Default +

+ + +
+

+ Radio needs only label and onChange by default. +

+
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+ + +
+
+
+
+ +
+
+
+
+ +
+

+ Source +

+
+                  
+ + < + Radio + + + + + + label + + + = + + + " + Label + " + + + + + + + + onChange + + + = + + + { + + changed() + + } + + + + + + + + /> + +
+
+
+
+
+
+
+
+
+
+`; + +exports[`Storyshots Radio Playground 1`] = ` +
+
+
+
+

+ Playground +

+ + +
+

+ Playground of Radio +

+
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+ + +
+
+
+
+ +
+
+
+
+ +
+

+ Source +

+
+                  
+ + < + Radio + + + + +
+    +
+ + label + + + = + + + " + Label + " + + + +
+ + +
+    +
+ + value + + + = + + + " + value + " + + + +
+ + +
+    +
+ + checked + +
+ + +
+    +
+ + disabled + +
+ + +
+    +
+ + info + + + = + + + " + Additional information for this choice + " + + + +
+ + +
+    +
+ + onChange + + + = + + + { + + changed() + + } + + + +
+
+
+ + /> + +
+
+
+
+
+
+
+
+
+
+`; + +exports[`Storyshots Radio With help 1`] = ` +
+
+
+
+

+ With help +

+ + +
+

+ Additionally you can add info to this component. +

+
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+ + +
+
+
+
+ +
+
+
+
+ +
+

+ Source +

+
+                  
+ + < + Radio + + + + +
+    +
+ + label + + + = + + + " + Label + " + + + +
+ + +
+    +
+ + value + + + = + + + " + value + " + + + +
+ + +
+    +
+ + info + + + = + + + " + Additional information to this choice + " + + + +
+ + +
+    +
+ + onChange + + + = + + + { + + changed() + + } + + + +
+
+
+ + /> + +
+
+
+
+
+
+
+
+
+
+`; diff --git a/src/Radio/__snapshots__/RadioButton.stories.storyshot b/src/Radio/__snapshots__/RadioButton.stories.storyshot new file mode 100644 index 0000000000..7c9a6c2053 --- /dev/null +++ b/src/Radio/__snapshots__/RadioButton.stories.storyshot @@ -0,0 +1,339 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Storyshots RadioButton Default 1`] = ` +
+
+
+

+ Default +

+ + +
+

+ Example of RadioButton. You can change its label, name, value. +

+
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+ +

+ Checkbox +

+
+
+
+
+ +
+
+
+
+ +
+

+ Source +

+
+                
+ + < + RadioButton + + + + +
+    +
+ + label + + + = + + + " + Hello Button + " + + + +
+ + +
+    +
+ + name + + + = + + + " + name + " + + + +
+ + +
+    +
+ + value + + + = + + + " + value + " + + + +
+ + +
+    +
+ + checked + +
+ + +
+    +
+ + onChange + + + = + + + { + + changed() + + } + + + +
+
+
+ + /> + +
+
+
+
+
+
+
+
+
+`; diff --git a/src/Radio/__tests__/__snapshots__/index.test.js.snap b/src/Radio/__tests__/__snapshots__/index.test.js.snap new file mode 100644 index 0000000000..13e6403702 --- /dev/null +++ b/src/Radio/__tests__/__snapshots__/index.test.js.snap @@ -0,0 +1,2186 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Default CheckBox should match snapshot 1`] = ` + + + + + + + + Radio + + + +`; diff --git a/src/Radio/__tests__/index.test.js b/src/Radio/__tests__/index.test.js new file mode 100644 index 0000000000..ba39716246 --- /dev/null +++ b/src/Radio/__tests__/index.test.js @@ -0,0 +1,32 @@ +// @flow + +import * as React from "react"; +import { shallow } from "enzyme"; + +import Radio from "../Radio"; + +const label = "Radio"; +const onChange = jest.fn(); +const value = "option"; + +describe(`Default CheckBox`, () => { + const component = shallow(); + it("should contain a label", () => { + expect( + component + .find("Radio__LabelText") + .render() + .text(), + ).toBe(label); + }); + it("input value should match", () => { + expect(component.find("Radio__Input").prop("value")).toBe(value); + }); + it("should execute onChange method", () => { + component.find("Radio__Input").simulate("change"); + expect(onChange).toHaveBeenCalled(); + }); + it("should match snapshot", () => { + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/Radio/index.js b/src/Radio/index.js new file mode 100644 index 0000000000..bbb7f402dc --- /dev/null +++ b/src/Radio/index.js @@ -0,0 +1,6 @@ +// @flow +import { withTheme } from "theming"; + +import Radio from "./Radio"; + +export default withTheme(Radio); diff --git a/src/_deprecated/Radio/Radio.js b/src/_deprecated/Radio/Radio.js deleted file mode 100644 index 4c85416da1..0000000000 --- a/src/_deprecated/Radio/Radio.js +++ /dev/null @@ -1,64 +0,0 @@ -// @flow -import * as React from "react"; - -import Typography from "../Typography/Typography"; -import { colors } from "../../constants"; - -type Props = { - label: string, - checked?: boolean, - disabled?: boolean, - value?: string, - onChange: (SyntheticInputEvent) => any, -}; - -const Radio = (props: Props) => ( -
-