├── .editorconfig ├── .gitignore ├── .npmignore ├── .npmrc ├── .storybook ├── addons.js └── config.js ├── LICENSE ├── README.md ├── docs ├── favicon.ico ├── iframe.html ├── index.html └── static │ ├── manager.35104b144a2585984051.bundle.js │ └── preview.8d9b32df9f0e3651dea3.bundle.js ├── package.json ├── react-selected.png ├── rollup.config.js └── src ├── __stories__ └── index.stories.js └── index.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.yml] 11 | indent_style = space 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn.lock 3 | yarn-error.log 4 | lib/ 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-actions/register'; 2 | import '@storybook/addon-links/register'; 3 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure } from '@storybook/react'; 2 | 3 | // automatically import all files ending in *.stories.js 4 | const req = require.context('../src/__stories__', true, /.stories.js$/); 5 | function loadStories() { 6 | req.keys().forEach((filename) => req(filename)); 7 | } 8 | 9 | configure(loadStories, module); 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Jake Moxey 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Selected 2 | 3 | > React component to build flexible and accessible radio buttons/elements. 4 | 5 | Listen to [Belinda Carlisle - Summer Rain](https://www.youtube.com/watch?v=wssIZOBV9i4) while reading these docs - it will increase comprehensibility by 120%. [This](https://youtu.be/R_TcZ-ATihY?t=5m10s) will increase it by 420%. 6 | 7 |

