Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Tag): add new bq-tag component #695

Merged
merged 51 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
55c8f5e
feat(Tag): add basic bq-tag component structure
Cata1989 Dec 7, 2023
93f13ca
feat(Tag): add basic markup for bq-tag
Cata1989 Dec 8, 2023
b97f03e
feat(Tag): add bq-tag component sizes and some style
Cata1989 Dec 8, 2023
d2c0568
feat(Tag): add more style and some props to bq-tag component
Cata1989 Dec 11, 2023
12d532c
feat(Tag): add disabled state for bq-tag component
Cata1989 Dec 11, 2023
031bc4c
feat(Tag): adjust disabled state
Cata1989 Dec 12, 2023
be9332c
feat(Tag): add color story for bq-tag component
Cata1989 Dec 12, 2023
a45352c
feat(Tag): add more stories to display bq-tag
Cata1989 Dec 12, 2023
f4281c7
feat(Tag): add bq-tag usage description
Cata1989 Dec 13, 2023
ac73c43
feat(Tag): add active clickable state for bq-tag
Cata1989 Dec 13, 2023
25decd7
feat(Tag): add role to bq-tag element
Cata1989 Dec 13, 2023
e7d2478
feat(Tag): change role
Cata1989 Dec 13, 2023
9a612f8
feat(Tag): add focus event to bq-tag
Cata1989 Dec 13, 2023
1a24c41
feat(Tag): add tabindex for focus
Cata1989 Dec 13, 2023
835f10e
feat(Tag): refactor empty slot and replace tab with button role
Cata1989 Dec 14, 2023
d65a972
feat(Tag): split color story and refactor CSS style
Cata1989 Dec 14, 2023
8eec1f9
feat(Tag): change isRemovable with removable and avoid triggering the…
Cata1989 Dec 14, 2023
702d825
feat(Tag): use disabled attribute and refactor CSS states
Cata1989 Dec 14, 2023
fe5fc72
feat(Tag): add e2e tests for bq-tag
Cata1989 Dec 15, 2023
4d01aae
feat(Tag): revert to correct small bq-button style
Cata1989 Dec 19, 2023
ef34f02
feat(Tag): add removable action for colored tags and update close ico…
Cata1989 Dec 19, 2023
0a21373
feat(Tag): add private get tagColor method inside the component
Cata1989 Dec 19, 2023
02cf2df
feat(Tag): use upper case for constants
Cata1989 Dec 19, 2023
269f2d1
feat(Tag): replace selected with clickable and isolate clickable effect
Cata1989 Dec 20, 2023
e8357d2
feat(Tag): ensure removable tag is not clickable
Cata1989 Dec 20, 2023
448f00e
feat: add helper for tag icon size and text color
dgonzalezr Dec 20, 2023
5c1582b
refactor: add private get methods for isClickable, isRemovable and is…
dgonzalezr Dec 20, 2023
3a5e1e3
refactor: tag TS types
dgonzalezr Dec 20, 2023
9d916d9
refactor: change component props
dgonzalezr Dec 20, 2023
eabb46c
fix: improve hide/show handlers
dgonzalezr Dec 20, 2023
ebed086
fix: delegate focus and remove leftover
dgonzalezr Dec 20, 2023
c8eac77
refactor: improve style to match the new changes
dgonzalezr Dec 20, 2023
f2a41bb
docs: autogenerated doc
dgonzalezr Dec 20, 2023
ff979d6
refactor(size): use `xsmall` instead of `extra_small`
dgonzalezr Dec 20, 2023
7ef1114
docs: update storybook
dgonzalezr Dec 20, 2023
0634240
test: update e2e tests
dgonzalezr Dec 20, 2023
6f639f8
feat(Tag): sort props in alphabetical order
Cata1989 Dec 21, 2023
f48e7d7
feat(Tag): add bqOpen and bqClose events for when the tag si hidden/s…
Cata1989 Dec 21, 2023
57147fd
feat(Tag): remove unused events and rename the old ones
Cata1989 Dec 21, 2023
9bf28bc
feat(Tag): remove unused events and rename the old ones
Cata1989 Dec 21, 2023
5248860
feat(Tag): update readme.md
Cata1989 Dec 21, 2023
9c2dcaa
feat(Tag): add bqBlur event when tag loses focus
Cata1989 Dec 21, 2023
1fc0891
feat(CSS): add more CSS variables
dgonzalezr Dec 21, 2023
0720acf
feat: add `border` prop to allow border-radius customization
dgonzalezr Dec 21, 2023
c6eda97
feat: add CSS variable for gap
dgonzalezr Dec 21, 2023
5c4c037
fix: slotted prefix icon size
dgonzalezr Dec 21, 2023
6370185
docs: update storybook examples
dgonzalezr Dec 21, 2023
3dfb773
fix: prop document typo
dgonzalezr Dec 21, 2023
949258a
fix: use inline block in the host
dgonzalezr Dec 21, 2023
a9dda48
fix: remove unnecessary event stops on bqBlur
dgonzalezr Dec 21, 2023
c484443
docs: missing events in Storybook
dgonzalezr Dec 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions packages/beeq/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { TStepsSize, TStepsType } from "./components/steps/bq-steps.types";
import { TStepItemStatus } from "./components/step-item/bq-step-item.types";
import { TSwitchInnerLabel, TSwitchJustifyContent } from "./components/switch/bq-switch.types";
import { TTabSize } from "./components/tab/bq-tab.types";
import { TTagBorderRadius, TTagColor, TTagSize, TTagVariant } from "./components/tag/bq-tag.types";
import { TTextareaAutoCapitalize, TTextareaWrap } from "./components/textarea/bq-textarea.types";
import { TToastPlacement, TToastType } from "./components/toast/bq-toast.types";
export { TAccordionAppearance, TAccordionSize } from "./components/accordion/bq-accordion.types";
Expand All @@ -49,6 +50,7 @@ export { TStepsSize, TStepsType } from "./components/steps/bq-steps.types";
export { TStepItemStatus } from "./components/step-item/bq-step-item.types";
export { TSwitchInnerLabel, TSwitchJustifyContent } from "./components/switch/bq-switch.types";
export { TTabSize } from "./components/tab/bq-tab.types";
export { TTagBorderRadius, TTagColor, TTagSize, TTagVariant } from "./components/tag/bq-tag.types";
export { TTextareaAutoCapitalize, TTextareaWrap } from "./components/textarea/bq-textarea.types";
export { TToastPlacement, TToastType } from "./components/toast/bq-toast.types";
export namespace Components {
Expand Down Expand Up @@ -1001,6 +1003,52 @@ export namespace Components {
*/
"value": string;
}
interface BqTag {
/**
* The corner radius of the Tag (will override size's predefined border)
*/
"border": TTagBorderRadius;
/**
* If true, the Tag can be clickable
*/
"clickable": boolean;
/**
* The color style of the Tag
*/
"color": TTagColor;
/**
* If true, the Tag will be disabled (only if clickable = `true`, no interaction allowed)
*/
"disabled"?: boolean;
/**
* If true, the Tag component will hidden (only if removable = `true`)
*/
"hidden": boolean;
/**
* Method to be called to remove the tag component
*/
"hide": () => Promise<void>;
/**
* If true, the Tag component can be removed
*/
"removable": boolean;
/**
* If true, the Tag is selected (only if clickable = `true`)
*/
"selected": boolean;
/**
* Method to be called to show the tag component
*/
"show": () => Promise<void>;
/**
* The size of the Tag component
*/
"size": TTagSize;
/**
* The variant of Tag to apply on top of the variant
*/
"variant": TTagVariant;
}
interface BqTextarea {
/**
* If `true`, the textarea will automatically grow and shrink to fit its contents. If `false`, the textarea will have a fixed height specified by the `rows` property.
Expand Down Expand Up @@ -1238,6 +1286,10 @@ export interface BqTabGroupCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLBqTabGroupElement;
}
export interface BqTagCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLBqTagElement;
}
export interface BqTextareaCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLBqTextareaElement;
Expand Down Expand Up @@ -1750,6 +1802,27 @@ declare global {
prototype: HTMLBqTabGroupElement;
new (): HTMLBqTabGroupElement;
};
interface HTMLBqTagElementEventMap {
"bqClose": any;
"bqOpen": any;
"bqBlur": HTMLBqTagElement;
"bqClick": HTMLBqTagElement;
"bqFocus": HTMLBqTagElement;
}
interface HTMLBqTagElement extends Components.BqTag, HTMLStencilElement {
addEventListener<K extends keyof HTMLBqTagElementEventMap>(type: K, listener: (this: HTMLBqTagElement, ev: BqTagCustomEvent<HTMLBqTagElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof HTMLBqTagElementEventMap>(type: K, listener: (this: HTMLBqTagElement, ev: BqTagCustomEvent<HTMLBqTagElementEventMap[K]>) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
var HTMLBqTagElement: {
prototype: HTMLBqTagElement;
new (): HTMLBqTagElement;
};
interface HTMLBqTextareaElementEventMap {
"bqBlur": HTMLBqTextareaElement;
"bqChange": { value: string; el: HTMLBqTextareaElement };
Expand Down Expand Up @@ -1829,6 +1902,7 @@ declare global {
"bq-switch": HTMLBqSwitchElement;
"bq-tab": HTMLBqTabElement;
"bq-tab-group": HTMLBqTabGroupElement;
"bq-tag": HTMLBqTagElement;
"bq-textarea": HTMLBqTextareaElement;
"bq-toast": HTMLBqToastElement;
"bq-tooltip": HTMLBqTooltipElement;
Expand Down Expand Up @@ -2941,6 +3015,64 @@ declare namespace LocalJSX {
*/
"value"?: string;
}
interface BqTag {
/**
* The corner radius of the Tag (will override size's predefined border)
*/
"border"?: TTagBorderRadius;
/**
* If true, the Tag can be clickable
*/
"clickable"?: boolean;
/**
* The color style of the Tag
*/
"color"?: TTagColor;
/**
* If true, the Tag will be disabled (only if clickable = `true`, no interaction allowed)
*/
"disabled"?: boolean;
/**
* If true, the Tag component will hidden (only if removable = `true`)
*/
"hidden"?: boolean;
/**
* Handler to be called when tag loses focus
*/
"onBqBlur"?: (event: BqTagCustomEvent<HTMLBqTagElement>) => void;
/**
* Handler to be called when tag is clicked
*/
"onBqClick"?: (event: BqTagCustomEvent<HTMLBqTagElement>) => void;
/**
* Callback handler to be called when the tag is close/hidden
*/
"onBqClose"?: (event: BqTagCustomEvent<any>) => void;
/**
* Handler to be called when tag is focused
*/
"onBqFocus"?: (event: BqTagCustomEvent<HTMLBqTagElement>) => void;
/**
* Callback handler to be called when the tag is not open/shown
*/
"onBqOpen"?: (event: BqTagCustomEvent<any>) => void;
/**
* If true, the Tag component can be removed
*/
"removable"?: boolean;
/**
* If true, the Tag is selected (only if clickable = `true`)
*/
"selected"?: boolean;
/**
* The size of the Tag component
*/
"size"?: TTagSize;
/**
* The variant of Tag to apply on top of the variant
*/
"variant"?: TTagVariant;
}
interface BqTextarea {
/**
* If `true`, the textarea will automatically grow and shrink to fit its contents. If `false`, the textarea will have a fixed height specified by the `rows` property.
Expand Down Expand Up @@ -3127,6 +3259,7 @@ declare namespace LocalJSX {
"bq-switch": BqSwitch;
"bq-tab": BqTab;
"bq-tab-group": BqTabGroup;
"bq-tag": BqTag;
"bq-textarea": BqTextarea;
"bq-toast": BqToast;
"bq-tooltip": BqTooltip;
Expand Down Expand Up @@ -3182,6 +3315,7 @@ declare module "@stencil/core" {
"bq-switch": LocalJSX.BqSwitch & JSXBase.HTMLAttributes<HTMLBqSwitchElement>;
"bq-tab": LocalJSX.BqTab & JSXBase.HTMLAttributes<HTMLBqTabElement>;
"bq-tab-group": LocalJSX.BqTabGroup & JSXBase.HTMLAttributes<HTMLBqTabGroupElement>;
"bq-tag": LocalJSX.BqTag & JSXBase.HTMLAttributes<HTMLBqTagElement>;
"bq-textarea": LocalJSX.BqTextarea & JSXBase.HTMLAttributes<HTMLBqTextareaElement>;
"bq-toast": LocalJSX.BqToast & JSXBase.HTMLAttributes<HTMLBqToastElement>;
"bq-tooltip": LocalJSX.BqTooltip & JSXBase.HTMLAttributes<HTMLBqTooltipElement>;
Expand Down
2 changes: 2 additions & 0 deletions packages/beeq/src/components/button/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Buttons are designed for users to take action on a page or a screen.
- [bq-input](../input)
- [bq-notification](../notification)
- [bq-select](../select)
- [bq-tag](../tag)

### Depends on

Expand All @@ -69,6 +70,7 @@ graph TD;
bq-input --> bq-button
bq-notification --> bq-button
bq-select --> bq-button
bq-tag --> bq-button
style bq-button fill:#f9f,stroke:#333,stroke-width:4px
```

Expand Down
2 changes: 2 additions & 0 deletions packages/beeq/src/components/icon/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Icons are simplified images that graphically explain the meaning of an object on
- [bq-notification](../notification)
- [bq-select](../select)
- [bq-switch](../switch)
- [bq-tag](../tag)
- [bq-toast](../toast)

### Graph
Expand All @@ -59,6 +60,7 @@ graph TD;
bq-notification --> bq-icon
bq-select --> bq-icon
bq-switch --> bq-icon
bq-tag --> bq-icon
bq-toast --> bq-icon
style bq-icon fill:#f9f,stroke:#333,stroke-width:4px
```
Expand Down
116 changes: 116 additions & 0 deletions packages/beeq/src/components/tag/__tests__/bq-tag.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { newE2EPage } from '@stencil/core/testing';

import { computedStyle } from '../../../shared/test-utils';

describe('bq-tag', () => {
it('should render', async () => {
const page = await newE2EPage({
html: '<bq-tag></bq-tag>',
});
const element = await page.find('bq-tag');

expect(element).toHaveClass('hydrated');
});

it('should have shadow root', async () => {
const page = await newE2EPage({
html: '<bq-tag></bq-tag>',
});
const element = await page.find('bq-tag');

expect(element.shadowRoot).not.toBeNull();
});

it('should render as hidden', async () => {
const page = await newE2EPage({
html: `<bq-tag removable hidden></bq-tag>`,
});

const element = await page.find('bq-tag');
expect(element).toEqualAttribute('aria-hidden', 'true');
});

it('should render as hidden with `hidden="true"`', async () => {
const page = await newE2EPage({
html: `<bq-tag removable hidden="true"></bq-tag>`,
});

const element = await page.find('bq-tag');
expect(element).toEqualAttribute('aria-hidden', 'true');
});

it('should render as open', async () => {
const page = await newE2EPage({
html: `<bq-tag></bq-tag>`,
});

const element = await page.find('bq-tag');
expect(element).toEqualAttribute('aria-hidden', 'false');
expect(element).not.toHaveClass('is-hidden');
});

it('should render as open with `hidden="false"`', async () => {
const page = await newE2EPage({
html: `<bq-tag hidden="false"></bq-tag>`,
});

const element = await page.find('bq-tag');
expect(element).toEqualAttribute('aria-hidden', 'false');
expect(element).not.toHaveClass('is-hidden');
});

it('should render a removable tag component', async () => {
const page = await newE2EPage({
html: `<bq-tag removable>Tag</bq-tag>`,
});

const element = await page.find('bq-tag >>> bq-icon[name="x-circle"]');
expect(element).not.toBeNull();
});

it('should render a basic tag without icon', async () => {
const page = await newE2EPage({
html: `<bq-tag>Tag</bq-tag>`,
});

const element = await page.find('bq-tag >>> slot');

expect(element).not.toBeNull();
});

it('should render a tag with a prefix (icon)', async () => {
const page = await newE2EPage({
html: `
<bq-tag>
<span slot="prefix">
<bq-icon name="star"></bq-icon>
</span>
Tag
</bq-tag>
`,
});

const prefixSlot = await page.find('bq-tag >>> slot[name="prefix"]');
expect(prefixSlot).not.toBeNull();
});

it('should respect design style', async () => {
const page = await newE2EPage({
html: `
<bq-tag size="xsmall">Tag</tag>
<bq-tag size="small">Tag</tag>
<bq-tag size="medium">Tag</tag>
`,
});

const styleProps = ['padding'] as const;

const extra_smallStyle = await computedStyle(page, 'bq-tag[size="xsmall"] >>> [part="wrapper"]', styleProps);
const smallStyle = await computedStyle(page, 'bq-tag[size="small"] >>> [part="wrapper"]', styleProps);
const mediumStyle = await computedStyle(page, 'bq-tag[size="medium"] >>> [part="wrapper"]', styleProps);

expect(extra_smallStyle).toEqual({ padding: '2px 8px' });
expect(smallStyle).toEqual({ padding: '2px 8px' });
expect(mediumStyle).toEqual({ padding: '4px 12px' });
});
});
27 changes: 27 additions & 0 deletions packages/beeq/src/components/tag/_storybook/bq-tag.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ArgTypes, Title, Subtitle } from '@storybook/addon-docs';

<div className="bq-doc__wrapper" data-theme="light">
<div className="bq-doc__container">
<Title>Tag</Title>

The Tag Component is a UI element used to label and categorize content within an application.
Tags are commonly used to label items with keywords or categories, making it easier to find and organize content.

<Subtitle>Usage</Subtitle>

- Use tags for labeling and categorizing items or content, such as tagging articles with keywords or categorizing items in a shopping cart.
- Use tags for representing metadata about an item or content, such as the author, date, or source of an article.
- Use tags for filtering and organizing content based on tags, such as allowing users to filter articles based on keywords or categories.
- Use clear and concise labels for tags, avoiding complex sentences and technical jargon.

<Subtitle>👍 When to use</Subtitle>

- When using tags, ensure that you position them in a location that is easily visible and accessible, without obstructing important content or interactions.
- When using tags, ensure the use of visually distinct styles and colors to differentiate between different types of tags, allowing users to easily recognize the meaning of each tag.
- Ensure that tags are easy to interact with, allowing users to click on a tag to view related content or to remove a tag if desired.

<Title>Properties</Title>

<ArgTypes of="bq-tag" />
</div>
</div>
Loading