Skip to content

Commit

Permalink
Merge pull request #209 from otto-de/B2BDS-208
Browse files Browse the repository at this point in the history
feat(core): [B2BDS-208] Add chip component
  • Loading branch information
AnnaHoege authored Sep 13, 2023
2 parents 1ee5137 + b74fa67 commit 19a0c30
Show file tree
Hide file tree
Showing 18 changed files with 426 additions and 38 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 55 additions & 2 deletions packages/core-components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
* It contains typing information for all components that exist in this project.
*/
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
import { CheckboxEventDetail, InputChangeEvent, InputClear, OptionSelectedEventDetail, RadioEventDetail, SearchClickEventDetail, ToggleButtonEventDetail } from "./utils/interfaces/form.interface";
import { CheckboxEventDetail, ChipComponentEventDetail, InputChangeEvent, InputClear, OptionSelectedEventDetail, RadioEventDetail, SearchClickEventDetail, ToggleButtonEventDetail } from "./utils/interfaces/form.interface";
import { IconName } from "./components/icon/types";
import { BeforeCloseEventDetail } from "./utils/interfaces/status.interface";
import { ColumnSortChangeEventDetail, PageChangeEventDetail, TabChangeEventDetail } from "./utils/interfaces/interaction.interface";
import { ContentAlignment, TableAccordionRowTypes, TableColourOptions, TableRowgroupTypes, TableSizes, TableSortDirections } from "./utils/types/table.types";
import { CheckboxEventDetail as CheckboxEventDetail1 } from "./components";
import { TableAccordionSelectedEventDetail } from "./utils/interfaces/content.interface";
import { WizardStatus, WizardSteps } from "./utils/types/wizard.types";
export { CheckboxEventDetail, InputChangeEvent, InputClear, OptionSelectedEventDetail, RadioEventDetail, SearchClickEventDetail, ToggleButtonEventDetail } from "./utils/interfaces/form.interface";
export { CheckboxEventDetail, ChipComponentEventDetail, InputChangeEvent, InputClear, OptionSelectedEventDetail, RadioEventDetail, SearchClickEventDetail, ToggleButtonEventDetail } from "./utils/interfaces/form.interface";
export { IconName } from "./components/icon/types";
export { BeforeCloseEventDetail } from "./utils/interfaces/status.interface";
export { ColumnSortChangeEventDetail, PageChangeEventDetail, TabChangeEventDetail } from "./utils/interfaces/interaction.interface";
Expand Down Expand Up @@ -196,6 +196,24 @@ export namespace Components {
*/
"required": boolean;
}
interface B2bChipComponent {
/**
* Whether the chip is disabled.
*/
"disabled": boolean;
/**
* Whether or not the chip component has a close button. Per default it is true.
*/
"hasCloseButton": boolean;
/**
* The text content of the chip. It is required.
*/
"label": string;
/**
* It is only used when the chip component participates in a group
*/
"value"?: any;
}
interface B2bDropdown {
/**
* Whether the select as a whole is disabled. Per default it is false.
Expand Down Expand Up @@ -922,6 +940,10 @@ export interface B2bCheckboxGroupCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLB2bCheckboxGroupElement;
}
export interface B2bChipComponentCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLB2bChipComponentElement;
}
export interface B2bDropdownCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLB2bDropdownElement;
Expand Down Expand Up @@ -1031,6 +1053,12 @@ declare global {
prototype: HTMLB2bCheckboxGroupElement;
new (): HTMLB2bCheckboxGroupElement;
};
interface HTMLB2bChipComponentElement extends Components.B2bChipComponent, HTMLStencilElement {
}
var HTMLB2bChipComponentElement: {
prototype: HTMLB2bChipComponentElement;
new (): HTMLB2bChipComponentElement;
};
interface HTMLB2bDropdownElement extends Components.B2bDropdown, HTMLStencilElement {
}
var HTMLB2bDropdownElement: {
Expand Down Expand Up @@ -1294,6 +1322,7 @@ declare global {
"b2b-card": HTMLB2bCardElement;
"b2b-checkbox": HTMLB2bCheckboxElement;
"b2b-checkbox-group": HTMLB2bCheckboxGroupElement;
"b2b-chip-component": HTMLB2bChipComponentElement;
"b2b-dropdown": HTMLB2bDropdownElement;
"b2b-grid": HTMLB2bGridElement;
"b2b-grid-col": HTMLB2bGridColElement;
Expand Down Expand Up @@ -1529,6 +1558,28 @@ declare namespace LocalJSX {
*/
"required"?: boolean;
}
interface B2bChipComponent {
/**
* Whether the chip is disabled.
*/
"disabled"?: boolean;
/**
* Whether or not the chip component has a close button. Per default it is true.
*/
"hasCloseButton"?: boolean;
/**
* The text content of the chip. It is required.
*/
"label": string;
/**
* This event will be triggered when the chip element is closed
*/
"onB2b-close"?: (event: B2bChipComponentCustomEvent<ChipComponentEventDetail>) => void;
/**
* It is only used when the chip component participates in a group
*/
"value"?: any;
}
interface B2bDropdown {
/**
* Whether the select as a whole is disabled. Per default it is false.
Expand Down Expand Up @@ -2345,6 +2396,7 @@ declare namespace LocalJSX {
"b2b-card": B2bCard;
"b2b-checkbox": B2bCheckbox;
"b2b-checkbox-group": B2bCheckboxGroup;
"b2b-chip-component": B2bChipComponent;
"b2b-dropdown": B2bDropdown;
"b2b-grid": B2bGrid;
"b2b-grid-col": B2bGridCol;
Expand Down Expand Up @@ -2395,6 +2447,7 @@ declare module "@stencil/core" {
"b2b-card": LocalJSX.B2bCard & JSXBase.HTMLAttributes<HTMLB2bCardElement>;
"b2b-checkbox": LocalJSX.B2bCheckbox & JSXBase.HTMLAttributes<HTMLB2bCheckboxElement>;
"b2b-checkbox-group": LocalJSX.B2bCheckboxGroup & JSXBase.HTMLAttributes<HTMLB2bCheckboxGroupElement>;
"b2b-chip-component": LocalJSX.B2bChipComponent & JSXBase.HTMLAttributes<HTMLB2bChipComponentElement>;
"b2b-dropdown": LocalJSX.B2bDropdown & JSXBase.HTMLAttributes<HTMLB2bDropdownElement>;
"b2b-grid": LocalJSX.B2bGrid & JSXBase.HTMLAttributes<HTMLB2bGridElement>;
"b2b-grid-col": LocalJSX.B2bGridCol & JSXBase.HTMLAttributes<HTMLB2bGridColElement>;
Expand Down
55 changes: 55 additions & 0 deletions packages/core-components/src/components/chip/chip.docs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {
Story,
ArgsTable,
PRIMARY_STORY,
Primary,
Source,
Canvas,
} from '@storybook/addon-docs';

# Singular Checkbox

<Canvas columns={3} withSource="open" withToolbar={false}>
<Story id="components-interaction-chip-component--story-010-default" />
</Canvas>

## Properties

### Label

The label of the chip which appears on the component. This is the only
required property.

### Required

Adds an asterisk at the end of the label to signify that the field is required. This would not perform any
validation, is just a style addition.

### Disabled

Whether or not the chip is disabled. If not specified, it will not be disabled.

### Value

The chip value. It does not have to be the same as the chip label. When the chip is closed,
the value gets emitted

### Close Button

Per default, all large alerts except the error alert have a close button. By setting `hasCloseButton` to false, you can remove it.

## Events

### b2b-close

Fires whenever the chip is closed by clicking on the clear button.

`ChipComponentEventDetail<T = any> {
value: T;
}`

## Attributes

<ArgsTable story={PRIMARY_STORY} />
Changes made to the attributes in the above table will reflect in the example below:
<Primary />
34 changes: 34 additions & 0 deletions packages/core-components/src/components/chip/chip.e2e.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { newE2EPage } from '@stencil/core/testing';

describe('B2B-Chip-Component', () => {
it('should render the chip component', async () => {
const page = await newE2EPage();
await page.setContent(
`<b2b-chip-component label="chip"></b2b-chip-component>`,
);

const chip = await page.find({ text: 'chip' });
const clearIcon = await page.find(
'b2b-chip-component >>> div.b2b-chip__clearIcon',
);
expect(chip).not.toBeNull();
expect(clearIcon).not.toBeNull();
});

it('should emit b2b-close event on clear icon click', async () => {
const page = await newE2EPage();
await page.setContent(
`<b2b-chip-component label="chip"></b2b-chip-component>`,
);

const b2bClose = await page.spyOnEvent('b2b-close');

const clearIcon = await page.find(
'b2b-chip-component >>> div.b2b-chip__clearIcon',
);

await clearIcon.click();

expect(b2bClose).toHaveReceivedEvent();
});
});
41 changes: 41 additions & 0 deletions packages/core-components/src/components/chip/chip.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
@use 'sass:color';
@use '../../global/b2b-styles';

.b2b-chip {
font-family: var(--b2b-font-family-default);
font-size: var(--b2b-size-copy-100);
width: fit-content;
background-color: var(--b2b-color-grey-50);
border-radius: var(--b2b-size-50);
padding: var(--b2b-size-10) var(--b2b-size-25);
line-height: var(--b2b-size-copy-line-height-100);
height: var(--b2b-size-70);
display: flex;
align-items: center;
cursor: default;

&__label {
margin-right: var(--b2b-size-10);
}

&__clearIcon {
display: flex;
fill: var(--b2b-color-icon-default);
height: var(--b2b-size-copy-line-height-100);
width: var(--b2b-size-50);
align-items: center;
justify-content: center;
cursor: pointer;
transform: rotate(180deg);
}
}

.b2b-chip--disabled {
pointer-events: none;
background: var(--b2b-color-grey-25);
color: var(--b2b-color-grey-400);

&__clearIcon {
fill: var(--b2b-color-grey-400);
}
}
51 changes: 51 additions & 0 deletions packages/core-components/src/components/chip/chip.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Meta, Story } from '@storybook/web-components';
import { html } from 'lit-html';
import chipComponentDocs from './chip.docs.mdx';
import { getArgTypes } from '../../docs/config/utils';

const Template: Story = ({ label, disabled, value, hasCloseButton }) => {
return html`<b2b-chip-component
label="${label}"
disabled="${disabled}"
value="${value}"
has-close-button="${hasCloseButton}"></b2b-chip-component>`;
};

const defaultArgs = {
label: 'Chip Label',
disabled: false,
value: '',
hasCloseButton: true,
};

export const story010Default = Template.bind({});
story010Default.args = { ...defaultArgs, label: 'Default Chip' };
story010Default.storyName = 'Default';

export const story020Disabled = Template.bind({});
story020Disabled.args = {
...defaultArgs,
label: 'Disabled Chip',
disabled: true,
};
story020Disabled.storyName = 'Disabled';
export const story030WithoutButton = Template.bind({});
story030WithoutButton.args = {
...defaultArgs,
label: ' Chip without button',
hasCloseButton: false,
};
story030WithoutButton.storyName = 'Without Button';

const chipComponentArgs = getArgTypes('b2b-chip-component');

export default {
title: 'Components/Interaction/Chip',
argTypes: chipComponentArgs,
viewMode: 'docs',
parameters: {
docs: {
page: chipComponentDocs,
},
},
} as Meta;
66 changes: 66 additions & 0 deletions packages/core-components/src/components/chip/chip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Component, Prop, h, Host, Event, EventEmitter } from '@stencil/core';
import { ChipComponentEventDetail } from '../../utils/interfaces/form.interface';

@Component({
tag: 'b2b-chip-component',
styleUrl: 'chip.scss',
shadow: true,
})
export class B2bChipComponent {
/** The text content of the chip. It is required. */
@Prop() label!: string;

/** Whether the chip is disabled. */
@Prop() disabled: boolean = false;

/** Whether or not the chip component has a close button. Per default it is true. */
@Prop() hasCloseButton: boolean = true;

/** It is only used when the chip component participates in a group */
@Prop({ reflect: true }) value?: any;

/** This event will be triggered when the chip element is closed */
@Event({ eventName: 'b2b-close' })
b2bClose: EventEmitter<ChipComponentEventDetail>;

private onClick = () => {
if (this.disabled) {
return;
}
this.b2bClose.emit({ value: this.value });
};

private clearIcon = (
<svg
width="12"
height="12"
viewBox="0 0 12 12"
xmlns="http://www.w3.org/2000/svg">
<path d="M7.85352 3.14648C7.6582 2.95117 7.3418 2.95117 7.14648 3.14648L5.5 4.79297L3.85352 3.14648C3.6582 2.95117 3.3418 2.95117 3.14648 3.14648C2.95117 3.3418 2.95117 3.6582 3.14648 3.85352L4.79297 5.5L3.14648 7.14648C2.95117 7.3418 2.95117 7.6582 3.14648 7.85352C3.24414 7.95117 3.37207 8 3.5 8C3.62793 8 3.75586 7.95117 3.85352 7.85352L5.5 6.20703L7.14648 7.85352C7.24414 7.95117 7.37207 8 7.5 8C7.62793 8 7.75586 7.95117 7.85352 7.85352C8.04883 7.6582 8.04883 7.3418 7.85352 7.14648L6.20703 5.5L7.85352 3.85352C8.04883 3.6582 8.04883 3.3418 7.85352 3.14648ZM5.5 0C2.46729 0 0 2.46729 0 5.5C0 8.53271 2.46729 11 5.5 11C8.53271 11 11 8.53271 11 5.5C11 2.46729 8.53271 0 5.5 0ZM5.5 10C3.01855 10 1 7.98145 1 5.5C1 3.01855 3.01855 1 5.5 1C7.98145 1 10 3.01855 10 5.5C10 7.98145 7.98145 10 5.5 10Z" />
</svg>
);

render() {
return (
<Host>
<div
class={{
'b2b-chip': true,
'b2b-chip--disabled': this.disabled,
}}>
<span class="b2b-chip__label">{this.label}</span>
{this.hasCloseButton && (
<div
class={{
'b2b-chip__clearIcon': true,
'b2b-chip--disabled__clearIcon': this.disabled,
}}
onClick={this.onClick}>
{this.clearIcon}
</div>
)}
</div>
</Host>
);
}
}
27 changes: 27 additions & 0 deletions packages/core-components/src/components/chip/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# b2b-chip-component



<!-- Auto Generated Below -->


## Properties

| Property | Attribute | Description | Type | Default |
| -------------------- | ------------------ | ----------------------------------------------------------------------------- | --------- | ----------- |
| `disabled` | `disabled` | Whether the chip is disabled. | `boolean` | `false` |
| `hasCloseButton` | `has-close-button` | Whether or not the chip component has a close button. Per default it is true. | `boolean` | `true` |
| `label` _(required)_ | `label` | The text content of the chip. It is required. | `string` | `undefined` |
| `value` | `value` | It is only used when the chip component participates in a group | `any` | `undefined` |


## Events

| Event | Description | Type |
| ----------- | ------------------------------------------------------------ | -------------------------------------------- |
| `b2b-close` | This event will be triggered when the chip element is closed | `CustomEvent<ChipComponentEventDetail<any>>` |


----------------------------------------------

*Built with [StencilJS](https://stenciljs.com/)*
Loading

0 comments on commit 19a0c30

Please sign in to comment.