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(pie-tag): DSW-1520 tag component functionality #1123

Merged
merged 5 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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/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',
dandel10n marked this conversation as resolved.
Show resolved Hide resolved
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'],
},
});
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.
dandel10n marked this conversation as resolved.
Show resolved Hide resolved

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>
dandel10n marked this conversation as resolved.
Show resolved Hide resolved
</div>`;
}

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