├── docs ├── CNAME ├── favicon.ico ├── iframe.html ├── index.html ├── logo.svg └── logo-inverse.svg ├── .storybook ├── static │ ├── CNAME │ ├── logo.svg │ └── logo-inverse.svg ├── Logo.js ├── head.html ├── webpack.config.js └── config.js ├── .eslintignore ├── assets.json ├── .npmignore ├── .gitignore ├── src ├── stories │ ├── .eslintrc.yml │ ├── Icon.js │ ├── Button.js │ ├── Input.js │ ├── Modal.js │ ├── Notification.js │ └── Dropdown.js ├── __tests__ │ ├── index-test.js │ ├── __snapshots__ │ │ ├── index-test.js.snap │ │ ├── Button-test.js.snap │ │ ├── Input-test.js.snap │ │ └── Dropdown-test.js.snap │ ├── Button-test.js │ ├── Input-test.js │ └── Dropdown-test.js ├── index.js ├── Icon │ ├── utils.js │ ├── index.js │ ├── __tests__ │ │ ├── index-test.js │ │ ├── __snapshots__ │ │ │ └── Spinner-test.js.snap │ │ └── Spinner-test.js │ ├── Default.js │ ├── Spinner.js │ └── icons.js ├── Modal │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ ├── Prompt-test.js.snap │ │ │ ├── Dialog-test.js.snap │ │ │ └── index-test.js.snap │ │ ├── Prompt-test.js │ │ ├── Dialog-test.js │ │ └── index-test.js │ ├── Prompt.js │ ├── Dialog.js │ └── index.js ├── Notification │ ├── __tests__ │ │ ├── index-test.js │ │ ├── NotifyMessage-test.js │ │ └── __snapshots__ │ │ │ ├── NotifyMessage-test.js.snap │ │ │ └── index-test.js.snap │ ├── index.js │ └── NotifyMesssage.js ├── Button.js ├── Input.js └── Dropdown.js ├── .babelrc ├── test └── setup.js ├── .circleci └── config.yml ├── LICENSE ├── .eslintrc.yml ├── README.md ├── package.json └── CHANGELOG.md /docs/CNAME: -------------------------------------------------------------------------------- 1 | uikit-react.io 2 | -------------------------------------------------------------------------------- /.storybook/static/CNAME: -------------------------------------------------------------------------------- 1 | uikit-react.io 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | lib 2 | .storybook 3 | docs 4 | -------------------------------------------------------------------------------- /assets.json: -------------------------------------------------------------------------------- 1 | {"app":{"js":"http://localhost:8080/app.js"}} -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stipsan/uikit-react/HEAD/docs/favicon.ico -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .coverage 2 | .out 3 | .storybook 4 | docs 5 | src 6 | test 7 | assets.json 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | node_modules 3 | npm-debug.log 4 | .nyc_output 5 | coverage 6 | .coverage 7 | -------------------------------------------------------------------------------- /src/stories/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | rules: 2 | import/no-unresolved: off 3 | jsx-a11y/href-no-hash: off 4 | -------------------------------------------------------------------------------- /src/__tests__/index-test.js: -------------------------------------------------------------------------------- 1 | it('should export', () => { 2 | expect(Object.keys(require('../index'))).toMatchSnapshot() 3 | }) 4 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets" : ["react", "es2015", "stage-0"], 3 | "plugins": [ 4 | ["babel-plugin-inline-import", { 5 | "extensions": [".svg"] 6 | }] 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export Button from './Button' 2 | export Dropdown from './Dropdown' 3 | export Modal from './Modal' 4 | export Notification from './Notification' 5 | export Input from './Input' 6 | export Icon from './Icon' 7 | -------------------------------------------------------------------------------- /src/__tests__/__snapshots__/index-test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`should export 1`] = ` 4 | Array [ 5 | "Button", 6 | "Dropdown", 7 | "Modal", 8 | "Notification", 9 | "Input", 10 | "Icon", 11 | ] 12 | `; 13 | -------------------------------------------------------------------------------- /.storybook/Logo.js: -------------------------------------------------------------------------------- 1 | const src = require('./static/logo.svg') 2 | 3 | const logoStyle = Object.freeze({ 4 | height: '64px', 5 | }) 6 | 7 | const Logo = () => 8 | UIkit React Logo 9 | 10 | 11 | export default Logo 12 | -------------------------------------------------------------------------------- /test/setup.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line no-console 2 | const error = console.error 3 | // eslint-disable-next-line no-console 4 | console.error = (warning, ...args) => { 5 | if (/(Invalid prop|Failed prop type)/.test(warning)) { 6 | throw new Error(warning) 7 | } 8 | error.apply(console, [warning, ...args]) 9 | } 10 | -------------------------------------------------------------------------------- /src/Icon/utils.js: -------------------------------------------------------------------------------- 1 | 2 | export const getDimensionsFromViewBox = (svg) => { 3 | const match = svg.match(/view[bB]ox=['"]([\s\S]*?)['"]/m) 4 | 5 | if (!match) return false 6 | 7 | const [, , width, height] = match[1].split(' ') 8 | 9 | return { width, height } 10 | } 11 | 12 | export const getInnerSvg = svg => svg.replace(/.*]*>|<\/svg>$/g, '') 13 | -------------------------------------------------------------------------------- /.storybook/head.html: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /src/Icon/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | 4 | import Default from './Default' 5 | import Spinner from './Spinner' 6 | 7 | const Icon = (props) => { 8 | switch (props.icon) { 9 | case 'spinner': 10 | return 11 | default: 12 | return 13 | } 14 | } 15 | 16 | Icon.propTypes = { 17 | icon: PropTypes.string.isRequired, 18 | } 19 | 20 | export default Icon 21 | -------------------------------------------------------------------------------- /src/Icon/__tests__/index-test.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import renderer from 'react-test-renderer' 3 | import Icon from '../index' 4 | import icons from '../icons' 5 | 6 | jest.mock('../Spinner', () => 'Spinner') 7 | 8 | const iconNames = Object.keys(icons) 9 | iconNames.forEach((iconName) => { 10 | test(iconName, () => { 11 | const component = renderer.create() 12 | expect(component.toJSON()).toMatchSnapshot() 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /src/Icon/__tests__/__snapshots__/Spinner-test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`should render correctly 1`] = ` 4 | 7 | 13 | 20 | 21 | 22 | `; 23 | -------------------------------------------------------------------------------- /src/Modal/__tests__/__snapshots__/Prompt-test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Prompt renders correctly 1`] = ` 4 |
7 |

8 | 12 |

13 |
14 | `; 15 | 16 | exports[`Prompt renders correctly 2`] = ` 17 |
20 |

21 | 25 |

26 |
27 | `; 28 | -------------------------------------------------------------------------------- /src/stories/Icon.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { storiesOf } from '@storybook/react' 3 | import { Icon } from '..' 4 | 5 | // This is to work around: https://github.com/kadirahq/react-storybook-addon-info/issues/26#issuecomment-229029177 6 | Icon.displayName = 'Icon' 7 | 8 | storiesOf('Icon', module) 9 | .addWithInfo('Basic Usage', '', () => ( 10 |
11 | 12 |   13 | 14 |   15 | 16 |
17 | ), { header: false, inline: true, propTables: [Icon] }) 18 | -------------------------------------------------------------------------------- /src/Icon/__tests__/Spinner-test.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import renderer from 'react-test-renderer' 3 | import Spinner from '../Spinner' 4 | 5 | jest.mock('react-dom') 6 | 7 | jest.mock('computed-style', () => () => 1) 8 | 9 | it('should render correctly', () => { 10 | const createNodeMock = ({ type }) => { 11 | switch (type) { 12 | case 'span': 13 | return { clientWidth: 32 } 14 | case 'circle': 15 | return {} 16 | default: 17 | return null 18 | } 19 | } 20 | const options = { createNodeMock } 21 | const component = renderer.create(, options) 22 | 23 | expect(component.toJSON()).toMatchSnapshot() 24 | }) 25 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/node:latest 6 | 7 | working_directory: ~/repo 8 | 9 | steps: 10 | - checkout 11 | 12 | - restore_cache: 13 | keys: 14 | - v1-dependencies-{{ checksum "package.json" }} 15 | - v1-dependencies- 16 | 17 | - run: yarn install 18 | 19 | - save_cache: 20 | paths: 21 | - node_modules 22 | key: v1-dependencies-{{ checksum "package.json" }} 23 | 24 | - run: yarn lint 25 | 26 | - run: yarn test --coverage 27 | 28 | - run: yarn coveralls 29 | 30 | - run: yarn semantic-release || true 31 | -------------------------------------------------------------------------------- /src/Modal/__tests__/Prompt-test.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import renderer from 'react-test-renderer' 3 | import Prompt from '../Prompt' 4 | 5 | function createNodeMock(element) { 6 | if (element.type === 'input') { 7 | return { 8 | focus() {}, 9 | } 10 | } 11 | return null 12 | } 13 | 14 | describe('Prompt', () => { 15 | it('renders correctly', () => { 16 | const options = { createNodeMock } 17 | const component = renderer.create( 18 | , options 19 | ) 20 | 21 | expect(component.toJSON()).toMatchSnapshot() 22 | 23 | component.update( 24 | , options 25 | ) 26 | expect(component.toJSON()).toMatchSnapshot() 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /src/Notification/__tests__/index-test.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import renderer from 'react-test-renderer' 3 | 4 | import Notification from '../index' 5 | 6 | jest.mock('react-portal', () => 'Portal') 7 | 8 | describe('Notification', () => { 9 | const defaultProps = { 10 | notifications: [{ id: 1, type: 'warning', message: 'Notification #1', icon: 'check' }], 11 | position: 'top-center', 12 | } 13 | const component = renderer.create( 14 | 15 | ) 16 | it('should render correctly', () => { 17 | expect(component.toJSON()).toMatchSnapshot() 18 | }) 19 | 20 | it('should hanlde click correctly', () => { 21 | const instance = component.getInstance() 22 | instance.handleClick() 23 | expect(instance.state.isOpened).toBe(true) 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /.storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpack = require('webpack') 3 | 4 | module.exports = { 5 | module: { 6 | rules: [ 7 | { 8 | test: /\.less/, 9 | loaders: ["style-loader", "css-loader", "less-loader"], 10 | }, 11 | { 12 | test: /\.css/, 13 | loaders: ["style-loader", "css-loader"], 14 | }, 15 | { 16 | test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, 17 | options: { limit: 10000, mimetype: 'application/font-woff' }, 18 | loader: 'url-loader', 19 | }, 20 | { 21 | test: /\.svg$/, 22 | options: { limit: 10000, mimetype: 'image/svg+xml' }, 23 | loader: 'url-loader', 24 | }, 25 | { 26 | test: /\.(ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9])?$/, 27 | loader: 'file-loader', 28 | }, 29 | ] 30 | }, 31 | } 32 | -------------------------------------------------------------------------------- /src/Modal/Prompt.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import PropTypes from 'prop-types' 3 | 4 | export default class Prompt extends Component { 5 | 6 | static defaultProps = { 7 | isOpen: false, 8 | } 9 | 10 | static propTypes = { 11 | isOpen: PropTypes.bool, 12 | } 13 | 14 | componentDidUpdate(prevProps) { 15 | if (prevProps.isOpen === false && this.props.isOpen === true) { 16 | this.input.focus() 17 | } 18 | } 19 | 20 | render() { 21 | return ( 22 |
23 |

24 | { 27 | if (node) { 28 | this.input = node 29 | } 30 | }} 31 | type="text" 32 | /> 33 |

34 |
35 | ) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Modal/__tests__/Dialog-test.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import renderer from 'react-test-renderer' 3 | import Dialog from '../Dialog' 4 | 5 | describe('Dialog', () => { 6 | const component = renderer.create( 7 | Lorem Ipsum 8 | ) 9 | it('renders correctly', () => { 10 | const tree = component.toJSON() 11 | expect(tree).toMatchSnapshot() 12 | }) 13 | 14 | it('should handle handleClose', () => { 15 | const instance = component.getInstance() 16 | instance.handleClose() 17 | expect(instance.props.handleClose).toHaveBeenCalled() 18 | }) 19 | 20 | it('should handle handleOverlayClick', () => { 21 | const instance = component.getInstance() 22 | const event = { stopPropagation: jest.fn() } 23 | instance.handleOverlayClick(event) 24 | expect(event.stopPropagation).toHaveBeenCalled() 25 | }) 26 | }) 27 | -------------------------------------------------------------------------------- /src/Modal/__tests__/__snapshots__/Dialog-test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Dialog renders correctly 1`] = ` 4 |
8 | 30 | 31 | 32 |
35 | Lorem Ipsum 36 |
37 |
38 | `; 39 | -------------------------------------------------------------------------------- /src/Notification/__tests__/NotifyMessage-test.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import renderer from 'react-test-renderer' 3 | 4 | import NotifyMesssage from '../NotifyMesssage' 5 | 6 | jest.useFakeTimers() 7 | 8 | describe('NotifyMesssage', () => { 9 | const defaultProps = { 10 | children: 'children', 11 | icon: 'check', 12 | position: 'top-center', 13 | onClick: jest.fn(), 14 | } 15 | 16 | it('should render correctly', () => { 17 | const component = renderer.create( 18 | 19 | ) 20 | expect(component.toJSON()).toMatchSnapshot() 21 | 22 | // Test unmount 23 | component.update() 24 | expect(component.toJSON()).toMatchSnapshot() 25 | }) 26 | 27 | it('should return if state is closed', () => { 28 | const component = renderer.create( 29 | 30 | ) 31 | const instance = component.getInstance() 32 | instance.handleClose() 33 | jest.runAllTimers() 34 | expect(instance.state.isOpen).toBe(false) 35 | 36 | instance.openNotification() 37 | expect(instance.state.isOpen).toBe(true) 38 | }) 39 | }) 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Stian Didriksen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /docs/iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | Storybook 14 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/__tests__/Button-test.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import renderer from 'react-test-renderer' 3 | import Button from '../Button' 4 | 5 | test('Button renders correctly', () => { 6 | expect(renderer.create( 7 | 8 | ).toJSON()).toMatchSnapshot() 9 | 10 | expect(renderer.create( 11 | 12 | ).toJSON()).toMatchSnapshot() 13 | 14 | expect(renderer.create( 15 | 16 | ).toJSON()).toMatchSnapshot() 17 | 18 | expect(renderer.create( 19 | 20 | ).toJSON()).toMatchSnapshot() 21 | 22 | expect(renderer.create( 23 | 24 | ).toJSON()).toMatchSnapshot() 25 | 26 | expect(renderer.create( 27 | 28 | ).toJSON()).toMatchSnapshot() 29 | 30 | expect(renderer.create( 31 | 32 | ).toJSON()).toMatchSnapshot() 33 | 34 | expect(renderer.create( 35 | 36 | ).toJSON()).toMatchSnapshot() 37 | 38 | expect(renderer.create( 39 | 40 | ).toJSON()).toMatchSnapshot() 41 | 42 | expect(renderer.create( 43 | 44 | ).toJSON()).toMatchSnapshot() 45 | }) 46 | -------------------------------------------------------------------------------- /src/Icon/Default.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react' 2 | import PropTypes from 'prop-types' 3 | 4 | import cx from 'classnames' 5 | 6 | import icons from './icons' 7 | import { getDimensionsFromViewBox, getInnerSvg } from './utils' 8 | 9 | export default class Default extends PureComponent { 10 | 11 | static propTypes = { 12 | component: PropTypes.string.isRequired, 13 | icon: PropTypes.oneOf(Object.keys(icons)).isRequired, 14 | ratio: PropTypes.number.isRequired, 15 | className: PropTypes.string, 16 | } 17 | 18 | static defaultProps = { 19 | className: '', 20 | component: 'span', 21 | ratio: 1, 22 | } 23 | 24 | render() { 25 | const { className, component, ratio, icon, ...props } = this.props 26 | const svg = icons[icon] 27 | const { width, height } = getDimensionsFromViewBox(svg) 28 | const innerSvg = getInnerSvg(svg) 29 | 30 | if (!svg) return false 31 | 32 | const Wrapper = component 33 | 34 | return ( 35 | 36 | 45 | 46 | ) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | parser: babel-eslint 2 | extends: airbnb 3 | env: 4 | browser: true 5 | jest: true 6 | rules: 7 | semi: 8 | - error 9 | - never 10 | react/no-danger: error 11 | react/no-comment-textnodes: off 12 | jsx-a11y/img-has-alt: off 13 | react/no-direct-mutation-state: error 14 | react/no-string-refs: error 15 | react/jsx-handler-names: error 16 | react/jsx-boolean-value: 17 | - error 18 | - never 19 | react/sort-comp: warn 20 | react/jsx-no-bind: 21 | - error 22 | - ignoreRefs: true 23 | allowArrowFunctions: false 24 | allowBind: false 25 | react/jsx-no-duplicate-props: error 26 | react/jsx-key: 27 | - error 28 | react/sort-prop-types: 29 | - error 30 | - ignoreCase: true 31 | callbacksLast: true 32 | requiredFirst: true 33 | react/jsx-sort-props: 34 | - error 35 | - callbacksLast: true 36 | shorthandFirst: true 37 | ignoreCase: true 38 | react/react-in-jsx-scope: error 39 | react/jsx-filename-extension: off 40 | import/no-extraneous-dependencies: off 41 | global-require: off 42 | no-underscore-dangle: off 43 | import/imports-first: off 44 | jsx-a11y/no-static-element-interactions: off 45 | jsx-a11y/anchor-has-content: off 46 | import/extensions: off 47 | comma-dangle: 48 | - error 49 | - arrays: always-multiline 50 | objects: always-multiline 51 | imports: always-multiline 52 | exports: always-multiline 53 | functions: never 54 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Storybook 10 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/Button.js: -------------------------------------------------------------------------------- 1 | import cx from 'classnames' 2 | import React, { Component } from 'react' 3 | import PropTypes from 'prop-types' 4 | 5 | export default class Button extends Component { 6 | 7 | static propTypes = { 8 | active: PropTypes.bool, 9 | className: PropTypes.string, 10 | danger: PropTypes.bool, 11 | large: PropTypes.bool, 12 | link: PropTypes.bool, 13 | primary: PropTypes.bool, 14 | secondary: PropTypes.bool, 15 | small: PropTypes.bool, 16 | text: PropTypes.bool, 17 | } 18 | 19 | static defaultProps = { 20 | type: 'button', 21 | active: false, 22 | primary: false, 23 | danger: false, 24 | link: false, 25 | small: false, 26 | large: false, 27 | className: '', 28 | secondary: false, 29 | text: false, 30 | } 31 | 32 | render() { 33 | const { 34 | active, 35 | primary, 36 | danger, 37 | link, 38 | small, 39 | large, 40 | secondary, 41 | text, 42 | className: customClassName, 43 | ...other 44 | } = this.props 45 | const className = cx('uk-button', customClassName, { 46 | 'uk-button-default': !primary && !secondary && !danger && !text && !link, 47 | 'uk-button-primary': primary, 48 | 'uk-button-secondary': secondary, 49 | 'uk-button-danger': danger, 50 | 'uk-button-text': text, 51 | 'uk-button-link': link, 52 | 'uk-button-small': small, 53 | 'uk-button-large': large, 54 | 'uk-active': active, 55 | }) 56 | 57 | return ( 58 | 10 | `; 11 | 12 | exports[`Button renders correctly 2`] = ` 13 | 19 | `; 20 | 21 | exports[`Button renders correctly 3`] = ` 22 | 28 | `; 29 | 30 | exports[`Button renders correctly 4`] = ` 31 | 37 | `; 38 | 39 | exports[`Button renders correctly 5`] = ` 40 | 47 | `; 48 | 49 | exports[`Button renders correctly 6`] = ` 50 | 56 | `; 57 | 58 | exports[`Button renders correctly 7`] = ` 59 | 65 | `; 66 | 67 | exports[`Button renders correctly 8`] = ` 68 | 74 | `; 75 | 76 | exports[`Button renders correctly 9`] = ` 77 | 83 | `; 84 | 85 | exports[`Button renders correctly 10`] = ` 86 | 93 | `; 94 | -------------------------------------------------------------------------------- /src/Notification/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import PropTypes from 'prop-types' 3 | import Portal from 'react-portal' 4 | import cx from 'classnames' 5 | 6 | import NotifyMesssage from './NotifyMesssage' 7 | 8 | export default class Notification extends Component { 9 | static propTypes = { 10 | notifications: PropTypes.arrayOf(PropTypes.object).isRequired, 11 | position: PropTypes.string, 12 | } 13 | 14 | static defaultProps = { 15 | className: 'uk-notification', 16 | notifications: [], 17 | position: 'top-center', 18 | type: 'primary', 19 | } 20 | 21 | state = { 22 | isOpened: false, 23 | } 24 | 25 | handleClick = () => { 26 | this.setState({ 27 | isOpened: true, 28 | }) 29 | } 30 | 31 | render() { 32 | const { 33 | position, 34 | notifications, 35 | } = this.props 36 | 37 | const className = cx('uk-notification', { 38 | 'uk-notification-top-center': position === 'top-center', 39 | 'uk-notification-top-left': position === 'top-left', 40 | 'uk-notification-top-right': position === 'top-right', 41 | 'uk-notification-bottom-center': position === 'bottom-center', 42 | 'uk-notification-bottom-left': position === 'bottom-left', 43 | 'uk-notification-bottom-right': position === 'bottom-right', 44 | }) 45 | return ( 46 | 0} 48 | onClose={this.handleClick} 49 | > 50 |
51 | {notifications.map(({ type, message, id, icon, isSticky, onClick, timeout }) => ( 52 | 60 | {message} 61 | 62 | ))} 63 |
64 |
65 | ) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Notification/__tests__/__snapshots__/index-test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Notification should render correctly 1`] = ` 4 | 8 |
11 |
21 | 25 | 30 | 31 | 32 | ", 33 | } 34 | } 35 | height={14} 36 | icon="close-icon" 37 | viewBox="0 0 14 14" 38 | width={14} 39 | xmlns="http://www.w3.org/2000/svg" 40 | /> 41 | 42 |
45 | 48 | ", 52 | } 53 | } 54 | height={20} 55 | icon="check" 56 | viewBox="0 0 20 20" 57 | width={20} 58 | xmlns="http://www.w3.org/2000/svg" 59 | /> 60 | 61 |   62 | Notification #1 63 |
64 |
65 |
66 |
67 | `; 68 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import 'uikit/src/less/uikit.theme.less' 2 | 3 | import infoAddon from '@storybook/addon-info' 4 | import { configure, setAddon, addDecorator } from '@storybook/react' 5 | 6 | import Logo from './Logo' 7 | 8 | setAddon(infoAddon) 9 | 10 | addDecorator((fn, { kind, story }) =>
11 |