Skip to content

Commit

Permalink
feat(pie-tag): DSW-1520 tag component functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
dandel10n committed Dec 19, 2023
1 parent 373503f commit 9fbfea7
Show file tree
Hide file tree
Showing 17 changed files with 606 additions and 74 deletions.
5 changes: 5 additions & 0 deletions .changeset/good-shoes-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@justeattakeaway/pie-webc-testing": minor
---

[Added] - getShadowElementStylePropValues helper function
5 changes: 5 additions & 0 deletions .changeset/nervous-apricots-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@justeattakeaway/pie-button": minor
---

[Removed] - getShadowElementStylePropValues function from button component test to pie-webc-testing helpers
5 changes: 5 additions & 0 deletions .changeset/serious-maps-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@justeattakeaway/pie-icons-webc": minor
---

[Added] - :host-context(pie-tag) svg styles
5 changes: 5 additions & 0 deletions .changeset/ten-mangos-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@justeattakeaway/pie-tag": minor
---

[Added] - Tag component functionality
40 changes: 40 additions & 0 deletions apps/pie-storybook/stories/pie-tag-docs/variants.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as TagStories from '../pie-tag.stories.ts'
import { Meta, Canvas } from '@storybook/blocks';

<Meta of={TagStories} />

### Neutral

<Canvas of={TagStories.Neutral} />

### Blue

<Canvas of={TagStories.Blue} />

### Green

<Canvas of={TagStories.Green} />

### Yellow

<Canvas of={TagStories.Yellow} />

### Red

<Canvas of={TagStories.Red} />

### Brand

<Canvas of={TagStories.Brand} />

### Neutral Alternative

<Canvas of={TagStories.NeutralAlternative} />

### Outline

<Canvas of={TagStories.Outline} />

### Ghost

<Canvas of={TagStories.Ghost} />
106 changes: 94 additions & 12 deletions apps/pie-storybook/stories/pie-tag.stories.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,118 @@
import { html } from 'lit';
import { html, nothing } from 'lit';

/* eslint-disable import/no-duplicates */
import '@justeattakeaway/pie-tag';
import { TagProps } from '@justeattakeaway/pie-tag';
import {
TagProps as TagBaseProps, variants, sizes,
} from '@justeattakeaway/pie-tag';
/* eslint-enable import/no-duplicates */
import '@justeattakeaway/pie-icons-webc/IconHeartFilled';

import { type StoryMeta } from '../types';
import { createStory } from '../utilities';
import type { StoryMeta, SlottedComponentProps } from '../types';
import { createStory, type TemplateFunction } from '../utilities';

type TagProps = SlottedComponentProps<TagBaseProps>;
type TagStoryMeta = StoryMeta<TagProps>;

const defaultArgs: TagProps = {};
const defaultArgs: TagProps = {
variant: 'neutral',
size: 'large',
isStrong: false,
showIcon: false,
slot: 'Label',
};

const tagStoryMeta: TagStoryMeta = {
title: 'Tag',
component: 'pie-tag',
argTypes: {},
argTypes: {
variant: {
description: 'Set the variant of the tag.',
control: 'select',
options: variants,
defaultValue: {
summary: 'neutral',
},
},
size: {
description: 'Set the size of the tag.',
control: 'select',
options: sizes,
defaultValue: {
summary: 'large',
},
},
isStrong: {
description: 'If `true`, displays strong tag styles for some of the variant',
control: 'boolean',
defaultValue: {
summary: false,
},
},
showIcon: {
description: 'Enable to see the example of Tag with icon. Available only for large tag size.',
control: 'boolean',
defaultValue: {
summary: false,
},
if: { arg: 'size', eq: 'large' },
},
},
args: defaultArgs,
parameters: {
design: {
type: 'figma',
url: '',
url: 'https://www.figma.com/file/OOgnT2oNMdGFytj5AanYvt/branch/QGEtmJqZM3OL9QG33L4053/%E2%9D%8C-%5BBETA%5D-%5BCore%5D-Component-Documentation-%5BPIE-3%5D-%E2%9D%8C?type=design&node-id=419-62146&mode=design',
},
},
};

