Skip to content

Commit

Permalink
Feat(web-twig): Introduce Item component #DS-1049
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelklibani committed Nov 30, 2023
1 parent 7bd2ae7 commit d91ff7b
Show file tree
Hide file tree
Showing 20 changed files with 268 additions and 4 deletions.
20 changes: 20 additions & 0 deletions packages/web-twig/src/Resources/components/Item/Item.stories.twig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@

{% block content %}

<DocsSection title="Default">
{% include '@components/Item/stories/ItemDefault.twig' %}
</DocsSection>

<DocsSection title="Selected">
{% include '@components/Item/stories/ItemSelected.twig' %}
</DocsSection>

<DocsSection title="Disabled">
{% include '@components/Item/stories/ItemDisabled.twig' %}
</DocsSection>

<DocsSection title="Helper Text">
{% include '@components/Item/stories/ItemHelperText.twig' %}
</DocsSection>

<DocsSection title="Icon">
{% include '@components/Item/stories/ItemIcon.twig' %}
</DocsSection>

<DocsSection title="Checkbox Item">
{% include '@components/Item/stories/CheckboxItem.twig' %}
</DocsSection>
Expand Down
70 changes: 70 additions & 0 deletions packages/web-twig/src/Resources/components/Item/Item.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{# API #}
{%- set props = props | default([]) -%}
{%- set _elementType = props.elementType | default('button') -%}
{%- set _helperText = props.helperText | default(null) -%}
{%- set _href = props.href | default(null) -%}
{%- set _iconName = props.iconName | default(null) -%}
{%- set _isDisabled = props.isDisabled | default(null) -%}
{%- set _isSelected = props.isSelected | default(null) -%}
{%- set _label = props.label | default('') -%}
{%- set _target = props.target | default(null) -%}
{%- set _type = props.type | default('button') -%}
{%- set _unsafeHelperText = props.UNSAFE_helperText | default(null) -%}
{%- set _unsafeLabel = props.UNSAFE_label | default(null) -%}

{# Class names #}
{%- set _rootClassName = _spiritClassPrefix ~ 'Item' -%}
{%- set _disabledClassName = _isDisabled ? _spiritClassPrefix ~ 'Item--disabled' : null -%}
{%- set _selectedClassName = _isSelected ? _spiritClassPrefix ~ 'Item--selected' : null -%}
{%- set _iconClassName = _spiritClassPrefix ~ 'Item__icon' -%}
{%- set _startIconClassName = _iconClassName ~ ' ' ~ _spiritClassPrefix ~ 'Item__icon--start' -%}
{%- set _endIconClassName = _iconClassName ~ ' ' ~ _spiritClassPrefix ~ 'Item__icon--end' -%}
{%- set _helperTextClassName = _spiritClassPrefix ~ 'Item__helperText' -%}
{%- set _labelClassName = _spiritClassPrefix ~ 'Item__label' -%}

{# Attributes #}
{%- set _ariaSelectedAttr = 'aria-selected="' ~ (_isSelected ? 'true' : 'false') ~ '"' -%}
{%- set _buttonDisabledAttr = (_elementType == 'button' and _isDisabled) ? 'disabled' : null -%}
{%- set _hrefAttr = (_elementType == 'a' and _href) ? 'href=' ~ _href : null -%}
{%- set _targetAttr = (_elementType == 'a' and _target) ? 'target=' ~ _target | escape('html_attr') : null -%}
{%- set _typeAttr = (_elementType == 'button' and _type) ? 'type=' ~ _type : null -%}

{# Miscellaneous #}
{%- set _styleProps = useStyleProps(props) -%}
{%- set _classNames = [ _rootClassName, _disabledClassName, _selectedClassName, _styleProps.className ] -%}
{%- set _selectedIconName = 'check-plain' -%}

<{{ _elementType }}
{{ mainProps(props) }}
{{ styleProp(_styleProps) }}
{{ classProp(_classNames) }}
{{ _hrefAttr }}
{{ _targetAttr }}
{{ _typeAttr }}
{{ _buttonDisabledAttr }}
{{ _ariaSelectedAttr | raw }}
>
{% if _iconName %}
<span class="{{ _startIconClassName }}">
<Icon name="{{ _iconName }}" isReusable={ false } />
</span>
{% endif %}
<span class="{{ _labelClassName }}">
{%- if _unsafeLabel -%}
{{ _unsafeLabel | raw }}
{%- else -%}
{{ _label }}
{%- endif -%}
</span>
<HelperText
elementType="span"
className="{{ _helperTextClassName }}"
helperText="{{ _helperText }}"
UNSAFE_helperText="{{ _unsafeHelperText }}"
/>
{% if _isSelected %}
<span class="{{ _endIconClassName }}">
<Icon name="{{ _selectedIconName }}" isReusable={ false } />
</span>
{% endif %}
</{{ _elementType }}>
90 changes: 86 additions & 4 deletions packages/web-twig/src/Resources/components/Item/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,90 @@
# Item

To implement Item component with content of `Radio` or `Checkbox`,
you need to use directly these components with prop `isItem`.
The Item component is used to display a single item in a list. It can be used in Dropdown or similar.

See `web` package [Item documentation][item-documentation] for more info.
To use Item with checkbox or radio please use components [Checkbox][checkbox] or [Radio][radio]
with `isItem` property. We do this to avoid repeating the same code and to simplify the API.

[item-documentation]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/src/scss/components/Item/README.md
Simple Item example:

```twig
<Item label="Item" />;
```

Item with icon example:

```twig
<Item label="Item" iconName="search" />;
```

Item in selected state example:

```twig
<Item label="Item" isSelected />;
```

Item with Helper text example:

```twig
<Item label="Item" helperText="Helper text" />;
```

Item in disabled state example:

```twig
<Item label="Item" isDisabled />;
```

Item with icon and helper text in selected state example:

```twig
<Item label="Item" iconName="search" helperText="Helper text" isSelected />;
```

Item as a link example:

```twig
<Item label="Item" elementType="a" href="#" />;
```

Radio as Item:

```twig
<Radio id="radioItem" name="example" label="Radio Label" isItem />;
```

Checkbox as Item:

```twig
<Checkbox id="checkboxItem" name="example" label="Checkbox Label" isItem />;
```

## API

| Name | Type | Default | Required | Description |
| ------------------- | --------------- | -------- | -------- | ------------------------------------- |
| `elementType` | `ElementType` | `button` || Type of element used as wrapper |
| `helperText` | `string` ||\*\* | Custom helper text |
| `href` | `string` ||| Link URL if element type is anchor |
| `iconName` | `string` ||| Icon used in item |
| `isDisabled` | `bool` | `false` || Whether is the item disabled |
| `isSelected` | `bool` | `false` || Whether is the item selected |
| `label` | `string` | - |\* | Label of the item |
| `target` | `string` ||| Target prop if element type is anchor |
| `type` | `string` | `button` || Input type if element type is button |
| `UNSAFE_className` | `string` ||| Wrapper custom class name |
| `UNSAFE_helperText` | `string` ||\*\* | Unescaped custom helper text |
| `UNSAFE_label` | `string` ||| Unescaped label text (allows HTML) |
| `UNSAFE_style` | `CSSProperties` ||| Wrapper custom style |

(\*) Label is required. You can use the `label` for simple text or `UNSAFE_label` for HTML content.
(\*\*) Props with and without `UNSAFE_` prefix are mutually exclusive.

On top of the API options, you can add `data-*` or `aria-*` attributes to
further extend component's descriptiveness and accessibility. Also, UNSAFE styling props are available,
see the [Escape hatches][escape-hatches] section in README to learn how and when to use them.
These attributes will be passed to the topmost HTML element of the component.

[checkbox]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-twig/src/Resources/components/Checkbox/README.md
[radio]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-twig/src/Resources/components/Radio/README.md
[escape-hatches]: https://github.com/lmc-eu/spirit-design-system/tree/main/packages/web-twig/README.md#escape-hatches
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Lmc\SpiritWebTwigBundle\Resources\components\Item;

use Lmc\SpiritWebTwigBundle\AbstractComponentSnapshotTest;

class ItemSnapshotTest extends AbstractComponentSnapshotTest
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Item label="Item label"/>
<Item elementType="a" label="Item label" href="https://www.example.com/" />
<Item elementType="div" label="Item label" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<Item label="Item label" isDisabled />
<Item label="Item label" elementType="a" isDisabled />
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<Item label="Item label" helperText="Helper text" />
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<Item label="Item label" iconName="search" />
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<Item label="Item label" isSelected />
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>
</title>
</head>
<body>
<button class="Item" type="button" aria-selected="false"><span class="Item__label">Item label</span></button>
<a class="Item" href="https://www.example.com/" aria-selected="false"><span class="Item__label">Item
label</span></a>
<div class="Item" aria-selected="false">
<span class="Item__label">Item label</span>
</div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>
</title>
</head>
<body>
<button class="Item Item--disabled" type="button" disabled aria-selected="false"><span class="Item__label">Item label</span></button> <a class="Item Item--disabled" aria-selected="false"><span class="Item__label">Item label</span></a>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>
</title>
</head>
<body>
<button class="Item" type="button" aria-selected="false"><span class="Item__label">Item label</span> <span class="Item__helperText">Helper text</span></button>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>
</title>
</head>
<body>
<button class="Item" type="button" aria-selected="false"><span class="Item__icon Item__icon--start"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M15.5 14H14.71L14.43 13.73C15.63 12.33 16.25 10.42 15.91 8.39002C15.44 5.61002 13.12 3.39002 10.32 3.05002C6.09001 2.53002 2.53002 6.09001 3.05002 10.32C3.39002 13.12 5.61002 15.44 8.39002 15.91C10.42 16.25 12.33 15.63 13.73 14.43L14 14.71V15.5L18.25 19.75C18.66 20.16 19.33 20.16 19.74 19.75C20.15 19.34 20.15 18.67 19.74 18.26L15.5 14ZM9.50002 14C7.01002 14 5.00002 11.99 5.00002 9.50002C5.00002 7.01002 7.01002 5.00002 9.50002 5.00002C11.99 5.00002 14 7.01002 14 9.50002C14 11.99 11.99 14 9.50002 14Z" fill="currentColor">
</path></svg></span> <span class="Item__label">Item label</span></button>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>
</title>
</head>
<body>
<button class="Item Item--selected" type="button" aria-selected="true"><span class="Item__label">Item label</span>
<span class="Item__icon Item__icon--end"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M9.00012 16.5447L5.50012 13.0447C5.11012 12.6547 4.49012 12.6547 4.10012 13.0447C3.71012 13.4347 3.71012 14.0547 4.10012 14.4447L8.29012 18.6347C8.68012 19.0247 9.31012 19.0247 9.70012 18.6347L20.3001 8.04473C20.6901 7.65473 20.6901 7.03473 20.3001 6.64473C19.9101 6.25473 19.2901 6.25473 18.9001 6.64473L9.00012 16.5447Z" fill="currentColor">
</path></svg></span></button>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Item label="Item label" />
<Item elementType="a" label="Item label" href="https://www.example.com/" />
<Item elementType="div" label="Item label" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<Item label="Item label" isDisabled />
<Item label="Item label" isDisabled isSelected />
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<Item label="Item label" helperText="Helper text" />
<Item label="Item label" helperText="Helper text" isSelected />
<Item label="Item label" helperText="Helper text" isDisabled />
<Item label="Item label" helperText="Helper text" isSelected isDisabled />
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<Item label="Item label" iconName="search" />
<Item label="Item label" iconName="search" isSelected />
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<Item label="Item label" isSelected />
1 change: 1 addition & 0 deletions packages/web-twig/src/Resources/twig-components/item.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends '@spirit/Item/Item.twig' %}

0 comments on commit d91ff7b

Please sign in to comment.