From 2baf4202a9313375dcfe5c7382a8a3db37d0ba76 Mon Sep 17 00:00:00 2001 From: Adam Raider Date: Wed, 17 Apr 2019 16:22:42 -0400 Subject: [PATCH] feat(chip): add the chip component --- docs/components/chip.md | 12 ++++ docs/html/chip/chip.html | 1 + packages/core/src/components/chip/_chip.scss | 42 ++++++++++++ packages/core/src/components/chip/index.js | 68 +++++++++++++++++++ packages/core/src/components/index.js | 3 +- packages/core/src/ray-core.scss | 1 + packages/core/stories/chip.stories.js | 19 ++++++ .../src/data/navigation/navigation.json | 3 + 8 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 docs/components/chip.md create mode 100644 docs/html/chip/chip.html create mode 100644 packages/core/src/components/chip/_chip.scss create mode 100644 packages/core/src/components/chip/index.js create mode 100644 packages/core/stories/chip.stories.js diff --git a/docs/components/chip.md b/docs/components/chip.md new file mode 100644 index 00000000..923bbe32 --- /dev/null +++ b/docs/components/chip.md @@ -0,0 +1,12 @@ +--- +label: Component +title: Chip +--- + +Filter chips use tags or descriptive words to filter content. Filter chips clearly delineate and display options in a compact area. + + + diff --git a/docs/html/chip/chip.html b/docs/html/chip/chip.html new file mode 100644 index 00000000..ab1fd3a1 --- /dev/null +++ b/docs/html/chip/chip.html @@ -0,0 +1 @@ +
Neighborhoods
diff --git a/packages/core/src/components/chip/_chip.scss b/packages/core/src/components/chip/_chip.scss new file mode 100644 index 00000000..f4b6fc50 --- /dev/null +++ b/packages/core/src/components/chip/_chip.scss @@ -0,0 +1,42 @@ +@import '../../global/variables'; + +$ray-chip-border-width: 1px; +$ray-chip-height: $ray-spacing-xs * 2 + 1rem; + +.#{$ray-class-prefix}chip { + @include no-select; + border: $ray-chip-border-width solid $ray-color-blue-50; + background-color: $ray-color-white; + padding: $ray-spacing-xs $ray-spacing-md; + border-radius: $ray-chip-height; + color: $ray-color-blue-50; + display: inline-block; + cursor: pointer; + + &:not(:last-child) { + margin-right: $ray-spacing-xs; + } + + &:hover { + background-color: $ray-color-blue-10; + color: $ray-color-blue-50; + } + + &:focus { + box-shadow: $ray-box-shadow-focus-state; + } + + &:active { + background-color: $ray-color-blue-20; + } +} + +.#{$ray-class-prefix}chip--active { + background-color: $ray-color-blue-50; + color: $ray-color-white; + + &:hover { + background-color: $ray-color-blue-50; + color: $ray-color-white; + } +} diff --git a/packages/core/src/components/chip/index.js b/packages/core/src/components/chip/index.js new file mode 100644 index 00000000..cf8a5354 --- /dev/null +++ b/packages/core/src/components/chip/index.js @@ -0,0 +1,68 @@ +class Chip { + static instances = new WeakMap(); + + static get cssClasses() { + return {}; + } + + static get strings() { + return { + INIT_SELECTOR: '.ray-chip' + }; + } + + static create(element, options) { + return this.instances.get(element) || new this(element, options); + } + + static createAll(target = document, _options = { active: false }) { + // Finds all instances of select on the document or within a given element and instantiates them. + const options = { + initSelector: this.strings.INIT_SELECTOR, + ..._options + }; + + const chips = Array.from(target.querySelectorAll(options.initSelector)); + chips.forEach(select => this.create(select, options)); + } + + constructor(root, options) { + this._root = root; + + this.constructor.instances.set(this._root, this); + + this.state = { + active: options.active + }; + + this._bindEventListeners(); + this.assignClasses(); + } + + _bindEventListeners() { + this._root.addEventListener('mousedown', this.onMousedown); + } + + assignClasses() { + if (this.state.active) { + this._root.classList.add('ray-chip--active'); + } else { + this._root.classList.remove('ray-chip--active'); + } + } + + onMousedown = () => { + this.state.active = !this.state.active; + this.assignClasses(); + }; + + destroy() { + // Implement this method to release any resources / deregister any listeners they have + // attached. An example of this might be deregistering a resize event from the window object. + this._root.removeEventListener('mousedown', this.onMousedown); + + this.constructor.instances.delete(this._root); + } +} + +export default Chip; diff --git a/packages/core/src/components/index.js b/packages/core/src/components/index.js index 50270da6..0eed6fff 100644 --- a/packages/core/src/components/index.js +++ b/packages/core/src/components/index.js @@ -1,4 +1,5 @@ import Select from './select'; import { TextField, TextArea } from './text-field'; +import Chip from './chip'; -export { Select, TextField, TextArea }; +export { Select, TextField, TextArea, Chip }; diff --git a/packages/core/src/ray-core.scss b/packages/core/src/ray-core.scss index 59851bfd..c8de0009 100644 --- a/packages/core/src/ray-core.scss +++ b/packages/core/src/ray-core.scss @@ -10,6 +10,7 @@ @import './global/material-grid/mdc-layout-grid'; @import './components/card/card'; +@import './components/chip/chip'; @import './components/button/button'; @import './components/breadcrumb/breadcrumb'; @import './components/radio-checkbox/radio-checkbox'; diff --git a/packages/core/stories/chip.stories.js b/packages/core/stories/chip.stories.js new file mode 100644 index 00000000..2c840f75 --- /dev/null +++ b/packages/core/stories/chip.stories.js @@ -0,0 +1,19 @@ +import React from 'react'; +import { storiesOf } from '@storybook/react'; + +import Chip from '../src/components/chip'; + +function initChip() { + Chip.createAll(); +} + +/* eslint-disable no-script-url */ +storiesOf('Chip', module).add('default', () => { + setTimeout(initChip); + return ( + <> +
Neighborhoods
+
Offices
+ + ); +}); diff --git a/packages/docs-app/src/data/navigation/navigation.json b/packages/docs-app/src/data/navigation/navigation.json index f87e8fe9..073a7c80 100644 --- a/packages/docs-app/src/data/navigation/navigation.json +++ b/packages/docs-app/src/data/navigation/navigation.json @@ -46,6 +46,9 @@ "card": { "title": "Card" }, + "chip": { + "title": "Chip" + }, "image": { "title": "Image" },