From d83b533b5b623c1449cea46fa62ffff9d11b7ff5 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Tue, 3 Sep 2019 17:40:59 -0400 Subject: [PATCH] feat(togglebox): adds ToggleBox component --- package-lock.json | 41 +- packages/card/README.md | 3 + packages/card/components/ButtonCard.tsx | 62 ++ packages/card/components/Card.tsx | 21 +- packages/card/index.ts | 1 + packages/card/stories/ButtonCard.stories.tsx | 26 + packages/card/style.ts | 79 +- packages/card/tests/ButtonCard.test.tsx | 50 + .../__snapshots__/ButtonCard.test.tsx.snap | 203 ++++ .../tests/__snapshots__/Card.test.tsx.snap | 6 +- packages/index.ts | 3 +- packages/toggleBox/README.md | 11 + packages/toggleBox/components/ToggleBox.tsx | 31 + .../toggleBox/components/ToggleBoxGroup.tsx | 89 ++ packages/toggleBox/index.ts | 2 + .../toggleBox/stories/ToggleBox.stories.tsx | 53 + .../stories/ToggleBoxGroup.stories.tsx | 163 +++ .../helpers/ToggleBoxGroupStoryHelper.tsx | 42 + .../stories/helpers/ToggleBoxStoryHelper.tsx | 42 + packages/toggleBox/tests/ToggleBox.test.tsx | 56 + .../toggleBox/tests/ToggleBoxGroup.test.tsx | 94 ++ .../__snapshots__/ToggleBox.test.tsx.snap | 290 ++++++ .../ToggleBoxGroup.test.tsx.snap | 963 ++++++++++++++++++ packages/toggleWrapper/README.md | 3 + .../components/ToggleWrapper.tsx | 102 ++ packages/toggleWrapper/index.ts | 1 + .../stories/ToggleWrapper.stories.tsx | 29 + .../tests/ToggleWrapper.test.tsx | 56 + .../__snapshots__/ToggleWrapper.test.tsx.snap | 81 ++ 29 files changed, 2560 insertions(+), 43 deletions(-) create mode 100644 packages/card/components/ButtonCard.tsx create mode 100644 packages/card/stories/ButtonCard.stories.tsx create mode 100644 packages/card/tests/ButtonCard.test.tsx create mode 100644 packages/card/tests/__snapshots__/ButtonCard.test.tsx.snap create mode 100644 packages/toggleBox/README.md create mode 100644 packages/toggleBox/components/ToggleBox.tsx create mode 100644 packages/toggleBox/components/ToggleBoxGroup.tsx create mode 100644 packages/toggleBox/index.ts create mode 100644 packages/toggleBox/stories/ToggleBox.stories.tsx create mode 100644 packages/toggleBox/stories/ToggleBoxGroup.stories.tsx create mode 100644 packages/toggleBox/stories/helpers/ToggleBoxGroupStoryHelper.tsx create mode 100644 packages/toggleBox/stories/helpers/ToggleBoxStoryHelper.tsx create mode 100644 packages/toggleBox/tests/ToggleBox.test.tsx create mode 100644 packages/toggleBox/tests/ToggleBoxGroup.test.tsx create mode 100644 packages/toggleBox/tests/__snapshots__/ToggleBox.test.tsx.snap create mode 100644 packages/toggleBox/tests/__snapshots__/ToggleBoxGroup.test.tsx.snap create mode 100644 packages/toggleWrapper/README.md create mode 100644 packages/toggleWrapper/components/ToggleWrapper.tsx create mode 100644 packages/toggleWrapper/index.ts create mode 100644 packages/toggleWrapper/stories/ToggleWrapper.stories.tsx create mode 100644 packages/toggleWrapper/tests/ToggleWrapper.test.tsx create mode 100644 packages/toggleWrapper/tests/__snapshots__/ToggleWrapper.test.tsx.snap diff --git a/package-lock.json b/package-lock.json index f8c1a8250..5c00ba9a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12677,8 +12677,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -12699,14 +12698,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -12721,20 +12718,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -12851,8 +12845,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -12864,7 +12857,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -12879,7 +12871,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -12887,14 +12878,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -12913,7 +12902,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -12994,8 +12982,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -13007,7 +12994,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -13093,8 +13079,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -13130,7 +13115,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -13150,7 +13134,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -13194,14 +13177,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, diff --git a/packages/card/README.md b/packages/card/README.md index 8c7f174af..6a379ec60 100644 --- a/packages/card/README.md +++ b/packages/card/README.md @@ -3,3 +3,6 @@ Cards are used to visually group related content. Cards can be used to make it e ## Aspect ratio Sometimes we want a card's size to obey a specific aspect ratio. When an aspect ratio is defined, the card's width and height will always follow that proportion unless the content is too high: in which case the card's height will increase. + +## ButtonCard +A `ButtonCard` component is used to render a card that a user can interact with. It has all of the same properties as a `Card` component, but can also appear in an "on", "off", or "disabled" state. diff --git a/packages/card/components/ButtonCard.tsx b/packages/card/components/ButtonCard.tsx new file mode 100644 index 000000000..f8b98b5bf --- /dev/null +++ b/packages/card/components/ButtonCard.tsx @@ -0,0 +1,62 @@ +import Card, { CardProps } from "./Card"; +import { + buttonCard, + buttonCardActive, + buttonCardDisabled, + buttonCardDisabledActive, + buttonCardFocused, + buttonCardFocusedActive +} from "../style"; +import { cx } from "emotion"; + +export interface ButtonCardProps extends CardProps { + /** + * Whether the component should look and act like a disabled element + */ + disabled?: boolean; + /** + * Whether the component is in the "on" state + */ + isActive?: boolean; + /** + * Whether the component is controlled by a checkbox or radio input + */ + isInput?: boolean; + /** + * Whether the component's child input has focus + */ + hasFocus?: boolean; +} + +class ButtonCard extends Card { + public render() { + const { isActive, isInput, disabled, hasFocus, ...other } = this.props; + const tabIndex = disabled ? -1 : 0; + const buttonProps = !isInput + ? { + tabIndex, + role: "button", + "aria-disabled": disabled, + "aria-pressed": isActive + } + : {}; + const buttonCardProps = { + ...{ "data-cy": "buttonCard" }, + ...buttonProps, + ...other + }; + + return this.getCardElement( + buttonCardProps, + cx(buttonCard, { + [buttonCardActive]: isActive, + [buttonCardDisabled]: disabled, + [buttonCardDisabledActive]: disabled && isActive, + [buttonCardFocused]: hasFocus, + [buttonCardFocusedActive]: hasFocus && isActive + }) + ); + } +} + +export default ButtonCard; diff --git a/packages/card/components/Card.tsx b/packages/card/components/Card.tsx index 402625d93..9fab7a205 100644 --- a/packages/card/components/Card.tsx +++ b/packages/card/components/Card.tsx @@ -1,10 +1,10 @@ import * as React from "react"; -import { style } from "../style"; +import { cardBase } from "../style"; import { cx } from "emotion"; import { preserveAspectRatio, padding } from "../../shared/styles/styleUtils"; import { SpaceSize } from "../../shared/styles/styleUtils/modifiers/modifierUtils"; -export interface CardProps { +export interface CardProps extends React.HTMLProps { /** * `[width, height]` Keeps the card's width and height at a specific proportion. e.g.: 2:1 would be [2, 1] */ @@ -16,19 +16,30 @@ export interface CardProps { children?: React.ReactNode | string; } -class Card extends React.PureComponent { +class Card

