Skip to content

Commit

Permalink
FCT-1188: filters: quick filters: create quick filters component (#2954)
Browse files Browse the repository at this point in the history
* feat: deprecate Tag's `type` property, introduce `tone` as replacement

* chore(tag): add visual tests for new 'tone' prop

* chore: add more docs

* chore: changeset added

* fix(tag): layout adjustments (font-size, spacings, gaps)

* fix(tag): disable text-selection (cause ui-component)

* fix(tag): fix html semantics + add missing focus outlines

* chore(quick-filters): add visual test

* test(quick-filters): add unit-test

* fix(tag): display as regular flex-element again, to prevent side-effects

* fix: fix visual test

* fix(tag): fix visual test

* fix: visualtest for QuickFilters

* fix: remove Tag reference from QuickFilters test

* fix: Update packages/components/quick-filters/src/quick-filters.stories.tsx

Co-authored-by: Byron Wall <87667330+ByronDWall@users.noreply.github.com>

* fix(tag): ux review fixes (revert font-size change, add missing gap between drag-icon & label)

* fix(tag): add not-allowed cursor when isDisabled is true

* fix(quick-filters): remove leftover comment

* fix(quick-filters): update handleItemClick in QuickFilters test

* fix(quick-filters): update tone prop in QuickFilters component

---------

Co-authored-by: Byron Wall <87667330+ByronDWall@users.noreply.github.com>
  • Loading branch information
misama-ct and ByronDWall authored Oct 11, 2024
1 parent 38c2dfe commit 7b68886
Show file tree
Hide file tree
Showing 18 changed files with 433 additions and 121 deletions.
5 changes: 5 additions & 0 deletions .changeset/spicy-candles-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@commercetools-uikit/tag': minor
---

Deprecated 'type' property in favor of 'tone' for better clarity and flexibility. New tone 'surface' added.
63 changes: 54 additions & 9 deletions packages/components/quick-filters/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

The `QuickFilters` component displays a selection of `Tag` components that represent the available filter actions.

This description is a stub and shold be expanded as development continues.

## Installation

```
Expand All @@ -32,16 +30,63 @@ npm --save install react
## Usage

```jsx
import { useState } from 'react';
import QuickFilters from '@commercetools-uikit/quick-filters';

/**TODO: EXPAND THIS */
const Example = () => <QuickFilters />;

export default Example;
const App = () => {
const [items, setItems] = useState([
{
id: '1',
label: 'Accepted',
isActive: true,
},
{
id: '2',
label: 'Rejected',
isActive: false,
},
]);

const onItemClick = (clickedItem) => {
const updatedItems = items.map((item) => {
return {
...item,
isActive: item.id === clickedItem.id ? !item.isActive : false,
};
});
setItems(updatedItems);
};

return <QuickFilters items={items} onItemClick={onItemClick} />;
};

export default App;
```

## Properties

| Props | Type | Required | Default | Description |
| ------- | -------- | :------: | ------- | -------------------- |
| `label` | `string` || | This is a stub prop! |
| Props | Type | Required | Default | Description |
| ------------- | ------------------------------------------------------------------- | :------: | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `items` | `Array: TQuickFiltersItem[]`<br/>[See signature.](#signature-items) || | collection of quick filter items@param item.id unique identifier for the item.&#xA;@param item.label label to display&#xA;@param item.isActive the current active state of the item |
| `onItemClick` | `Function`<br/>[See signature.](#signature-onItemClick) || | callback fn, executed when an item is clicked |

## Signatures

### Signature `items`

```ts
{
/** unique identifier for the item. */
id: string;
/* label to display */
label: string;
/* the current active state of the item */
isActive: boolean;
}
```

### Signature `onItemClick`

```ts
(item: TQuickFiltersItem) => void
```
2 changes: 0 additions & 2 deletions packages/components/quick-filters/docs/description.md
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
The `QuickFilters` component displays a selection of `Tag` components that represent the available filter actions.

This description is a stub and shold be expanded as development continues.
31 changes: 28 additions & 3 deletions packages/components/quick-filters/docs/usage-example.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,31 @@
import { useState } from 'react';
import QuickFilters from '@commercetools-uikit/quick-filters';

/**TODO: EXPAND THIS */
const Example = () => <QuickFilters />;
const App = () => {
const [items, setItems] = useState([
{
id: '1',
label: 'Accepted',
isActive: true,
},
{
id: '2',
label: 'Rejected',
isActive: false,
},
]);

export default Example;
const onItemClick = (clickedItem) => {
const updatedItems = items.map((item) => {
return {
...item,
isActive: item.id === clickedItem.id ? !item.isActive : false,
};
});
setItems(updatedItems);
};

return <QuickFilters items={items} onItemClick={onItemClick} />;
};

export default App;
2 changes: 2 additions & 0 deletions packages/components/quick-filters/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
"dependencies": {
"@babel/runtime": "^7.20.13",
"@babel/runtime-corejs3": "^7.20.13",
"@commercetools-uikit/design-system": "workspace:^",
"@commercetools-uikit/tag": "workspace:^",
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
"prop-types": "15.8.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Meta, Markdown } from '@storybook/blocks';
import ReadMe from './../README.md?raw'

<Meta tags={['local-dev']} title="components/QuickFilters/Readme" />
<Meta title="components/QuickFilters/Readme" />

<Markdown>{ReadMe}</Markdown>
26 changes: 20 additions & 6 deletions packages/components/quick-filters/src/quick-filters.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import { screen, render } from '../../../../test/test-utils';
import QuickFilters from './quick-filters';

/**
* THIS IS A PLACEHOLDER, PLEASE UPDATE IT
*/
describe('QuickFilters', () => {
it('should render the quick-filters', async () => {
await render(<QuickFilters label="quickfilters" />);
await screen.findByText('quickfilters');
it('should render items and propagate item-clicks', async () => {
const items = [
{ id: '1', label: 'Foo', isActive: true },
{ id: '2', label: 'Bar', isActive: false },
];

const handleItemClick = jest.fn();

await render(<QuickFilters items={items} onItemClick={handleItemClick} />);

const button1 = (await screen.findByText('Foo')).closest('button');
const button2 = (await screen.findByText('Bar')).closest('button');

expect(button1).toBeInTheDocument();
expect(button2).toBeInTheDocument();

button2?.click();
expect(handleItemClick).toHaveBeenCalledWith(items[1]);
button1?.click();
expect(handleItemClick).toHaveBeenCalledWith(items[0]);
});
});
53 changes: 44 additions & 9 deletions packages/components/quick-filters/src/quick-filters.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,57 @@
import type { Meta, StoryObj } from '@storybook/react';
import QuickFilters from './quick-filters';
import QuickFilters, {
TQuickFiltersItem,
TQuickFiltersProps,
} from './quick-filters';
import { useState } from 'react';

const meta: Meta<typeof QuickFilters> = {
title: 'components/QuickFilters',
component: QuickFilters,
tags: ['local-dev'],
argTypes: {
label: {
control: 'text',
},
},
//tags: ['local-dev'],
};
export default meta;

type Story = StoryObj<typeof QuickFilters>;

/** The `QuickFilters` component displays a selection of `Tag` components that represent the available filter actions. */
export const BasicExample: Story = {
args: {
label: 'A component for applying static filter controls',
render: (args) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const [items, setItems] = useState<TQuickFiltersProps['items']>([
{
id: '1',
label: 'Accepted (234)',
isActive: true,
},
{
id: '2',
label: 'Rejected (25)',
isActive: false,
},
{
id: '3',
label: 'Canceled (3)',
isActive: false,
},
{
id: '4',
label: 'Drafts (58)',
isActive: false,
},
]);

const onItemClick = (clickedItem: TQuickFiltersItem) => {
const updatedItems = items.map((item) => {
return {
...item,
isActive: item.id === clickedItem.id ? !item.isActive : false,
};
});
setItems(updatedItems);
};

return <QuickFilters {...args} items={items} onItemClick={onItemClick} />;
},
args: {},
};
52 changes: 48 additions & 4 deletions packages/components/quick-filters/src/quick-filters.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,56 @@
import Tag from '@commercetools-uikit/tag';
import { css } from '@emotion/react';
import { designTokens } from '@commercetools-uikit/design-system';

export type TQuickFiltersItem = {
/** unique identifier for the item. */
id: string;
/* label to display */
label: string;
/* the current active state of the item */
isActive: boolean;
};

export type TQuickFiltersProps = {
/**
* This is a stub prop!
* collection of quick filter items
*
* @param item.id unique identifier for the item.
* @param item.label label to display
* @param item.isActive the current active state of the item
*/
label: string;
items: TQuickFiltersItem[];

/** callback fn, executed when an item is clicked */
onItemClick: (item: TQuickFiltersItem) => void;
};

function QuickFilters(props: TQuickFiltersProps) {
return <div>{props.label}</div>;
const listStyles = css`
all: unset;
display: inline-flex;
flex-wrap: wrap;
gap: ${designTokens.spacing20};
`;

const listItemStyles = css`
all: unset;
`;

function QuickFilters({ items, onItemClick }: TQuickFiltersProps) {
return (
<ul css={listStyles}>
{items.map((item) => (
<li key={item.id} css={listItemStyles}>
<Tag
tone={item.isActive ? 'primary' : 'surface'}
onClick={() => onItemClick(item)}
>
{item.label}
</Tag>
</li>
))}
</ul>
);
}

export default QuickFilters;
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import { Suite, Spec } from '../../../../test/percy';
import QuickFilters from './quick-filters';

export const routePath = '/quick-filters';

export const component = () => (
<Suite>
<Spec label="this is a placeholder test">
{/**ACTUAL TEST GOES HERE */}
<Spec label="Renders an active + inactive item">
<QuickFilters
items={[
{
id: '1',
label: 'Accepted',
isActive: true,
},
{
id: '2',
label: 'Rejected',
isActive: false,
},
]}
onItemClick={() => {}}
/>
</Spec>
</Suite>
);
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import percySnapshot from '@percy/puppeteer';
import { getDocument, queries } from 'pptr-testing-library';

describe('FiltersList', () => {
describe('QuickFilters', () => {
beforeAll(async () => {
await page.goto(`${globalThis.HOST}/quick-filters`);
});

it.skip('Default', async () => {
// THIS IS A STUB
it('Default', async () => {
await page.waitForSelector('text/Renders an active + inactive item');
await percySnapshot(page, 'QuickFilters');
});
});
23 changes: 12 additions & 11 deletions packages/components/tag/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,18 @@ export default Example;

## Properties

| Props | Type | Required | Default | Description |
| ---------------------- | ----------------------------------------------------------------------------------------------------------- | :------: | ---------- | ------------------------------------------------------------------------------------- |
| `type` | `union`<br/>Possible values:<br/>`'normal' , 'warning'` | | `'normal'` | Indicates color scheme of the tag. |
| `styles` | `Record` | | | Styles object that is spread into the tag body. |
| `to` | `union`<br/>Possible values:<br/>`string , LocationDescriptor` | | | Link of the tag when not disabled |
| `isDisabled` | `boolean` | | `false` | Disable the tag element along with the option to remove it. |
| `isDraggable` | `boolean` | | `false` | Adds the draggable icon on the left side. |
| `onRemove` | `Function`<br/>[See signature.](#signature-onRemove) | | | Called when remove button is clicked. |
| `onClick` | `Function`<br/>[See signature.](#signature-onClick) | | | Called when tag element is clicked. This is not called when remove button is clicked. |
| `horizontalConstraint` | `union`<br/>Possible values:<br/>`, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 'scale', 'auto'` | | `'scale'` | Horizontal size limit of the input field. |
| `children` | `ReactNode` || | Content rendered within the tag |
| Props | Type | Required | Default | Description |
| ---------------------- | ----------------------------------------------------------------------------------------------------------- | :------: | ----------- | ------------------------------------------------------------------------------------- |
| `type` | `union`<br/>Possible values:<br/>`'normal' , 'warning'` | | | Indicates color scheme of the tag.&#xA;@deprecated use `tone` instead |
| `styles` | `Record` | | | Styles object that is spread into the tag body. |
| `to` | `union`<br/>Possible values:<br/>`string , LocationDescriptor` | | | Link of the tag when not disabled |
| `isDisabled` | `boolean` | | `false` | Disable the tag element along with the option to remove it. |
| `isDraggable` | `boolean` | | `false` | Adds the draggable icon on the left side. |
| `onRemove` | `Function`<br/>[See signature.](#signature-onRemove) | | | Called when remove button is clicked. |
| `onClick` | `Function`<br/>[See signature.](#signature-onClick) | | | Called when tag element is clicked. This is not called when remove button is clicked. |
| `horizontalConstraint` | `union`<br/>Possible values:<br/>`, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 'scale', 'auto'` | | `'scale'` | Horizontal size limit of the input field. |
| `children` | `ReactNode` || | Content rendered within the tag |
| `tone` | `union`<br/>Possible values:<br/>`'primary' , 'warning' , 'surface'` | | `'primary'` | Indicates the color scheme of the tag. |

## Signatures

Expand Down
Loading

0 comments on commit 7b68886

Please sign in to comment.