8 | 9 | ## Why should I use this? 10 | 11 | React Selected has control over select logic and state meaning that you don't have to do much! It also has the ability to add WAI-ARIA compliant and other accessibility attributes to the selectable elements. 12 | 13 | ## Install 14 | 15 | `npm install react-selected` 16 | 17 | ## Example 18 | 19 | ```jsx 20 | import Selected from 'react-selected'; 21 | 22 | 23 | {({ getSelectableProps, selectedKey }) => ( 24 | 25 | 28 | 31 | 34 | 35 | )} 36 | 37 | ``` 38 | 39 | ### More examples 40 | 41 | - [Storybook](https://jxom.github.io/react-selected/) 42 | - [Storybook Stories](https://github.com/jxom/react-selected/blob/master/src/__stories__/index.stories.js) 43 | 44 | ## Props 45 | 46 | ### defaultSelectedKey 47 | 48 | Type: `string` 49 | 50 | The key of the component that should be selected by default. 51 | 52 | ### onSelect 53 | 54 | Type: `function({ key, value })` 55 | 56 | Function to invoke when a component is selected. 57 | 58 | ### selectedKey 59 | 60 | Type: `string` 61 | 62 | React Selected manages select logic and state internally, but if you wish to have your own, you can control the value of `selectedKey`. 63 | 64 | ### Render props 65 | 66 | #### getSelectableProps 67 | 68 | Type: `function(key, value, props)` **(`key` is required)** 69 | 70 | Returns the props to apply to the button element you render. 71 | Includes `aria-` attributes. 72 | 73 | #### getElementSelectableProps 74 | 75 | Type: `function(key, value, props)` **(`key` is required)** 76 | 77 | Returns the props to apply to the element you render. Use this for any element other than a <button>. 78 | Includes aria- attributes. 79 | 80 | #### select 81 | 82 | Type: `function(key, value)` 83 | 84 | Sets `selectedKey` to `key` and sets `selectedValue` to `value`. 85 | 86 | #### selectedKey 87 | 88 | Type: `string` 89 | 90 | The key of the current selected component. 91 | 92 | #### selectedValue 93 | 94 | Type: `string` 95 | 96 | The value of the current selected component. 97 | 98 | ## Inspiration 99 | 100 | - [Downshift](https://github.com/paypal/downshift) 101 | - [React Toggled](https://github.com/kentcdodds/react-toggled) 102 | 103 | ## License 104 | 105 | MIT © [jxom](http://jxom.io) 106 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxom/react-selected/9cb92a94b6588afe7671fff9b29d2b2b2e5e3172/docs/favicon.ico -------------------------------------------------------------------------------- /docs/iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 18 | Storybook 19 | 20 | 21 | 22 | 23 |
24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Storybook 9 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-selected", 3 | "version": "1.0.0", 4 | "description": "A react component to handle select state", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "build": "npm run clean && rollup -c rollup.config.js", 8 | "clean": "rimraf lib/", 9 | "develop": "rollup -c rollup.config.js -w", 10 | "lint": "eslint src/", 11 | "lint:fix": "eslint src/ --fix", 12 | "test": "npm run lint", 13 | "prepublish": "npm run lint && npm run build", 14 | "storybook": "start-storybook -p 6006", 15 | "build-storybook": "build-storybook -o docs/" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/jxom/react-selected.git" 20 | }, 21 | "keywords": [ 22 | "react" 23 | ], 24 | "author": "Jake Moxey", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/jxom/react-selected/issues" 28 | }, 29 | "homepage": "https://github.com/jxom/react-selected#readme", 30 | "peerDependencies": { 31 | "react": "^16.0.0" 32 | }, 33 | "devDependencies": { 34 | "@medipass/eslint-config-react-medipass": "8.3.0", 35 | "@storybook/addon-actions": "^3.4.6", 36 | "@storybook/addon-links": "^3.4.6", 37 | "@storybook/addons": "^3.4.6", 38 | "@storybook/react": "^3.4.6", 39 | "babel-cli": "6.26.0", 40 | "babel-core": "6.26.0", 41 | "babel-eslint": "8.2.1", 42 | "babel-plugin-external-helpers": "6.22.0", 43 | "babel-plugin-transform-class-properties": "6.24.1", 44 | "babel-plugin-transform-object-rest-spread": "6.26.0", 45 | "babel-preset-env": "1.6.1", 46 | "babel-preset-react": "6.24.1", 47 | "bulma": "0.7.1", 48 | "eslint": "4.16.0", 49 | "eslint-config-react-app": "2.1.0", 50 | "eslint-plugin-flowtype": "2.41.0", 51 | "eslint-plugin-import": "2.12.0", 52 | "eslint-plugin-jsx-a11y": "6.0.3", 53 | "eslint-plugin-prettier": "2.5.0", 54 | "eslint-plugin-react": "7.5.1", 55 | "flow-bin": "0.72.0", 56 | "prettier": "1.12.1", 57 | "prop-types": "15.6.1", 58 | "react": "16.4.0", 59 | "react-dom": "16.4.0", 60 | "rebul": "1.0.0-canary.15", 61 | "rimraf": "2.6.2", 62 | "rollup": "^0.54.1", 63 | "rollup-plugin-babel": "^3.0.3", 64 | "rollup-plugin-uglify": "3.0.0", 65 | "uglify-es": "3.3.9" 66 | }, 67 | "eslintConfig": { 68 | "extends": [ 69 | "@medipass/react-medipass" 70 | ] 71 | }, 72 | "dependencies": {} 73 | } 74 | -------------------------------------------------------------------------------- /react-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jxom/react-selected/9cb92a94b6588afe7671fff9b29d2b2b2e5e3172/react-selected.png -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import uglify from 'rollup-plugin-uglify'; 3 | import { minify } from 'uglify-es'; 4 | 5 | export default { 6 | input: `${__dirname}/src/index.js`, 7 | output: { 8 | name: 'Selected', 9 | file: `${__dirname}/lib/index.js`, 10 | format: 'umd', 11 | globals: { 12 | react: 'React', 13 | 'prop-types': 'PropTypes' 14 | } 15 | }, 16 | external: ['react', 'prop-types'], 17 | plugins: [ 18 | babel({ 19 | presets: [['env', { modules: false }], 'react'], 20 | plugins: ['external-helpers', 'transform-class-properties', 'transform-object-rest-spread'] 21 | }), 22 | uglify({}, minify) 23 | ] 24 | }; 25 | -------------------------------------------------------------------------------- /src/__stories__/index.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react'; 3 | import Buttons from 'rebul/Button/Buttons'; 4 | import Button from 'rebul/Button'; 5 | import 'bulma/css/bulma.css'; 6 | 7 | import Selected from '../index'; 8 | 9 | storiesOf('Selected', module) 10 | .add('basic (with buttons)', () => ( 11 | 12 | {({ getSelectableProps, selectedKey }) => ( 13 | 14 | 17 | 20 | 23 | 24 | )} 25 | 26 | )) 27 | .add('basic (without buttons)', () => ( 28 | 29 | {({ getElementSelectableProps, selectedKey }) => ( 30 | 31 | 32 | Dog 33 | 34 | 35 | Cat 36 | 37 | 38 | Mouse 39 | 40 | 41 | )} 42 | 43 | )) 44 | .add('with onSelect handler', () => ( 45 | alert(key)}> 46 | {({ getSelectableProps, selectedKey }) => ( 47 | 48 | 51 | 54 | 57 | 58 | )} 59 | 60 | )) 61 | .add('with values', () => ( 62 | alert(`key: ${key}, value: ${JSON.stringify(value)}`)} 65 | > 66 | {({ getSelectableProps, selectedKey }) => ( 67 | 68 | 71 | 74 | 77 | 78 | )} 79 | 80 | )) 81 | .add('override default selectable props', () => ( 82 | alert(`key: ${key}, value: ${JSON.stringify(value)}`)} 85 | > 86 | {({ getSelectableProps, selectedKey }) => ( 87 | 88 | 94 | 100 | 106 | 107 | )} 108 | 109 | )); 110 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | const ELEMENT_SELECT_TRIGGER_KEYS = ['Enter', ' ']; // Mimics