extends React.PureComponent< + P, + S +> { public static defaultProps: Partial = { paddingSize: "m" }; public render() { - const { children, aspectRatio, paddingSize } = this.props; + return this.getCardElement(this.props); + } + + protected getCardElement(cardProps: CardProps, additionalClasses?: string) { + const { children, aspectRatio, paddingSize, ...other } = cardProps; const aspectRatioStyle = aspectRatio ? preserveAspectRatio(aspectRatio[0], aspectRatio[1]) : null; return ( -

+
{children}
); diff --git a/packages/card/index.ts b/packages/card/index.ts index cb57db57f..a4f158160 100644 --- a/packages/card/index.ts +++ b/packages/card/index.ts @@ -1 +1,2 @@ export { default as Card } from "./components/Card"; +export { default as ButtonCard } from "./components/ButtonCard"; diff --git a/packages/card/stories/ButtonCard.stories.tsx b/packages/card/stories/ButtonCard.stories.tsx new file mode 100644 index 000000000..9c3fc1264 --- /dev/null +++ b/packages/card/stories/ButtonCard.stories.tsx @@ -0,0 +1,26 @@ +import * as React from "react"; +import { storiesOf } from "@storybook/react"; +import { withReadme } from "storybook-readme"; +import { action } from "@storybook/addon-actions"; +import ButtonCard from "../components/ButtonCard"; +import { SpacingBox } from "../../styleUtils/modifiers"; + +const readme = require("../README.md"); + +storiesOf("Card/ButtonCard", module) + .addDecorator(withReadme([readme])) + .add("default", () => default) + .add("active", () => isActive) + .add("disabled", () => ( + + + disabled + + + disabled + isActive + + + )) + .add("with onClick", () => ( + default + )); diff --git a/packages/card/style.ts b/packages/card/style.ts index 5e29e819a..6f5892f80 100644 --- a/packages/card/style.ts +++ b/packages/card/style.ts @@ -1,13 +1,84 @@ import { css } from "emotion"; -import { border, borderRadius } from "../shared/styles/styleUtils/index"; -import { themeBgPrimary } from "../design-tokens/build/js/designTokens"; +import { borderRadius } from "../shared/styles/styleUtils/index"; +import { + themeBgPrimary, + themeBorder, + themeBrandPrimary, + themeBgDisabled, + themeTextColorDisabled, + themeBgHover +} from "../design-tokens/build/js/designTokens"; -export const style = css` +export const cardBase = css` background-color: ${themeBgPrimary}; - ${border("all")}; + box-shadow: 0 0 0 1px ${themeBorder}; ${borderRadius("default")}; > div { height: 100%; } `; + +const buttonCardFocusStyles = ` + box-shadow: 0 0 0 1px ${themeBrandPrimary}; + outline: 0; +`; + +const buttonCardActiveStyles = ` + box-shadow: 0 0 0 2px ${themeBrandPrimary}; +`; + +const buttonCardFocusedActiveStyles = `background-color: ${themeBgHover};`; + +export const buttonCard = css` + cursor: pointer; + + &:hover, + &:focus { + ${buttonCardFocusStyles}; + } + + &:active { + ${buttonCardActiveStyles}; + } +`; + +export const buttonCardActive = css` + &, + &:hover, + &:focus { + ${buttonCardActiveStyles}; + } + + &:focus { + ${buttonCardFocusedActiveStyles}; + } +`; + +export const buttonCardFocused = css` + ${buttonCardFocusStyles}; +`; + +export const buttonCardDisabled = css` + background-color: ${themeBgDisabled}; + color: ${themeTextColorDisabled}; + cursor: auto; + + &, + &:hover, + &:focus { + box-shadow: 0 0 0 0 transparent; + } +`; + +export const buttonCardDisabledActive = css` + &, + &:hover, + &:focus { + box-shadow: 0 0 0 2px ${themeBorder}; + } +`; + +export const buttonCardFocusedActive = css` + ${buttonCardFocusedActiveStyles}; +`; diff --git a/packages/card/tests/ButtonCard.test.tsx b/packages/card/tests/ButtonCard.test.tsx new file mode 100644 index 000000000..f4c37d762 --- /dev/null +++ b/packages/card/tests/ButtonCard.test.tsx @@ -0,0 +1,50 @@ +import React from "react"; +import { mount } from "enzyme"; +import * as emotion from "emotion"; +import { createSerializer } from "jest-emotion"; +import toJson from "enzyme-to-json"; + +import { ButtonCard } from "../"; + +expect.addSnapshotSerializer(createSerializer(emotion)); + +describe("ButtonCard", () => { + it("renders default", () => { + const component = mount(default); + + expect(toJson(component)).toMatchSnapshot(); + }); + it("renders as isActive", () => { + const component = mount(default); + + expect(toJson(component)).toMatchSnapshot(); + }); + it("renders as disabled", () => { + const component = mount(default); + + expect(toJson(component)).toMatchSnapshot(); + }); + it("renders as hasFocus", () => { + const component = mount(default); + + expect(toJson(component)).toMatchSnapshot(); + }); + it("does not pass accessibility props if isInput is true", () => { + const accessibilityProps = [ + "tabIndex", + "role", + "aria-disabled", + "aria-pressed" + ]; + const component = mount(default); + const buttonCardNodeProps = component + .find("[data-cy='buttonCard']") + .props(); + const propKeys = Object.keys(buttonCardNodeProps).map(key => key); + + accessibilityProps.forEach(prop => { + expect(propKeys.includes(prop)).toBe(false); + }); + // expect(toJson(component)).toMatchSnapshot(); + }); +}); diff --git a/packages/card/tests/__snapshots__/ButtonCard.test.tsx.snap b/packages/card/tests/__snapshots__/ButtonCard.test.tsx.snap new file mode 100644 index 000000000..e5ea95fb5 --- /dev/null +++ b/packages/card/tests/__snapshots__/ButtonCard.test.tsx.snap @@ -0,0 +1,203 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ButtonCard renders as disabled 1`] = ` +.emotion-0 { + padding: 16px; +} + +.emotion-1 { + background-color: var(--themeBgPrimary,#FFFFFF); + box-shadow: 0 0 0 1px var(--themeBorder,#DADDE2); + border-radius: 6px; + cursor: pointer; + background-color: var(--themeBgDisabled,#E8EAED); + color: var(--themeTextColorDisabled,#AEB0B4); + cursor: auto; +} + +.emotion-1 > div { + height: 100%; +} + +.emotion-1:hover, +.emotion-1:focus { + box-shadow: 0 0 0 1px var(--themeBrandPrimary,#7D58FF); + outline: 0; +} + +.emotion-1:active { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-1, +.emotion-1:hover, +.emotion-1:focus { + box-shadow: 0 0 0 0 transparent; +} + + +
+
+ default +
+
+
+`; + +exports[`ButtonCard renders as hasFocus 1`] = ` +.emotion-0 { + padding: 16px; +} + +.emotion-1 { + background-color: var(--themeBgPrimary,#FFFFFF); + box-shadow: 0 0 0 1px var(--themeBorder,#DADDE2); + border-radius: 6px; + cursor: pointer; + box-shadow: 0 0 0 1px var(--themeBrandPrimary,#7D58FF); + outline: 0; +} + +.emotion-1 > div { + height: 100%; +} + +.emotion-1:hover, +.emotion-1:focus { + box-shadow: 0 0 0 1px var(--themeBrandPrimary,#7D58FF); + outline: 0; +} + +.emotion-1:active { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + + +
+
+ default +
+
+
+`; + +exports[`ButtonCard renders as isActive 1`] = ` +.emotion-0 { + padding: 16px; +} + +.emotion-1 { + background-color: var(--themeBgPrimary,#FFFFFF); + box-shadow: 0 0 0 1px var(--themeBorder,#DADDE2); + border-radius: 6px; + cursor: pointer; +} + +.emotion-1 > div { + height: 100%; +} + +.emotion-1:hover, +.emotion-1:focus { + box-shadow: 0 0 0 1px var(--themeBrandPrimary,#7D58FF); + outline: 0; +} + +.emotion-1:active { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-1, +.emotion-1:hover, +.emotion-1:focus { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-1:focus { + background-color: var(--themeBgHover,#F7F8F9); +} + + +
+
+ default +
+
+
+`; + +exports[`ButtonCard renders default 1`] = ` +.emotion-1 { + background-color: var(--themeBgPrimary,#FFFFFF); + box-shadow: 0 0 0 1px var(--themeBorder,#DADDE2); + border-radius: 6px; + cursor: pointer; +} + +.emotion-1 > div { + height: 100%; +} + +.emotion-1:hover, +.emotion-1:focus { + box-shadow: 0 0 0 1px var(--themeBrandPrimary,#7D58FF); + outline: 0; +} + +.emotion-1:active { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-0 { + padding: 16px; +} + + +
+
+ default +
+
+
+`; diff --git a/packages/card/tests/__snapshots__/Card.test.tsx.snap b/packages/card/tests/__snapshots__/Card.test.tsx.snap index d2e3fc51e..02700f2bd 100644 --- a/packages/card/tests/__snapshots__/Card.test.tsx.snap +++ b/packages/card/tests/__snapshots__/Card.test.tsx.snap @@ -2,7 +2,7 @@ exports[`Card default 1`] = `
( + + {({ isActive, hasFocus }) => ( + + {children} + + )} + +); + +export default ToggleBox; diff --git a/packages/toggleBox/components/ToggleBoxGroup.tsx b/packages/toggleBox/components/ToggleBoxGroup.tsx new file mode 100644 index 000000000..eab0e869f --- /dev/null +++ b/packages/toggleBox/components/ToggleBoxGroup.tsx @@ -0,0 +1,89 @@ +import * as React from "react"; +import shortid from "shortid"; +import { ToggleBoxProps } from "./ToggleBox"; +import { Flex, FlexItem } from "../../styleUtils/layout"; +import { BreakpointConfig } from "../../shared/styles/breakpoints"; +import { SpaceSize } from "../../shared/styles/styleUtils/modifiers/modifierUtils"; + +type FlexDirection = BreakpointConfig; + +export interface ToggleBoxGroupProps { + children: Array>; + /** + * The unique identifier for a collection of ToggleBoxes + */ + id?: string; + /** + * The direction the `ToggleBox` children are laid out in. Can be set for all viewport sizes, or configured to have different values at different viewport width breakpoints + */ + direction?: FlexDirection; + /** + * The size of the space between each `ToggleBox` child. Can be set for all viewport sizes, or configured to have different values at different viewport width breakpoints + */ + gutterSize?: SpaceSize; + /** + * Whether multiple ToggleBoxes can be selected + */ + multiSelect?: boolean; + /** + * An array of selected ToggleBox values + */ + selectedItems?: string[]; + /** + * Callback for when a user makes a selection. Passes an array selected ToggleBox values as a parameter + */ + onChange?: (selectedItems: string[]) => void; +} + +const ToggleBoxGroup = ({ + children, + direction = "row" as FlexDirection, + gutterSize = "m" as SpaceSize, + id = shortid.generate(), + multiSelect, + onChange, + selectedItems = [] +}: ToggleBoxGroupProps) => { + const getSelectedItems = (value, checked) => { + if (checked) { + return multiSelect ? [...selectedItems, value] : [value]; + } + + return selectedItems.filter(selectedChoice => selectedChoice !== value); + }; + + const toggleBoxes = () => + (React.Children.toArray(children) as Array< + React.ReactElement + >).map(toggleBox => { + const { name, value, ...childOther } = toggleBox.props; + const handleChange = e => { + if (onChange) { + onChange(getSelectedItems(value, e.target.checked)); + } + }; + + delete childOther.onChange; + + return ( + + {React.cloneElement(toggleBox, { + name: !multiSelect ? name || id : name, + type: multiSelect ? "checkbox" : "radio", + onChange: handleChange, + isActive: selectedItems.includes(value), + id: childOther.id, + value, + ...childOther + })} + + ); + }); + return ( + + {toggleBoxes()} + + ); +}; + +export default ToggleBoxGroup; diff --git a/packages/toggleBox/index.ts b/packages/toggleBox/index.ts new file mode 100644 index 000000000..e4f7d8a0d --- /dev/null +++ b/packages/toggleBox/index.ts @@ -0,0 +1,2 @@ +export { default as ToggleBox } from "./components/ToggleBox"; +export { default as ToggleBoxGroup } from "./components/ToggleBoxGroup"; diff --git a/packages/toggleBox/stories/ToggleBox.stories.tsx b/packages/toggleBox/stories/ToggleBox.stories.tsx new file mode 100644 index 000000000..be03d0cb7 --- /dev/null +++ b/packages/toggleBox/stories/ToggleBox.stories.tsx @@ -0,0 +1,53 @@ +import * as React from "react"; +import { storiesOf } from "@storybook/react"; +import { withReadme } from "storybook-readme"; +import { ToggleBox } from "../index"; +import ToggleBoxStoryHelper from "./helpers/ToggleBoxStoryHelper"; + +const readme = require("../README.md"); + +storiesOf("Forms/ToggleBox", module) + .addDecorator(withReadme([readme])) + .add("default", () => ( + + {({ isActive, changeHandler }) => ( + + default + + )} + + )) + .add("isActive", () => ( + + {({ isActive, changeHandler }) => ( + + isActive + + )} + + )) + .add("disabled", () => ( + + {({ isActive, changeHandler }) => ( + + disabled + + )} + + )); diff --git a/packages/toggleBox/stories/ToggleBoxGroup.stories.tsx b/packages/toggleBox/stories/ToggleBoxGroup.stories.tsx new file mode 100644 index 000000000..27b3cd14d --- /dev/null +++ b/packages/toggleBox/stories/ToggleBoxGroup.stories.tsx @@ -0,0 +1,163 @@ +import * as React from "react"; +import { storiesOf } from "@storybook/react"; +import { withReadme } from "storybook-readme"; +import { withKnobs, select } from "@storybook/addon-knobs"; +import { ToggleBox, ToggleBoxGroup } from "../index"; +import ToggleBoxGroupStoryHelper from "./helpers/ToggleBoxGroupStoryHelper"; +import { SpaceSize } from "../../shared/styles/styleUtils/modifiers/modifierUtils"; + +const readme = require("../README.md"); + +storiesOf("Forms/ToggleBoxGroup", module) + .addDecorator(withReadme([readme])) + .addDecorator(withKnobs) + .add("default", () => ( + + {({ changeHandler, selectedItems }) => ( + + + Exosphere + + + Thermosphere + + + Mesosphere + + + )} + + )) + .add("multiSelect", () => ( + + {({ changeHandler, selectedItems }) => ( + + + Exosphere + + + Thermosphere + + + Mesosphere + + + )} + + )) + .add("with selectedItems", () => ( + + {({ changeHandler, selectedItems }) => ( + + + Exosphere + + + Thermosphere + + + Mesosphere + + + )} + + )) + .add( + "custom direction", + () => { + const directions = { + column: "column", + row: "row", + columnReverse: "column-reverse", + rowReverse: "row-reverse" + }; + const direction = select("directions", directions, "column"); + + return ( + + {({ changeHandler, selectedItems }) => ( + + + Exosphere + + + Thermosphere + + + Mesosphere + + + )} + + ); + }, + { + info: { + text: + "Use the knobs panel to customize the direction that the ToggleBoxes are laid out" + } + } + ) + .add( + "custom gutter size", + () => { + const gutterSizes = { + xxs: "xxs", + xs: "xs", + s: "s", + m: "m", + l: "l", + xl: "xl", + xxl: "xxl", + none: "none" + }; + const gutterSize = select("gutterSizes", gutterSizes, "xl"); + + return ( + + {({ changeHandler, selectedItems }) => ( + + + Exosphere + + + Thermosphere + + + Mesosphere + + + )} + + ); + }, + { + info: { + text: "Use the knobs panel to customize the spacing between ToggleBoxes" + } + } + ); diff --git a/packages/toggleBox/stories/helpers/ToggleBoxGroupStoryHelper.tsx b/packages/toggleBox/stories/helpers/ToggleBoxGroupStoryHelper.tsx new file mode 100644 index 000000000..798e00d6b --- /dev/null +++ b/packages/toggleBox/stories/helpers/ToggleBoxGroupStoryHelper.tsx @@ -0,0 +1,42 @@ +import * as React from "react"; + +interface ToggleBoxGroupStoryHelperState { + selectedItems: string[]; +} + +interface RenderProps { + changeHandler: (selectedItems: string[]) => void; + selectedItems: string[]; +} +interface ToggleBoxGroupStoryHelperProps { + children: (renderProps: RenderProps) => React.ReactNode; + selectedItems?: string[]; +} + +class ToggleBoxGroupStoryHelper extends React.PureComponent< + ToggleBoxGroupStoryHelperProps, + ToggleBoxGroupStoryHelperState +> { + constructor(props) { + super(props); + + this.handleChange = this.handleChange.bind(this); + + this.state = { + selectedItems: props.selectedItems || [] + }; + } + + public render() { + return this.props.children({ + changeHandler: this.handleChange, + selectedItems: this.state.selectedItems + }); + } + + private handleChange(value) { + this.setState({ selectedItems: value }); + } +} + +export default ToggleBoxGroupStoryHelper; diff --git a/packages/toggleBox/stories/helpers/ToggleBoxStoryHelper.tsx b/packages/toggleBox/stories/helpers/ToggleBoxStoryHelper.tsx new file mode 100644 index 000000000..2a049470d --- /dev/null +++ b/packages/toggleBox/stories/helpers/ToggleBoxStoryHelper.tsx @@ -0,0 +1,42 @@ +import * as React from "react"; + +interface ToggleBoxStoryHelperState { + isActive: boolean; +} + +interface RenderProps { + changeHandler?: (event?: React.SyntheticEvent) => void; + isActive?: boolean; +} +interface ToggleBoxStoryHelperProps { + children: (renderProps: RenderProps) => React.ReactNode; + isActive?: boolean; +} + +class ToggleBoxStoryHelper extends React.PureComponent< + ToggleBoxStoryHelperProps, + ToggleBoxStoryHelperState +> { + constructor(props) { + super(props); + + this.handleChange = this.handleChange.bind(this); + + this.state = { + isActive: props.isActive + }; + } + + public render() { + return this.props.children({ + changeHandler: this.handleChange, + isActive: this.state.isActive + }); + } + + private handleChange(e) { + this.setState({ isActive: e.target.checked }); + } +} + +export default ToggleBoxStoryHelper; diff --git a/packages/toggleBox/tests/ToggleBox.test.tsx b/packages/toggleBox/tests/ToggleBox.test.tsx new file mode 100644 index 000000000..b2ab1f932 --- /dev/null +++ b/packages/toggleBox/tests/ToggleBox.test.tsx @@ -0,0 +1,56 @@ +import React from "react"; +import { mount } from "enzyme"; +import * as emotion from "emotion"; +import { createSerializer } from "jest-emotion"; +import toJson from "enzyme-to-json"; + +import { ToggleBox } from ".."; + +expect.addSnapshotSerializer(createSerializer(emotion)); + +describe("ToggleBox", () => { + it("renders default", () => { + const component = mount( + + default + + ); + + expect(toJson(component)).toMatchSnapshot(); + }); + + it("renders active", () => { + const component = mount( + + isActive + + ); + + expect(toJson(component)).toMatchSnapshot(); + }); + + it("renders disabled", () => { + const component = mount( + + disabled + + ); + + expect(toJson(component)).toMatchSnapshot(); + }); + + it("calls onChange prop when the input is changed", () => { + const onChangeFn = jest.fn(); + const component = mount( + + default + + ); + + const toggleBoxInput = component.find("input"); + + expect(onChangeFn).not.toHaveBeenCalled(); + toggleBoxInput.simulate("change", { target: { checked: true } }); + expect(onChangeFn).toHaveBeenCalled(); + }); +}); diff --git a/packages/toggleBox/tests/ToggleBoxGroup.test.tsx b/packages/toggleBox/tests/ToggleBoxGroup.test.tsx new file mode 100644 index 000000000..41dcab8de --- /dev/null +++ b/packages/toggleBox/tests/ToggleBoxGroup.test.tsx @@ -0,0 +1,94 @@ +import React from "react"; +import { mount } from "enzyme"; +import * as emotion from "emotion"; +import { createSerializer } from "jest-emotion"; +import toJson from "enzyme-to-json"; + +import { ToggleBox, ToggleBoxGroup } from ".."; + +expect.addSnapshotSerializer(createSerializer(emotion)); + +describe("ToggleBoxGroup", () => { + it("renders default", () => { + const component = mount( + + + Exosphere + + + Thermosphere + + + Mesosphere + + + ); + + expect(toJson(component)).toMatchSnapshot(); + }); + + it("renders with a selected ToggleBox", () => { + const component = mount( + + + Exosphere + + + Thermosphere + + + Mesosphere + + + ); + + expect(toJson(component)).toMatchSnapshot(); + }); + + it("renders with custom direction and gutter size", () => { + const component = mount( + + + Exosphere + + + Thermosphere + + + Mesosphere + + + ); + + expect(toJson(component)).toMatchSnapshot(); + }); + + it("calls onChange prop with the selected values", () => { + const onChangeFn = jest.fn(); + const component = mount( + + + Exosphere + + + Thermosphere + + + Mesosphere + + + ); + + const toggleBoxInput = component.find("input").first(); + + expect(onChangeFn).not.toHaveBeenCalled(); + toggleBoxInput.simulate("change", { target: { checked: true } }); + expect(onChangeFn).toHaveBeenCalledWith([toggleBoxInput.prop("value")]); + toggleBoxInput.simulate("change", { target: { checked: false } }); + expect(onChangeFn).toHaveBeenCalledWith([]); + }); +}); diff --git a/packages/toggleBox/tests/__snapshots__/ToggleBox.test.tsx.snap b/packages/toggleBox/tests/__snapshots__/ToggleBox.test.tsx.snap new file mode 100644 index 000000000..182b78a34 --- /dev/null +++ b/packages/toggleBox/tests/__snapshots__/ToggleBox.test.tsx.snap @@ -0,0 +1,290 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ToggleBox renders active 1`] = ` +.emotion-0 { + border: 0; + -webkit-clip: rect(0 0 0 0); + clip: rect(0 0 0 0); + position: absolute; + overflow: hidden; + margin: -1px; + padding: 0; + width: 1px; + height: 1px; +} + +.emotion-3 { + display: block; +} + +.emotion-1 { + padding: 16px; +} + +.emotion-2 { + background-color: var(--themeBgPrimary,#FFFFFF); + box-shadow: 0 0 0 1px var(--themeBorder,#DADDE2); + border-radius: 6px; + cursor: pointer; +} + +.emotion-2 > div { + height: 100%; +} + +.emotion-2:hover, +.emotion-2:focus { + box-shadow: 0 0 0 1px var(--themeBrandPrimary,#7D58FF); + outline: 0; +} + +.emotion-2:active { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-2, +.emotion-2:hover, +.emotion-2:focus { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-2:focus { + background-color: var(--themeBgHover,#F7F8F9); +} + + + + + + +`; + +exports[`ToggleBox renders default 1`] = ` +.emotion-0 { + border: 0; + -webkit-clip: rect(0 0 0 0); + clip: rect(0 0 0 0); + position: absolute; + overflow: hidden; + margin: -1px; + padding: 0; + width: 1px; + height: 1px; +} + +.emotion-3 { + display: block; +} + +.emotion-2 { + background-color: var(--themeBgPrimary,#FFFFFF); + box-shadow: 0 0 0 1px var(--themeBorder,#DADDE2); + border-radius: 6px; + cursor: pointer; +} + +.emotion-2 > div { + height: 100%; +} + +.emotion-2:hover, +.emotion-2:focus { + box-shadow: 0 0 0 1px var(--themeBrandPrimary,#7D58FF); + outline: 0; +} + +.emotion-2:active { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-1 { + padding: 16px; +} + + + + + + +`; + +exports[`ToggleBox renders disabled 1`] = ` +.emotion-0 { + border: 0; + -webkit-clip: rect(0 0 0 0); + clip: rect(0 0 0 0); + position: absolute; + overflow: hidden; + margin: -1px; + padding: 0; + width: 1px; + height: 1px; +} + +.emotion-3 { + display: block; +} + +.emotion-1 { + padding: 16px; +} + +.emotion-2 { + background-color: var(--themeBgPrimary,#FFFFFF); + box-shadow: 0 0 0 1px var(--themeBorder,#DADDE2); + border-radius: 6px; + cursor: pointer; + background-color: var(--themeBgDisabled,#E8EAED); + color: var(--themeTextColorDisabled,#AEB0B4); + cursor: auto; +} + +.emotion-2 > div { + height: 100%; +} + +.emotion-2:hover, +.emotion-2:focus { + box-shadow: 0 0 0 1px var(--themeBrandPrimary,#7D58FF); + outline: 0; +} + +.emotion-2:active { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-2, +.emotion-2:hover, +.emotion-2:focus { + box-shadow: 0 0 0 0 transparent; +} + + + + + + +`; diff --git a/packages/toggleBox/tests/__snapshots__/ToggleBoxGroup.test.tsx.snap b/packages/toggleBox/tests/__snapshots__/ToggleBoxGroup.test.tsx.snap new file mode 100644 index 000000000..653826672 --- /dev/null +++ b/packages/toggleBox/tests/__snapshots__/ToggleBoxGroup.test.tsx.snap @@ -0,0 +1,963 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ToggleBoxGroup renders default 1`] = ` +.emotion-0 { + border: 0; + -webkit-clip: rect(0 0 0 0); + clip: rect(0 0 0 0); + position: absolute; + overflow: hidden; + margin: -1px; + padding: 0; + width: 1px; + height: 1px; +} + +.emotion-15 { + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + height: auto; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + box-sizing: border-box; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + min-height: 0; +} + +.emotion-15 > div { + width: auto; +} + +.emotion-15 > *:not(:first-child) { + padding-left: 16px; + padding-top: 0; +} + +.emotion-4 { + box-sizing: border-box; + -webkit-flex-basis: 0; + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + width: auto; +} + +.emotion-3 { + display: block; +} + +.emotion-2 { + background-color: var(--themeBgPrimary,#FFFFFF); + box-shadow: 0 0 0 1px var(--themeBorder,#DADDE2); + border-radius: 6px; + cursor: pointer; +} + +.emotion-2 > div { + height: 100%; +} + +.emotion-2:hover, +.emotion-2:focus { + box-shadow: 0 0 0 1px var(--themeBrandPrimary,#7D58FF); + outline: 0; +} + +.emotion-2:active { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-1 { + padding: 16px; +} + + + +
+ +
+ + + + + +
+
+ +
+ + + + + +
+
+ +
+ + + + + +
+
+
+
+
+`; + +exports[`ToggleBoxGroup renders with a selected ToggleBox 1`] = ` +.emotion-0 { + border: 0; + -webkit-clip: rect(0 0 0 0); + clip: rect(0 0 0 0); + position: absolute; + overflow: hidden; + margin: -1px; + padding: 0; + width: 1px; + height: 1px; +} + +.emotion-15 { + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + height: auto; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + box-sizing: border-box; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + min-height: 0; +} + +.emotion-15 > div { + width: auto; +} + +.emotion-15 > *:not(:first-child) { + padding-left: 16px; + padding-top: 0; +} + +.emotion-4 { + box-sizing: border-box; + -webkit-flex-basis: 0; + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + width: auto; +} + +.emotion-3 { + display: block; +} + +.emotion-2 { + background-color: var(--themeBgPrimary,#FFFFFF); + box-shadow: 0 0 0 1px var(--themeBorder,#DADDE2); + border-radius: 6px; + cursor: pointer; +} + +.emotion-2 > div { + height: 100%; +} + +.emotion-2:hover, +.emotion-2:focus { + box-shadow: 0 0 0 1px var(--themeBrandPrimary,#7D58FF); + outline: 0; +} + +.emotion-2:active { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-1 { + padding: 16px; +} + +.emotion-12 { + background-color: var(--themeBgPrimary,#FFFFFF); + box-shadow: 0 0 0 1px var(--themeBorder,#DADDE2); + border-radius: 6px; + cursor: pointer; +} + +.emotion-12 > div { + height: 100%; +} + +.emotion-12:hover, +.emotion-12:focus { + box-shadow: 0 0 0 1px var(--themeBrandPrimary,#7D58FF); + outline: 0; +} + +.emotion-12:active { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-12, +.emotion-12:hover, +.emotion-12:focus { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-12:focus { + background-color: var(--themeBgHover,#F7F8F9); +} + + + +
+ +
+ + + + + +
+
+ +
+ + + + + +
+
+ +
+ + + + + +
+
+
+
+
+`; + +exports[`ToggleBoxGroup renders with custom direction and gutter size 1`] = ` +.emotion-0 { + border: 0; + -webkit-clip: rect(0 0 0 0); + clip: rect(0 0 0 0); + position: absolute; + overflow: hidden; + margin: -1px; + padding: 0; + width: 1px; + height: 1px; +} + +.emotion-4 { + box-sizing: border-box; + -webkit-flex-basis: 0; + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + width: auto; +} + +.emotion-3 { + display: block; +} + +.emotion-2 { + background-color: var(--themeBgPrimary,#FFFFFF); + box-shadow: 0 0 0 1px var(--themeBorder,#DADDE2); + border-radius: 6px; + cursor: pointer; +} + +.emotion-2 > div { + height: 100%; +} + +.emotion-2:hover, +.emotion-2:focus { + box-shadow: 0 0 0 1px var(--themeBrandPrimary,#7D58FF); + outline: 0; +} + +.emotion-2:active { + box-shadow: 0 0 0 2px var(--themeBrandPrimary,#7D58FF); +} + +.emotion-1 { + padding: 16px; +} + +.emotion-15 { + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + height: 100%; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + box-sizing: border-box; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + min-height: 0; +} + +.emotion-15 > div { + width: 100%; +} + +.emotion-15 > *:not(:first-child) { + padding-left: 0; + padding-top: 48px; +} + + + +
+ +
+ + + + + +
+
+ +
+ + + + + +
+
+ +
+ + + + + +
+
+
+
+
+`; diff --git a/packages/toggleWrapper/README.md b/packages/toggleWrapper/README.md new file mode 100644 index 000000000..7fd35abaf --- /dev/null +++ b/packages/toggleWrapper/README.md @@ -0,0 +1,3 @@ +# ToggleWrapper + +A `ToggleWrapper` is a utility component that's useful for rendering children differently based on whether the component is in an "on" or "off" state. diff --git a/packages/toggleWrapper/components/ToggleWrapper.tsx b/packages/toggleWrapper/components/ToggleWrapper.tsx new file mode 100644 index 000000000..b5f57c442 --- /dev/null +++ b/packages/toggleWrapper/components/ToggleWrapper.tsx @@ -0,0 +1,102 @@ +import * as React from "react"; +import { visuallyHidden, display } from "../../shared/styles/styleUtils"; + +interface RenderProps { + isActive?: boolean; + hasFocus?: boolean; +} + +export interface ToggleWrapperProps extends React.HTMLProps { + /** + * Whether the component is in the "on" state + */ + isActive?: boolean; + /** + * The value being toggled + */ + value: string; + /** + * The unique identifier for the toggle + */ + id: string; + /** + * The type of boolean input element + */ + type?: "checkbox" | "radio"; +} + +interface LocalToggleWrapperProps extends ToggleWrapperProps { + children: (renderProps: RenderProps) => React.ReactNode; +} + +interface ToggleWrapperState { + hasFocus: boolean; +} + +class ToggleWrapper extends React.PureComponent< + LocalToggleWrapperProps, + ToggleWrapperState +> { + public static defaultProps: Partial = { + type: "checkbox" + }; + + constructor(props: LocalToggleWrapperProps) { + super(props); + + this.state = { + hasFocus: false + }; + + this.handleFocus = this.handleFocus.bind(this); + this.handleBlur = this.handleBlur.bind(this); + } + + public render() { + const { children, id, isActive, ...other } = this.props; + const { hasFocus } = this.state; + delete other.checked; + delete other.className; + delete other.onFocus; + delete other.onBlur; + + return ( + // tslint is giving an error because it can't tell that the value of `type` + // will be "radio" or "checkbox". + // Passing either string directly makes the error go away + // tslint:disable react-a11y-role-supports-aria-props + + // tslint:enable + ); + } + + private handleFocus(e) { + this.setState({ hasFocus: true }); + + if (this.props.onFocus) { + this.props.onFocus(e); + } + } + + private handleBlur(e) { + this.setState({ hasFocus: false }); + + if (this.props.onBlur) { + this.props.onBlur(e); + } + } +} + +export default ToggleWrapper; diff --git a/packages/toggleWrapper/index.ts b/packages/toggleWrapper/index.ts new file mode 100644 index 000000000..9d50f8d09 --- /dev/null +++ b/packages/toggleWrapper/index.ts @@ -0,0 +1 @@ +export { default as ToggleWrapper } from "./components/ToggleWrapper"; diff --git a/packages/toggleWrapper/stories/ToggleWrapper.stories.tsx b/packages/toggleWrapper/stories/ToggleWrapper.stories.tsx new file mode 100644 index 000000000..e912b712c --- /dev/null +++ b/packages/toggleWrapper/stories/ToggleWrapper.stories.tsx @@ -0,0 +1,29 @@ +import * as React from "react"; +import { storiesOf } from "@storybook/react"; +import { withReadme } from "storybook-readme"; +import { ToggleWrapper } from "../index"; + +const readme = require("../README.md"); + +storiesOf("ToggleWrapper", module) + .addDecorator(withReadme([readme])) + .add("default", () => ( + + {({ isActive }) => ( +
+ the isActive render prop returns: +
{`${isActive}`}
+
+ )} +
+ )) + .add("isActive", () => ( + + {({ isActive }) => ( +
+ the isActive render prop returns: +
{`${isActive}`}
+
+ )} +
+ )); diff --git a/packages/toggleWrapper/tests/ToggleWrapper.test.tsx b/packages/toggleWrapper/tests/ToggleWrapper.test.tsx new file mode 100644 index 000000000..db2eb89e5 --- /dev/null +++ b/packages/toggleWrapper/tests/ToggleWrapper.test.tsx @@ -0,0 +1,56 @@ +import React from "react"; +import { mount } from "enzyme"; +import * as emotion from "emotion"; +import { createSerializer } from "jest-emotion"; +import toJson from "enzyme-to-json"; + +import { ToggleWrapper } from "../"; + +expect.addSnapshotSerializer(createSerializer(emotion)); + +describe("ToggleWrapper", () => { + it("renders", () => { + const component = mount( + + {({ isActive }) =>
{`isActive? ${isActive}`}
} +
+ ); + + expect(toJson(component)).toMatchSnapshot(); + }); + it("renders as a radio input", () => { + const component = mount( + + {({ isActive }) =>
{`isActive? ${isActive}`}
} +
+ ); + + expect(toJson(component)).toMatchSnapshot(); + }); + it("calls onFocus prop when the input gets focus", () => { + const focusFn = jest.fn(); + const component = mount( + + {({ isActive }) =>
{`isActive? ${isActive}`}
} +
+ ); + + expect(focusFn).not.toHaveBeenCalled(); + component.find("input").simulate("focus"); + expect(focusFn).toHaveBeenCalled(); + }); + it("calls onBlur prop when the input loses focus", () => { + const blurFn = jest.fn(); + const component = mount( + + {({ isActive }) =>
{`isActive? ${isActive}`}
} +
+ ); + + expect(blurFn).not.toHaveBeenCalled(); + component.find("input").simulate("focus"); + expect(blurFn).not.toHaveBeenCalled(); + component.find("input").simulate("blur"); + expect(blurFn).toHaveBeenCalled(); + }); +}); diff --git a/packages/toggleWrapper/tests/__snapshots__/ToggleWrapper.test.tsx.snap b/packages/toggleWrapper/tests/__snapshots__/ToggleWrapper.test.tsx.snap new file mode 100644 index 000000000..75ac4f3a9 --- /dev/null +++ b/packages/toggleWrapper/tests/__snapshots__/ToggleWrapper.test.tsx.snap @@ -0,0 +1,81 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ToggleWrapper renders 1`] = ` +.emotion-0 { + border: 0; + -webkit-clip: rect(0 0 0 0); + clip: rect(0 0 0 0); + position: absolute; + overflow: hidden; + margin: -1px; + padding: 0; + width: 1px; + height: 1px; +} + +.emotion-1 { + display: block; +} + + + + +`; + +exports[`ToggleWrapper renders as a radio input 1`] = ` +.emotion-0 { + border: 0; + -webkit-clip: rect(0 0 0 0); + clip: rect(0 0 0 0); + position: absolute; + overflow: hidden; + margin: -1px; + padding: 0; + width: 1px; + height: 1px; +} + +.emotion-1 { + display: block; +} + + + + +`;