diff --git a/package-lock.json b/package-lock.json index f4ddb8d3b..57e782760 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14289,6 +14289,12 @@ "css-mediaquery": "^0.1.2" } }, + "material-design-icons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/material-design-icons/-/material-design-icons-3.0.1.tgz", + "integrity": "sha1-mnHEh0chjrylHlGmbaaCA4zct78=", + "dev": true + }, "math-expression-evaluator": { "version": "1.2.17", "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", diff --git a/package.json b/package.json index b7e66c3d5..dfd500620 100644 --- a/package.json +++ b/package.json @@ -115,6 +115,7 @@ "jest": "^23.4.1", "jsdom": "^11.11.0", "loader-utils": "^1.1.0", + "material-design-icons": "^3.0.1", "npm-run-all": "^4.1.3", "postcss-advanced-variables": "^2.3.3", "postcss-css-variables": "^0.9.0", diff --git a/src/core/client/stream/components/__snapshots__/App.spec.tsx.snap b/src/core/client/stream/components/__snapshots__/App.spec.tsx.snap index 6a12e4e09..2fc77d00c 100644 --- a/src/core/client/stream/components/__snapshots__/App.spec.tsx.snap +++ b/src/core/client/stream/components/__snapshots__/App.spec.tsx.snap @@ -1,14 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`renders correctly 1`] = ` - - + `; exports[`renders correctly when asset is null 1`] = ` diff --git a/src/core/client/stream/components/__snapshots__/ReplyList.spec.tsx.snap b/src/core/client/stream/components/__snapshots__/ReplyList.spec.tsx.snap index 9fbe86dab..5707b755f 100644 --- a/src/core/client/stream/components/__snapshots__/ReplyList.spec.tsx.snap +++ b/src/core/client/stream/components/__snapshots__/ReplyList.spec.tsx.snap @@ -2,7 +2,7 @@ exports[`renders correctly 1`] = ` - - + `; exports[`when there is more disables load more button 1`] = ` - - + `; exports[`when there is more renders a load more button 1`] = ` - - + `; diff --git a/src/core/client/stream/components/__snapshots__/Stream.spec.tsx.snap b/src/core/client/stream/components/__snapshots__/Stream.spec.tsx.snap index a8210fd99..441437216 100644 --- a/src/core/client/stream/components/__snapshots__/Stream.spec.tsx.snap +++ b/src/core/client/stream/components/__snapshots__/Stream.spec.tsx.snap @@ -10,14 +10,14 @@ exports[`renders correctly 1`] = ` - - - - + - - + + `; @@ -71,14 +71,14 @@ exports[`when there is more disables load more button 1`] = ` - - - - + - + @@ -133,7 +133,7 @@ exports[`when there is more disables load more button 1`] = ` Load More - + `; @@ -147,14 +147,14 @@ exports[`when there is more renders a load more button 1`] = ` - - - - + - + @@ -209,6 +209,6 @@ exports[`when there is more renders a load more button 1`] = ` Load More - + `; diff --git a/src/core/client/ui/components/BaseButton/BaseButton.spec.tsx b/src/core/client/ui/components/BaseButton/BaseButton.spec.tsx new file mode 100644 index 000000000..b7754c865 --- /dev/null +++ b/src/core/client/ui/components/BaseButton/BaseButton.spec.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import TestRenderer from "react-test-renderer"; + +import { PropTypesOf } from "talk-framework/types"; + +import BaseButton from "./BaseButton"; + +it("renders correctly", () => { + const props: PropTypesOf = { + className: "my-class", + children: "Push Me", + }; + const renderer = TestRenderer.create(); + expect(renderer.toJSON()).toMatchSnapshot(); +}); + +it("renders as anchor", () => { + const props: PropTypesOf = { + anchor: true, + children: "Push Me", + }; + const renderer = TestRenderer.create(); + expect(renderer.toJSON()).toMatchSnapshot(); +}); diff --git a/src/core/client/ui/components/BaseButton/__snapshots__/BaseButton.spec.tsx.snap b/src/core/client/ui/components/BaseButton/__snapshots__/BaseButton.spec.tsx.snap new file mode 100644 index 000000000..c6fd97a78 --- /dev/null +++ b/src/core/client/ui/components/BaseButton/__snapshots__/BaseButton.spec.tsx.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders as anchor 1`] = ` + + Push Me + +`; + +exports[`renders correctly 1`] = ` + +`; diff --git a/src/core/client/ui/components/Button/Button.css b/src/core/client/ui/components/Button/Button.css index bda2d0e31..9124a859f 100644 --- a/src/core/client/ui/components/Button/Button.css +++ b/src/core/client/ui/components/Button/Button.css @@ -1,9 +1,20 @@ .root { composes: button from "talk-ui/shared/typography.css"; - padding: 5px 20px; + padding: 5px 15px; border-radius: var(--round-corners); background-color: transparent; + position: relative; + display: flex; + justify-content: center; + align-items: center; + + & > * { + margin: 0 calc(0.5 * var(--spacing-unit)) 0 0; + } + & > *:last-child { + margin: 0; + } } .root.disabled { diff --git a/src/core/client/ui/components/Button/Button.mdx b/src/core/client/ui/components/Button/Button.mdx index 398aff282..011e47ea5 100644 --- a/src/core/client/ui/components/Button/Button.mdx +++ b/src/core/client/ui/components/Button/Button.mdx @@ -5,6 +5,7 @@ menu: UI Kit import { Playground } from 'docz' import Button from './Button' +import Icon from '../Icon' import Flex from '../Flex' # Button @@ -28,3 +29,14 @@ import Flex from '../Flex' + +## Button with Icon + + + + + + + + + diff --git a/src/core/client/ui/components/Button/Button.tsx b/src/core/client/ui/components/Button/Button.tsx index 8a73c0c1a..aaeaeb518 100644 --- a/src/core/client/ui/components/Button/Button.tsx +++ b/src/core/client/ui/components/Button/Button.tsx @@ -64,7 +64,7 @@ class Button extends React.Component { className={rootClassName} classes={pick(classes, "keyboardFocus", "mouseHover")} disabled={disabled} - ref={forwardRef} + forwardRef={forwardRef} {...rest} /> ); diff --git a/src/core/client/ui/components/Flex/Flex.spec.tsx b/src/core/client/ui/components/Flex/Flex.spec.tsx index b774d9961..5c68f0de0 100644 --- a/src/core/client/ui/components/Flex/Flex.spec.tsx +++ b/src/core/client/ui/components/Flex/Flex.spec.tsx @@ -1,5 +1,5 @@ -import { shallow } from "enzyme"; import React from "react"; +import TestRenderer from "react-test-renderer"; import { PropTypesOf } from "talk-ui/types"; @@ -11,10 +11,58 @@ it("renders correctly", () => { alignItems: "center", direction: "row", }; - const wrapper = shallow( + const renderer = TestRenderer.create(
Hello World
); - expect(wrapper).toMatchSnapshot(); + expect(renderer.toJSON()).toMatchSnapshot(); +}); + +it("renders with wrap", () => { + const props: PropTypesOf = { + wrap: true, + }; + const renderer = TestRenderer.create( + +
Hello World
+
+ ); + expect(renderer.toJSON()).toMatchSnapshot(); +}); + +it("renders with wrap reverse", () => { + const props: PropTypesOf = { + wrap: "reverse", + }; + const renderer = TestRenderer.create( + +
Hello World
+
+ ); + expect(renderer.toJSON()).toMatchSnapshot(); +}); + +it("renders with item gutter", () => { + const props: PropTypesOf = { + itemGutter: true, + }; + const renderer = TestRenderer.create( + +
Hello World
+
+ ); + expect(renderer.toJSON()).toMatchSnapshot(); +}); + +it("renders with halfe item gutter", () => { + const props: PropTypesOf = { + itemGutter: "half", + }; + const renderer = TestRenderer.create( + +
Hello World
+
+ ); + expect(renderer.toJSON()).toMatchSnapshot(); }); diff --git a/src/core/client/ui/components/Flex/Flex.tsx b/src/core/client/ui/components/Flex/Flex.tsx index 8bf770ec7..62d8ff66c 100644 --- a/src/core/client/ui/components/Flex/Flex.tsx +++ b/src/core/client/ui/components/Flex/Flex.tsx @@ -3,11 +3,16 @@ import React, { Ref } from "react"; import { StatelessComponent } from "react"; import { pascalCase } from "talk-common/utils"; -import { withForwardRef } from "talk-ui/hocs"; +import { withForwardRef, withStyles } from "talk-ui/hocs"; import * as styles from "./Flex.css"; interface InnerProps { + /** + * This prop can be used to add custom classnames. + * It is handled by the `withStyles `HOC. + */ + classes: typeof styles; id?: string; role?: string; justifyContent?: @@ -32,6 +37,7 @@ interface InnerProps { const Flex: StatelessComponent = props => { const { + classes, className, justifyContent, alignItems, @@ -43,27 +49,29 @@ const Flex: StatelessComponent = props => { } = props; const classObject: Record = { - [styles.itemGutter]: itemGutter === true, - [styles.halfItemGutter]: itemGutter === "half", - [styles.wrap]: wrap === true, - [styles.wrapReverse]: wrap === "reverse", + [classes.itemGutter]: itemGutter === true, + [classes.halfItemGutter]: itemGutter === "half", + [classes.wrap]: wrap === true, + [classes.wrapReverse]: wrap === "reverse", }; if (justifyContent) { - classObject[(styles as any)[`justify${pascalCase(justifyContent)}`]] = true; + classObject[ + (classes as any)[`justify${pascalCase(justifyContent)}`] + ] = true; } if (alignItems) { - classObject[(styles as any)[`align${pascalCase(alignItems)}`]] = true; + classObject[(classes as any)[`align${pascalCase(alignItems)}`]] = true; } if (direction) { - classObject[(styles as any)[`direction${pascalCase(direction)}`]] = true; + classObject[(classes as any)[`direction${pascalCase(direction)}`]] = true; } - const classNames: string = cn(styles.root, className, classObject); + const classNames: string = cn(classes.root, className, classObject); return
; }; -export default withForwardRef(Flex); +export default withForwardRef(withStyles(styles)(Flex)); diff --git a/src/core/client/ui/components/Flex/__snapshots__/Flex.spec.tsx.snap b/src/core/client/ui/components/Flex/__snapshots__/Flex.spec.tsx.snap index 90ef93c13..31f1f73c1 100644 --- a/src/core/client/ui/components/Flex/__snapshots__/Flex.spec.tsx.snap +++ b/src/core/client/ui/components/Flex/__snapshots__/Flex.spec.tsx.snap @@ -9,3 +9,43 @@ exports[`renders correctly 1`] = `
`; + +exports[`renders with halfe item gutter 1`] = ` +
+
+ Hello World +
+
+`; + +exports[`renders with item gutter 1`] = ` +
+
+ Hello World +
+
+`; + +exports[`renders with wrap 1`] = ` +
+
+ Hello World +
+
+`; + +exports[`renders with wrap reverse 1`] = ` +
+
+ Hello World +
+
+`; diff --git a/src/core/client/ui/components/Icon/Icon.css b/src/core/client/ui/components/Icon/Icon.css new file mode 100644 index 000000000..65163aa8d --- /dev/null +++ b/src/core/client/ui/components/Icon/Icon.css @@ -0,0 +1,53 @@ +@font-face { + font-family: "Material Icons"; + font-style: normal; + font-weight: 400; + src: local("Material Icons"), local("MaterialIcons-Regular"), + url(material-design-icons/iconfont/MaterialIcons-Regular.woff2) + format("woff2"), + url(material-design-icons/iconfont/MaterialIcons-Regular.woff) + format("woff"), + url(material-design-icons/iconfont/MaterialIcons-Regular.ttf) + format("truetype"); +} + +.root { + font-family: "Material Icons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + overflow: hidden; + vertical-align: middle; + display: inline-block; + + /* Enable Ligatures */ + font-feature-settings: "liga"; + font-variant-ligatures: "discretionary-ligatures"; + + /* Support for Safari and Chrome. */ + text-rendering: optimizeLegibility; + + /* Better Font Rendering */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.sm { + font-size: 18px; + width: 18px; +} +.md { + font-size: 24px; + width: 24px; +} +.lg { + font-size: 36px; + width: 36px; +} +.xl { + font-size: 48px; + width: 48px; +} diff --git a/src/core/client/ui/components/Icon/Icon.mdx b/src/core/client/ui/components/Icon/Icon.mdx new file mode 100644 index 000000000..83428c28b --- /dev/null +++ b/src/core/client/ui/components/Icon/Icon.mdx @@ -0,0 +1,21 @@ +--- +name: Icon +menu: UI Kit +--- + +import { Playground, PropsTable } from 'docz' +import Icon from './Icon' + +# Icon + +Renders an icon. + +Checkout available icons https://material.io/tools/icons/ + +## Basic usage + + face + face + face + face + diff --git a/src/core/client/ui/components/Icon/Icon.spec.tsx b/src/core/client/ui/components/Icon/Icon.spec.tsx new file mode 100644 index 000000000..93cf68a66 --- /dev/null +++ b/src/core/client/ui/components/Icon/Icon.spec.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import TestRenderer from "react-test-renderer"; + +import { PropTypesOf } from "talk-framework/types"; + +import Icon from "./Icon"; + +it("renders correctly", () => { + const props: PropTypesOf = { + children: "face", + }; + const renderer = TestRenderer.create(); + expect(renderer.toJSON()).toMatchSnapshot(); +}); + +it("renders correctly with specified size", () => { + const props: PropTypesOf = { + size: "lg", + children: "bookmark", + }; + const renderer = TestRenderer.create(); + expect(renderer.toJSON()).toMatchSnapshot(); +}); diff --git a/src/core/client/ui/components/Icon/Icon.tsx b/src/core/client/ui/components/Icon/Icon.tsx new file mode 100644 index 000000000..4f920f2e5 --- /dev/null +++ b/src/core/client/ui/components/Icon/Icon.tsx @@ -0,0 +1,37 @@ +import cn from "classnames"; +import React, { HTMLAttributes, Ref, StatelessComponent } from "react"; + +import { withForwardRef, withStyles } from "talk-ui/hocs"; +import { PropTypesOf } from "talk-ui/types"; + +import * as styles from "./Icon.css"; + +interface InnerProps extends HTMLAttributes { + /** + * This prop can be used to add custom classnames. + * It is handled by the `withStyles `HOC. + */ + classes: typeof styles; + + size?: "sm" | "md" | "lg" | "xl"; + + /** ref to the HTMLIconElement */ + ref?: Ref; + + /** Internal: Forwarded Ref */ + forwardRef?: Ref; +} + +const Icon: StatelessComponent = props => { + const { classes, className, size, forwardRef, ...rest } = props; + const rootClassName = cn(classes.root, className, classes[size!]); + return ; +}; + +Icon.defaultProps = { + size: "sm", +}; + +const enhanced = withForwardRef(withStyles(styles)(Icon)); +export type IconProps = PropTypesOf; +export default enhanced; diff --git a/src/core/client/ui/components/Icon/__snapshots__/Icon.spec.tsx.snap b/src/core/client/ui/components/Icon/__snapshots__/Icon.spec.tsx.snap new file mode 100644 index 000000000..5e5a8c969 --- /dev/null +++ b/src/core/client/ui/components/Icon/__snapshots__/Icon.spec.tsx.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` + + face + +`; + +exports[`renders correctly with specified size 1`] = ` + + bookmark + +`; diff --git a/src/core/client/ui/components/Icon/index.ts b/src/core/client/ui/components/Icon/index.ts new file mode 100644 index 000000000..3e8146f8b --- /dev/null +++ b/src/core/client/ui/components/Icon/index.ts @@ -0,0 +1,2 @@ +export * from "./Icon"; +export { default } from "./Icon";