diff --git a/src/components/v-chip/index.ts b/src/components/v-chip/index.ts
new file mode 100644
index 0000000000..587e4a84a2
--- /dev/null
+++ b/src/components/v-chip/index.ts
@@ -0,0 +1,4 @@
+import VChip from './v-chip.vue';
+
+export { VChip };
+export default VChip;
diff --git a/src/components/v-chip/v-chip.readme.md b/src/components/v-chip/v-chip.readme.md
new file mode 100644
index 0000000000..4adb77740c
--- /dev/null
+++ b/src/components/v-chip/v-chip.readme.md
@@ -0,0 +1,67 @@
+# Chip
+
+```html
+I'm a chip!
+```
+
+## Sizes
+
+The chip component supports the following sizes through the use of props:
+
+* x-small
+* small
+* (default)
+* large
+* x-large
+
+```html
+I'm a chip!
+```
+
+## Colors
+
+You can set the color, background color, hover color, and background hover color with the `color`, `background-color`, `hover-color`, and `hover-background-color` props respectively:
+
+```html
+
+ I'm a chip!
+
+```
+
+## Events
+
+There are two events, one when clicking on the chip called `click` and one when clicking on the enabled close icon called `close`.
+
+```html
+Hello!
+I'm closeable!
+```
+
+| Event | Description |
+|---------|------------------------------------------------------------------------------------------------|
+| `click` | Triggers when clicked somewhere on the chip |
+| `close` | Triggers when the `close` prop is enabled and gets clicked (Doesn't trigger the `click` event) |
+
+## Props
+
+| Prop | Description | Default |
+|--------------------------|------------------------------------------------------|-----------------------------------------|
+| `active` | Change visibility. Can be reacted to via `sync` | `true` |
+| `close` | Displays a close icon which triggers the close event | `false` |
+| `closeIcon` | Which icon should be displayed instead of `close ` | `close` |
+| `outlined` | No background | `false` |
+| `color` | Text color | `--chip-primary-text-color` |
+| `hover-color` | Text color on hover | `--chip-primary-text-color` |
+| `background-color` | Chip color | `--chip-primary-background-color` |
+| `hover-background-color` | Chip color on hover | `--chip-primary-background-color-hover` |
+| `label` | Label style | `false` |
+| `disabled` | Disabled state | `false` |
+| `x-small` | Render extra small | `false` |
+| `small` | Render small | `false` |
+| `large` | Render large | `false` |
+| `x-large` | Render extra large | `false` |
diff --git a/src/components/v-chip/v-chip.story.ts b/src/components/v-chip/v-chip.story.ts
new file mode 100644
index 0000000000..10f749dbdb
--- /dev/null
+++ b/src/components/v-chip/v-chip.story.ts
@@ -0,0 +1,261 @@
+import { withKnobs, text, boolean, number, optionsKnob as options } from '@storybook/addon-knobs';
+import { action } from '@storybook/addon-actions';
+import Vue from 'vue';
+import VChip from './v-chip.vue';
+import VIcon from '../v-icon/';
+import markdown from './v-chip.readme.md';
+import withPadding from '../../../.storybook/decorators/with-padding';
+
+Vue.component('v-chip', VChip);
+Vue.component('v-icon', VIcon);
+
+export default {
+ title: 'Components / Chip',
+ component: VChip,
+ decorators: [withKnobs, withPadding],
+ parameters: {
+ notes: markdown
+ }
+};
+
+export const withText = () => ({
+ methods: { onClick: action('click'), onClose: action('close') },
+ props: {
+ text: {
+ default: text('Text in chip', 'Click me')
+ },
+ label: {
+ default: boolean('Label', false, 'Button')
+ },
+ outlined: {
+ default: boolean('Outlined', false, 'Button')
+ },
+ size: {
+ default: options(
+ 'Size',
+ {
+ 'Extra Small': 'xSmall',
+ Small: 'small',
+ '(default)': 'default',
+ Large: 'large',
+ 'Extra Large': 'xLarge'
+ },
+ 'default',
+ {
+ display: 'select'
+ },
+ 'Button'
+ )
+ },
+ close: {
+ default: boolean('Close', false, 'Button')
+ },
+ disabled: {
+ default: boolean('Disabled', false, 'Button')
+ },
+ active: {
+ default: boolean('Active', true, 'Button')
+ },
+ color: {
+ default: text('Color', '--chip-primary-text-color', 'Colors')
+ },
+ backgroundColor: {
+ default: text('Background Color', '--chip-primary-background-color', 'Colors')
+ },
+ hoverColor: {
+ default: text('Color (hover)', '--chip-primary-text-color', 'Colors')
+ },
+ hoverBackgroundColor: {
+ default: text(
+ 'Background Color (hover)',
+ '--chip-primary-background-color-hover',
+ 'Colors'
+ )
+ }
+ },
+ template: `
+
+ {{ text }}
+
+ `
+});
+
+export const withIcon = () => ({
+ methods: { onClick: action('click'), onClose: action('close') },
+ props: {
+ iconName: {
+ default: text('Material Icon', 'add')
+ },
+ text: {
+ default: text('Text in chip', 'Click me')
+ },
+ label: {
+ default: boolean('Label', false, 'Button')
+ },
+ outlined: {
+ default: boolean('Outlined', false, 'Button')
+ },
+ size: {
+ default: options(
+ 'Size',
+ {
+ 'Extra Small': 'xSmall',
+ Small: 'small',
+ '(default)': 'default',
+ Large: 'large',
+ 'Extra Large': 'xLarge'
+ },
+ 'default',
+ {
+ display: 'select'
+ },
+ 'Button'
+ )
+ },
+ iconSize: {
+ default: options(
+ 'Size (Icon)',
+ {
+ 'Extra Small': 'xSmall',
+ Small: 'small',
+ '(default)': 'default',
+ Large: 'large',
+ 'Extra Large': 'xLarge'
+ },
+ 'default',
+ {
+ display: 'select'
+ },
+ 'Button'
+ )
+ },
+ close: {
+ default: boolean('Close', false, 'Button')
+ },
+ disabled: {
+ default: boolean('Disabled', false, 'Button')
+ },
+ active: {
+ default: boolean('Active', true, 'Button')
+ },
+ color: {
+ default: text('Color', '--chip-primary-text-color', 'Colors')
+ },
+ backgroundColor: {
+ default: text('Background Color', '--chip-primary-background-color', 'Colors')
+ },
+ hoverColor: {
+ default: text('Color (hover)', '--chip-primary-text-color', 'Colors')
+ },
+ hoverBackgroundColor: {
+ default: text(
+ 'Background Color (hover)',
+ '--chip-primary-background-color-hover',
+ 'Colors'
+ )
+ }
+ },
+ template: `
+
+
+ {{ text }}
+
+ `
+});
+
+export const withColor = () => ({
+ template: `
+
+
+
+ Delete
+
+
+
+ Add Item
+
+
+
+ Watch out
+
+
+ `
+});
+
+export const sizes = () => ({
+ template: `
+
+ Extra small
+ Small
+ Default
+ Large
+ Extra large
+
+ `
+});
diff --git a/src/components/v-chip/v-chip.test.ts b/src/components/v-chip/v-chip.test.ts
new file mode 100644
index 0000000000..5dda62a1d0
--- /dev/null
+++ b/src/components/v-chip/v-chip.test.ts
@@ -0,0 +1,183 @@
+import { mount, createLocalVue, Wrapper } from '@vue/test-utils';
+import VueCompositionAPI from '@vue/composition-api';
+import VChip from './v-chip.vue';
+import VIcon from '@/components/v-icon/';
+
+const localVue = createLocalVue();
+localVue.use(VueCompositionAPI);
+localVue.component('v-icon', VIcon);
+
+describe('Chip', () => {
+ let component: Wrapper;
+
+ beforeEach(() => {
+ component = mount(VChip, { localVue });
+ });
+
+ it('Renders the provided markup in the default slow', () => {
+ const component = mount(VChip, {
+ localVue,
+ slots: {
+ default: 'Click me'
+ }
+ });
+
+ expect(component.text()).toContain('Click me');
+ });
+
+ it('Hides the whole component', async () => {
+ component.setProps({
+ active: false
+ });
+
+ await component.vm.$nextTick();
+
+ expect(component.find('span').exists()).toBe(false);
+ });
+
+ it('Adds the outline class for outline chips', async () => {
+ component.setProps({
+ outlined: true
+ });
+
+ await component.vm.$nextTick();
+
+ expect(component.classes()).toContain('outlined');
+ });
+
+ it('Adds the label class for block chips', async () => {
+ component.setProps({
+ label: true
+ });
+
+ await component.vm.$nextTick();
+
+ expect(component.classes()).toContain('label');
+ });
+
+ it('Adds the close icon for icon chips', async () => {
+ component.setProps({
+ close: true
+ });
+
+ await component.vm.$nextTick();
+
+ expect(component.find('.close-outline').exists()).toBe(true);
+ });
+
+ it('Sets the correct CSS variables for custom colors', async () => {
+ component.setProps({
+ color: '--red',
+ hoverColor: '--blue',
+ backgroundColor: '--green',
+ hoverBackgroundColor: '--yellow'
+ });
+
+ await component.vm.$nextTick();
+
+ expect((component.vm as any).styles['--_v-chip-color']).toBe('var(--red)');
+ expect((component.vm as any).styles['--_v-chip-hover-color']).toBe('var(--blue)');
+ expect((component.vm as any).styles['--_v-chip-background-color']).toBe('var(--green)');
+ expect((component.vm as any).styles['--_v-chip-hover-background-color']).toBe(
+ 'var(--yellow)'
+ );
+ });
+
+ it('Emits a click event when chip is not disabled', async () => {
+ component.setProps({
+ disabled: false
+ });
+
+ await component.vm.$nextTick();
+
+ (component.vm as any).onClick(new Event('click'));
+
+ expect(component.emitted('click')[0][0]).toBeInstanceOf(Event);
+ });
+
+ it('Does not emit click when disabled', async () => {
+ component.setProps({
+ disabled: true
+ });
+
+ await component.vm.$nextTick();
+
+ (component.vm as any).onClick(new Event('click'));
+
+ expect(component.emitted('click')).toBe(undefined);
+ });
+
+ it('Emits a click event when chip is not disabled and close button is clicked', async () => {
+ component.setProps({
+ disabled: false
+ });
+
+ await component.vm.$nextTick();
+
+ (component.vm as any).onCloseClick(new Event('click'));
+
+ expect(component.emitted('close')[0][0]).toBeInstanceOf(Event);
+ });
+
+ it('Does not emit click when disabled and close button is clicked', async () => {
+ component.setProps({
+ disabled: true
+ });
+
+ await component.vm.$nextTick();
+
+ (component.vm as any).onCloseClick(new Event('click'));
+
+ expect(component.emitted('click')).toBe(undefined);
+ });
+
+ describe('Sizes', () => {
+ const component = mount(VChip, {
+ localVue,
+ propsData: {
+ color: '--blue-grey',
+ name: 'person'
+ }
+ });
+
+ test('Extra Small', () => {
+ component.setProps({
+ xSmall: true,
+ small: false,
+ large: false,
+ xLarge: false
+ });
+ component.vm.$nextTick(() => expect(component.classes()).toContain('x-small'));
+ });
+
+ test('Small', () => {
+ component.setProps({
+ xSmall: false,
+ small: true,
+ large: false,
+ xLarge: false
+ });
+ component.vm.$nextTick(() => expect(component.classes()).toContain('small'));
+ });
+
+ test('Large', () => {
+ component.setProps({
+ xSmall: false,
+ small: false,
+ large: true,
+ xLarge: false
+ });
+ component.vm.$nextTick(() => expect(component.classes()).toContain('large'));
+ });
+
+ test('Extra Large', () => {
+ component.setProps({
+ xSmall: false,
+ small: false,
+ large: false,
+ xLarge: true
+ });
+ component.vm.$nextTick(() => expect(component.classes()).toContain('x-large'));
+ });
+ });
+});
diff --git a/src/components/v-chip/v-chip.vue b/src/components/v-chip/v-chip.vue
new file mode 100644
index 0000000000..139dbb6b3a
--- /dev/null
+++ b/src/components/v-chip/v-chip.vue
@@ -0,0 +1,218 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/v-overlay/v-overlay.test.ts b/src/components/v-overlay/v-overlay.test.ts
index 7c9ba8ed47..1c8b0bbf89 100644
--- a/src/components/v-overlay/v-overlay.test.ts
+++ b/src/components/v-overlay/v-overlay.test.ts
@@ -1,4 +1,4 @@
-import { mount, createLocalVue, Wrapper } from '@vue/test-utils';
+import { shallowMount, createLocalVue, Wrapper } from '@vue/test-utils';
import VueCompositionAPI from '@vue/composition-api';
const localVue = createLocalVue();
@@ -10,19 +10,19 @@ describe('Overlay', () => {
let component: Wrapper;
beforeEach(() => {
- component = mount(VOverlay, {
+ component = shallowMount(VOverlay, {
localVue
});
});
it('Is invisible when active prop is false', () => {
- expect(component.isVisible()).toBe(false);
+ expect(component.classes()).toEqual(['v-overlay']);
});
it('Is visible when active is true', async () => {
component.setProps({ active: true });
await component.vm.$nextTick();
- expect(component.isVisible()).toBe(true);
+ expect(component.classes()).toEqual(['v-overlay', 'active']);
});
it('Sets position absolute based on absolute prop', async () => {
@@ -46,7 +46,7 @@ describe('Overlay', () => {
});
it('Adds the has-click class when click event is passed', async () => {
- const component = mount(VOverlay, {
+ const component = shallowMount(VOverlay, {
localVue,
listeners: {
click: () => {}
diff --git a/src/routes/debug.vue b/src/routes/debug.vue
new file mode 100644
index 0000000000..fc2e35de79
--- /dev/null
+++ b/src/routes/debug.vue
@@ -0,0 +1,9 @@
+
+ Debug
+
+
+
diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss
index 7aadab60f8..6b32c1b650 100644
--- a/src/styles/_variables.scss
+++ b/src/styles/_variables.scss
@@ -341,6 +341,18 @@ body {
--button-tertiary-background-color-disabled: var(--blue-grey-400);
--button-tertiary-text-color-disabled: var(--blue-grey-600);
+ // Chip colors
+
+ --chip-primary-text-color: var(--black);
+ --chip-primary-background-color: var(--blue-grey-100);
+ --chip-primary-background-color-hover: var(--blue-grey-200);
+ --chip-primary-close-color: var(--blue-grey-700);
+ --chip-primary-close-color-hover: var(--blue-grey-800);
+ --chip-primary-close-color-disabled: var(--blue-grey-200);
+ --chip-primary-background-color-disabled: var(--blue-grey-50);
+ --chip-primary-text-color-disabled: var(--blue-grey-300);
+
+
// Table
--table-head-border-color: var(--blue-grey-50);
diff --git a/src/views/public/public-view.test.ts b/src/views/public/public-view.test.ts
index 0360e82568..5d78ab0f9c 100644
--- a/src/views/public/public-view.test.ts
+++ b/src/views/public/public-view.test.ts
@@ -1,10 +1,12 @@
import VueCompositionAPI from '@vue/composition-api';
import { mount, createLocalVue } from '@vue/test-utils';
import { VTooltip } from 'v-tooltip';
+import VIcon from '@/components/v-icon/';
const localVue = createLocalVue();
localVue.use(VueCompositionAPI);
localVue.directive('tooltip', VTooltip);
+localVue.component('v-icon', VIcon);
import PublicView from './public-view.vue';