export default tagStoryMeta;

// TODO: remove the eslint-disable rule when props are added
// eslint-disable-next-line no-empty-pattern
const Template = ({}: TagProps) => html`
<pie-tag></pie-tag>
const Template : TemplateFunction<TagProps> = ({
variant,
size,
isStrong,
showIcon,
slot,
}) => html`
<pie-tag
variant="${variant}"
size="${size}"
?isStrong="${isStrong}">
${showIcon ? html`<icon-heart-filled slot="icon"></icon-heart-filled>` : nothing}
${slot}
</pie-tag>
`;

export const Default = createStory<TagProps>(Template, defaultArgs)();
const createTagStory = createStory<TagProps>(Template, defaultArgs);

export const Default = createTagStory();
export const Neutral = createTagStory({ variant: 'neutral' });
export const Blue = createTagStory({ variant: 'blue' });
export const Green = createTagStory({ variant: 'green' });
export const Yellow = createTagStory({ variant: 'yellow' });
export const Red = createTagStory({ variant: 'red' });

// For the following stories isStrong prop won't have any effect so it is excluded
export const Brand = createTagStory({ variant: 'brand' }, {
controls: {
exclude: ['isStrong'],
},
});
export const NeutralAlternative = createTagStory({ variant: 'neutral-alternative' }, {
bgColor: 'dark (container-dark)',
controls: {
exclude: ['isStrong'],
},
});
export const Outline = createTagStory({ variant: 'outline' }, {
controls: {
exclude: ['isStrong'],
},
});
export const Ghost = createTagStory({ variant: 'ghost' }, {
controls: {
exclude: ['isStrong'],
},
});
33 changes: 1 addition & 32 deletions packages/components/pie-button/test/component/pie-button.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getShadowElementStylePropValues } from '@justeattakeaway/pie-webc-testing/src/helpers/get-shadow-element-style-prop-values.ts';
import { test, expect } from '@sand4rt/experimental-ct-web';
import type { Locator } from '@playwright/test';
import { PieButton, ButtonProps } from '@/index';

const props: Partial<ButtonProps> = {
Expand All @@ -12,37 +12,6 @@ type SizeResponsiveSize = {
responsiveSize: string;
};

/**
* Gets the value of the given style properties from the shadow element
* @param element The custom element instance
* @param selector The selector of the element in the shadow
* @param props The style properties to get the values from
* @returns The values of the given style properties
*/
async function getShadowElementStylePropValues (element:Locator, selector:string, props:Array<string>):Promise<Array<string>> {
const data = { selector, props };

const evaluated = await element.evaluate((el, data) => {
const { selector, props } = data;

if (!el || !el.shadowRoot) {
throw new Error('getShadowElementStylePropValues: evaluate didn\'t return an element');
}

const shadowEl = el.shadowRoot.querySelector(selector);

if (!shadowEl) {
throw new Error('getShadowElementStylePropValues: no shadow element was found');
}

const shadowElStyle = getComputedStyle(shadowEl);

return props.map((prop) => shadowElStyle.getPropertyValue(prop).trim());
}, data);

return evaluated;
}

const sizes:Array<SizeResponsiveSize> = [
{ sizeName: 'xsmall', responsiveSize: '--btn-height--small' },
{ sizeName: 'small-expressive', responsiveSize: '--btn-height--medium' },
Expand Down
32 changes: 28 additions & 4 deletions packages/components/pie-tag/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

## pie-tag

`pie-tag` is a Web Component built using the Lit library.
`pie-tag` is a Web Component built using the Lit library. A tag is a small visual element used to represent and categorize information within a user interface. 

This component can be easily integrated into various frontend frameworks and customized through a set of properties.

Expand Down Expand Up @@ -74,16 +74,40 @@ import { PieTag } from '@justeattakeaway/pie-tag/dist/react';

| Property | Type | Default | Description |
|---|---|---|---|
| - | - | - | - |
| size | `String` | `large` | Size of the tag. Can be either `large` or `small` |
| variant | `String` | `neutral` | Variant of the tag, one of `variants` - `neutral-alternative`, `neutral`, `outline`, `ghost`, `blue`, `green`, `yellow`, `red`, `brand` |
| isStrong | `Boolean` | `false` | If `true`, displays strong tag styles for `green`, `yellow`, `red`, `blue` and `neutral` variants'|

Since the component is not interactive it doesn't have a disabled property. To give the Tag a disabled look please use `--tag-opacity` css variable. Recommended opacity level for disabled tag is 0.5.

In your markup or JSX, you can then use these to set the properties for the `pie-tag` component:

```html
<!-- Native HTML -->
<pie-tag></pie-tag>
<pie-tag>Label</pie-tag>

<!-- JSX -->
<PieTag></PieTag>
<PieTag>Label</PieTag>
```
## Slots

| Slot | Description |
| Default slot | Used to pass text into the tag component. |
| icon | Used to pass in an icon to the tag component. We recommend using `pie-icons-webc` for defining this icon, but this can also accept an SVG icon. |

### Using `pie-icons-webc` with `pie-tag` icon slot

We recommend using `pie-icons-webc` when using the `icon` slot. Here is an example of how you would do this:

```html
<!--
Note that pie-tag and the icon that you want to use will need to be imported as components into your application.
See the `pie-icons-webc` README for more info on importing these icons.
-->
<pie-tag>
<icon-vegan slot="icon"></icon-vegan>
Vegan
</pie-tag>
```

## Contributing
Expand Down
22 changes: 19 additions & 3 deletions packages/components/pie-tag/src/defs.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
// TODO - please remove the eslint disable comment below when you add props to this interface
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface TagProps {}
export const variants = ['neutral-alternative', 'neutral', 'outline', 'ghost', 'blue', 'green', 'yellow', 'red', 'brand'] as const;
export const sizes = ['small', 'large'] as const;

export interface TagProps {
/**
* What style variant the tag should be such as neutral/ghost etc.
*/
variant: typeof variants[number];

/**
* When true, the 'green', "yellow", "red", "blue" and "neutral" variants change their styles and become bolder
*/
isStrong: boolean;

/**
* What size the tag should be.
*/
size: typeof sizes[number];
}
40 changes: 35 additions & 5 deletions packages/components/pie-tag/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { LitElement, html, unsafeCSS } from 'lit';

import { defineCustomElement } from '@justeattakeaway/pie-webc-core';
import {
LitElement, html, unsafeCSS, nothing,
} from 'lit';
import { property } from 'lit/decorators.js';
import { validPropertyValues, defineCustomElement } from '@justeattakeaway/pie-webc-core';
import styles from './tag.scss?inline';
import { TagProps } from './defs';
import { TagProps, variants, sizes } from './defs';

// Valid values available to consumers
export * from './defs';
Expand All @@ -11,10 +13,38 @@ const componentSelector = 'pie-tag';

/**
* @tagname pie-tag
* @slot icon - The icon slot
* @slot - Default slot
*/
export class PieTag extends LitElement implements TagProps {
@property({ type: String })
@validPropertyValues(componentSelector, variants, 'neutral')
public variant: TagProps['variant'] = 'neutral';

@property({ type: String })
@validPropertyValues(componentSelector, sizes, 'large')
public size : TagProps['size'] = 'large';

@property({ type: Boolean })
public isStrong = false;

render () {
return html`<h1 data-test-id="pie-tag">Hello world!</h1>`;
const {
variant,
size,
isStrong,
} = this;
return html`
<div
class="c-tag"
variant=${variant}
size=${size}
?isStrong=${isStrong}
data-test-id="pie-tag"
>
${size === 'large' ? html`<slot name="icon"></slot>` : nothing}
<slot></slot>
</div>`;
}

// Renders a `CSSResult` generated from SCSS by Vite
Expand Down
Loading

0 comments on commit 9fbfea7

Please sign in to comment.