Skip to content

Commit

Permalink
Feat(web-twig): Add abstract component TextFieldBase #DS-319
Browse files Browse the repository at this point in the history
  • Loading branch information
dlouhak committed Sep 22, 2022
1 parent 002a00f commit 1a27cfc
Show file tree
Hide file tree
Showing 17 changed files with 171 additions and 70 deletions.
Original file line number Diff line number Diff line change
@@ -1,59 +1,4 @@
{# API #}
{%- set props = props | default([]) -%}
{%- set _class = props.class | default(null) -%}
{%- set _id = props.id -%}
{%- set _isDisabled = props.isDisabled | default(false) | boolprop -%}
{%- set _isFluid = props.isFluid | default(false) | boolprop -%}
{%- set _isLabelHidden = props.isLabelHidden | default(false) | boolprop -%}
{%- set _isRequired = props.isRequired | default(false) | boolprop -%}
{%- set _label = props.label -%}
{%- set _message = props.message | default(null) -%}
{%- set _name = props.name | default(null) -%}
{%- set _placeholder = props.placeholder | default(null) -%}
{%- set _type = props.type | default('text') -%}
{%- set _validationState = props.validationState | default(null) -%}
{%- set _value = props.value | default(null) -%}

{# Class names #}
{%- set _inputClassName = _spiritClassPrefix ~ 'TextField__input' -%}
{%- set _labelClassName = _spiritClassPrefix ~ 'TextField__label' -%}
{%- set _labelHiddenClassName = _isLabelHidden ? _spiritClassPrefix ~ 'TextField__label--hidden' : null -%}
{%- set _labelRequiredClassName = _isRequired ? _spiritClassPrefix ~ 'TextField__label--required' : null -%}
{%- set _messageClassName = _spiritClassPrefix ~ 'TextField__message' -%}
{%- set _rootClassName = _spiritClassPrefix ~ 'TextField' -%}
{%- set _rootDisabledClassName = _isDisabled ? _spiritClassPrefix ~ 'TextField--disabled' : null -%}
{%- set _rootFluidClassName = _isFluid ? _spiritClassPrefix ~ 'TextField--fluid' : null -%}
{%- set _rootValidationStateClassName = _validationState ? _spiritClassPrefix ~ 'TextField--' ~ _validationState : null -%}

{# Attributes #}
{%- set _disabledAttr = _isDisabled ? 'disabled' : null -%}
{%- set _placeholderAttr = _placeholder ? 'placeholder="' ~ _placeholder ~'"' : null -%}
{%- set _requiredAttr = _isRequired ? 'required' : null -%}
{%- set _valueAttr = _value ? 'value="' ~ _value ~'"' : null -%}

{# Miscellaneous #}
{%- set _rootClassNames = [ _rootClassName, _rootDisabledClassName, _rootFluidClassName, _rootValidationStateClassName, _class ] -%}
{%- set _labelClassNames = [ _labelClassName, _labelHiddenClassName, _labelRequiredClassName ] -%}
{%- set _mainPropsWithoutId = props | filter((value, prop) => prop != 'id') -%}

<div {{ mainProps(_mainPropsWithoutId) }} {{ classProp(_rootClassNames) }}>
<label for="{{ _id }}" {{ classProp(_labelClassNames) }}>
{{ _label | raw }}
</label>
<input
{{ inputProps(props) }}
type="{{ _type }}"
id="{{ _id }}"
name="{{ _name }}"
class="{{ _inputClassName }}"
{{ _disabledAttr | raw }}
{{ _placeholderAttr | raw }}
{{ _requiredAttr | raw }}
{{ _valueAttr | raw }}
/>
{% if _message %}
<div class="{{ _messageClassName }}">
{{ _message | raw }}
</div>
{% endif %}
</div>
{% embed '@spirit/TextFieldBase/TextFieldBase.twig' with { props: props } only %}{% endembed %}
61 changes: 61 additions & 0 deletions packages/web-twig/src/Resources/components/TextFieldBase/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# TextFieldBase

This is Twig implementation of the abstract component [TextFieldBase] for the purposes of the form components TextField and TextArea.

Basic example usage:

```html
<TextFieldBase id="example" label="Label" name="example" />
```

Advanced example usage:

```html
<TextField
id="example2"
isRequired
messsage="validation failed"
name="example2"
placeholder="Placeholder"
type="password"
validationState="error"
/>
```

Without lexer:

```twig
{% include "@spirit/textFieldBase.twig" with { props: {
id: "example",
type: "text",
name: "example",
isRequired: true,
validationState: "error",
message: "validation failed",
}} %}
```

## API

| Prop name | Type | Default | Required | Description |
| ----------------- | ----------------------------- | --------- | -------- | ---------------------------------------------------------- |
| `class` | `string` | `null` | no | Custom CSS class |
| `id` | `string` || yes | Input and label identification |
| `isDisabled` | `bool` | `false` | no | If true, input is disabled |
| `isFluid` | `bool` | `false` | no | If true, the element spans to the full width of its parent |
| `isLabelHidden` | `bool` | `false` | no | If true, label is hidden |
| `isMultiline` | `bool` | `false` | no | If true, rendered DOM element is `textarea` |
| `isRequired` | `bool` | `false` | no | If true, input is required |
| `label` | `string` || yes | Label text |
| `message` | `string` | `null` | no | Validation or help message |
| `name` | `string` | `null` | no | Input name |
| `placeholder` | `string` | `null` | no | Input placeholder |
| `type` | `text`, `password`, `email` | `success` | no | Input type |
| `validationState` | `success`, `warning`, `error` | `null` | no | Type of validation state |
| `value` | `string` | `null` | no | Input value |

On top of the API options, you can add `data-*` or `aria-*` attributes to
further extend component's descriptiveness and accessibility. These attributes
will be passed to the topmost HTML element of the component.

[textfield]: https://github.com/lmc-eu/spirit-design-system/tree/main/packages/web/src/scss/components/TextField
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{# API #}
{%- set props = props | default([]) -%}
{%- set _class = props.class | default(null) -%}
{%- set _id = props.id -%}
{%- set _isDisabled = props.isDisabled | default(false) | boolprop -%}
{%- set _isFluid = props.isFluid | default(false) | boolprop -%}
{%- set _isLabelHidden = props.isLabelHidden | default(false) | boolprop -%}
{%- set _isMultiline = props.isMultiline | default(false) | boolprop -%}
{%- set _isRequired = props.isRequired | default(false) | boolprop -%}
{%- set _label = props.label -%}
{%- set _message = props.message | default(null) -%}
{%- set _name = props.name | default(null) -%}
{%- set _placeholder = props.placeholder | default(null) -%}
{%- set _type = props.type | default('text') -%}
{%- set _validationState = props.validationState | default(null) -%}
{%- set _value = props.value | default(null) -%}

{# Class names #}
{%- set _rootClassName = _spiritClassPrefix ~ _isMultiline ? 'TextArea' : 'TextField' -%}
{%- set _inputClassName = _rootClassName ~ '__input' -%}
{%- set _labelClassName = _rootClassName ~ '__label' -%}
{%- set _labelHiddenClassName = _isLabelHidden ? _rootClassName ~ '__label--hidden' : null -%}
{%- set _labelRequiredClassName = _isRequired ? _rootClassName ~ '__label--required' : null -%}
{%- set _messageClassName = _rootClassName ~ '__message' -%}
{%- set _rootDisabledClassName = _isDisabled ? _rootClassName ~ '--disabled' : null -%}
{%- set _rootFluidClassName = _isFluid ? _rootClassName ~ '--fluid' : null -%}
{%- set _rootValidationStateClassName = _validationState ? _rootClassName ~ '--' ~ _validationState : null -%}

{# Attributes #}
{%- set _disabledAttr = _isDisabled ? 'disabled' : null -%}
{%- set _placeholderAttr = _placeholder ? 'placeholder="' ~ _placeholder ~'"' : null -%}
{%- set _requiredAttr = _isRequired ? 'required' : null -%}
{%- set _valueAttr = _value ? 'value="' ~ _value ~'"' : null -%}

{# Miscellaneous #}
{%- set _rootClassNames = [ _rootClassName, _rootDisabledClassName, _rootFluidClassName, _rootValidationStateClassName, _class ] -%}
{%- set _labelClassNames = [ _labelClassName, _labelHiddenClassName, _labelRequiredClassName ] -%}
{%- set _mainPropsWithoutId = props | filter((value, prop) => prop != 'id') -%}

<div {{ mainProps(_mainPropsWithoutId) }} {{ classProp(_rootClassNames) }}>
<label for="{{ _id }}" {{ classProp(_labelClassNames) }}>
{{ _label | raw }}
</label>
{% if _isMultiline %}
<textarea
{{ inputProps(props) }}
id="{{ _id }}"
name="{{ _name }}"
class="{{ _inputClassName }}"
{{ _disabledAttr | raw }}
{{ _placeholderAttr | raw }}
{{ _requiredAttr | raw }}
>
{{ _valueAttr | raw }}
</textarea>
{% else %}
<input
{{ inputProps(props) }}
type="{{ _type }}"
id="{{ _id }}"
name="{{ _name }}"
class="{{ _inputClassName }}"
{{ _disabledAttr | raw }}
{{ _placeholderAttr | raw }}
{{ _requiredAttr | raw }}
{{ _valueAttr | raw }}
/>
{% endif %}
{% if _message %}
<div class="{{ _messageClassName }}">
{{ _message | raw }}
</div>
{% endif %}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends '@spirit/TextFieldBase/TextFieldBase.twig' %}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<nav class="Breadcrumbs" aria-label="Breadcrumb">
<ol>
<li class="d-none d-tablet-flex">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="none" id="82a17c5baa08e4d4af9894ef5019acde" aria-hidden="true"><path d="M9.29006 7.0545C8.90006 7.4445 8.90006 8.0745 9.29006 8.4645L13.1701 12.3445L9.29006 16.2245C8.90006 16.6145 8.90006 17.2445 9.29006 17.6345C9.68006 18.0245 10.3101 18.0245 10.7001 17.6345L15.2901 13.0445C15.6801 12.6545 15.6801 12.0245 15.2901 11.6345L10.7001 7.0445C10.3201 6.6645 9.68006 6.6645 9.29006 7.0545Z" fill="#132930"></path></svg><a aria-current="false" href="#rootUrl" class="link-primary link-underlined">Root</a>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="none" id="82a17c5baa08e4d4af9894ef5019acde" aria-hidden="true"><path d="M9.29006 7.05475C8.90006 7.44475 8.90006 8.07475 9.29006 8.46475L13.1701 12.3447L9.29006 16.2247C8.90006 16.6147 8.90006 17.2447 9.29006 17.6347C9.68006 18.0247 10.3101 18.0247 10.7001 17.6347L15.2901 13.0447C15.6801 12.6547 15.6801 12.0247 15.2901 11.6347L10.7001 7.04475C10.3201 6.66475 9.68006 6.66475 9.29006 7.05475Z" fill="#132930"></path></svg><a aria-current="false" href="#rootUrl" class="link-primary link-underlined">Root</a>
</li>
<li class="d-none d-tablet-flex">
<svg width="24" height="24" viewbox="0 0 24 24" fill="none" aria-hidden="true"><use href="#82a17c5baa08e4d4af9894ef5019acde"></use></svg><a aria-current="false" href="#categoryUrl" class="link-primary link-underlined">Category</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

<button type="button" class="Header__close" aria-expanded="false">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="none" id="5cf4a361209150b84108c93d7bf13d46" aria-hidden="true">
<path d="M18.3002 5.71022C17.9102 5.32022 17.2802 5.32022 16.8902 5.71022L12.0002 10.5902L7.11022 5.70021C6.72022 5.31021 6.09021 5.31021 5.70021 5.70021C5.31021 6.09021 5.31021 6.72022 5.70021 7.11022L10.5902 12.0002L5.70021 16.8902C5.31021 17.2802 5.31021 17.9102 5.70021 18.3002C6.09021 18.6902 6.72022 18.6902 7.11022 18.3002L12.0002 13.4102L16.8902 18.3002C17.2802 18.6902 17.9102 18.6902 18.3002 18.3002C18.6902 17.9102 18.6902 17.2802 18.3002 16.8902L13.4102 12.0002L18.3002 7.11022C18.6802 6.73022 18.6802 6.09022 18.3002 5.71022Z" fill="#132930"></path>
<path d="M18.3 5.70997C17.91 5.31997 17.28 5.31997 16.89 5.70997L12 10.59L7.10997 5.69997C6.71997 5.30997 6.08997 5.30997 5.69997 5.69997C5.30997 6.08997 5.30997 6.71997 5.69997 7.10997L10.59 12L5.69997 16.89C5.30997 17.28 5.30997 17.91 5.69997 18.3C6.08997 18.69 6.71997 18.69 7.10997 18.3L12 13.41L16.89 18.3C17.28 18.69 17.91 18.69 18.3 18.3C18.69 17.91 18.69 17.28 18.3 16.89L13.41 12L18.3 7.10997C18.68 6.72997 18.68 6.08997 18.3 5.70997Z" fill="#132930"></path>
</svg>

<span class="accessibility-hidden">Close</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div class="Modal__dialog">
<div class="Modal__header">
<button aria-controls="modal-example" aria-expanded="false" data-dismiss="modal" data-target="#modal-example" class="Button Button--tertiary Button--medium Button--square" type="button"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="none" id="5cf4a361209150b84108c93d7bf13d46" aria-hidden="true">
<path d="M18.3002 5.71022C17.9102 5.32022 17.2802 5.32022 16.8902 5.71022L12.0002 10.5902L7.11022 5.70021C6.72022 5.31021 6.09021 5.31021 5.70021 5.70021C5.31021 6.09021 5.31021 6.72022 5.70021 7.11022L10.5902 12.0002L5.70021 16.8902C5.31021 17.2802 5.31021 17.9102 5.70021 18.3002C6.09021 18.6902 6.72022 18.6902 7.11022 18.3002L12.0002 13.4102L16.8902 18.3002C17.2802 18.6902 17.9102 18.6902 18.3002 18.3002C18.6902 17.9102 18.6902 17.2802 18.3002 16.8902L13.4102 12.0002L18.3002 7.11022C18.6802 6.73022 18.6802 6.09022 18.3002 5.71022Z" fill="#132930"></path>
<path d="M18.3 5.70997C17.91 5.31997 17.28 5.31997 16.89 5.70997L12 10.59L7.10997 5.69997C6.71997 5.30997 6.08997 5.30997 5.69997 5.69997C5.30997 6.08997 5.30997 6.71997 5.69997 7.10997L10.59 12L5.69997 16.89C5.30997 17.28 5.30997 17.91 5.69997 18.3C6.08997 18.69 6.71997 18.69 7.10997 18.3L12 13.41L16.89 18.3C17.28 18.69 17.91 18.69 18.3 18.3C18.69 17.91 18.69 17.28 18.3 16.89L13.41 12L18.3 7.10997C18.68 6.72997 18.68 6.08997 18.3 5.70997Z" fill="#132930"></path>
</svg>

<span class="accessibility-hidden">Close</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
<label for="example2" class="TextField__label TextField__label--required">
Password field
</label>
<input type="password" id="example2" name="example2" class="TextField__input" required>
</div>
<input type="password" id="example2" name="example2" class="TextField__input" required>
</div>
</body></html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<html><body>
<div class="TextField TextField--error">
<label for="example" class="TextField__label TextField__label--required">
Text field
</label>
<input minlength="6" type="text" id="example" name="example" class="TextField__input" required>
</div>
</body></html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<html><body>
<div class="Textarea Textarea--error">
<label for="example" class="Textarea__label Textarea__label--required">
Textarea
</label>
<textarea minlength="6" id="example" name="example" class="Textarea__input" required>

</textarea>
</div>
</body></html>
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
<label for="example" class="TextField__label TextField__label--required">
Text field
</label>
<input minlength="6" type="text" id="example" name="example" class="TextField__input" required>
</div>
<input minlength="6" type="text" id="example" name="example" class="TextField__input" required>
</div>
</body></html>
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<label for="example" class="TextField__label TextField__label--required">

</label>
<input type="text" id="example" name="example" class="TextField__input" required>
<div class="TextField__message">
<input type="text" id="example" name="example" class="TextField__input" required>
<div class="TextField__message">
validation failed
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
<label for="example" class="TextField__label">
Text field
</label>
<input type="text" id="example" name="example" class="TextField__input" value="filled">
</div>
<input type="text" id="example" name="example" class="TextField__input" value="filled">
</div>
</body></html>
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
<label for="example" class="TextField__label TextField__label--hidden TextField__label--required">

</label>
<input type="text" id="example" name="example" class="TextField__input" required>
</div>
<input type="text" id="example" name="example" class="TextField__input" required>
</div>
</body></html>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Hello there!
<button type="button" class="Tooltip__close" data-dismiss="tooltip" data-target="#my-tooltip" aria-controls="my-tooltip" aria-expanded="true">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="none" id="5cf4a361209150b84108c93d7bf13d46" aria-hidden="true">
<path d="M18.3002 5.71022C17.9102 5.32022 17.2802 5.32022 16.8902 5.71022L12.0002 10.5902L7.11022 5.70021C6.72022 5.31021 6.09021 5.31021 5.70021 5.70021C5.31021 6.09021 5.31021 6.72022 5.70021 7.11022L10.5902 12.0002L5.70021 16.8902C5.31021 17.2802 5.31021 17.9102 5.70021 18.3002C6.09021 18.6902 6.72022 18.6902 7.11022 18.3002L12.0002 13.4102L16.8902 18.3002C17.2802 18.6902 17.9102 18.6902 18.3002 18.3002C18.6902 17.9102 18.6902 17.2802 18.3002 16.8902L13.4102 12.0002L18.3002 7.11022C18.6802 6.73022 18.6802 6.09022 18.3002 5.71022Z" fill="#132930"></path>
<path d="M18.3 5.70997C17.91 5.31997 17.28 5.31997 16.89 5.70997L12 10.59L7.10997 5.69997C6.71997 5.30997 6.08997 5.30997 5.69997 5.69997C5.30997 6.08997 5.30997 6.71997 5.69997 7.10997L10.59 12L5.69997 16.89C5.30997 17.28 5.30997 17.91 5.69997 18.3C6.08997 18.69 6.71997 18.69 7.10997 18.3L12 13.41L16.89 18.3C17.28 18.69 17.91 18.69 18.3 18.3C18.69 17.91 18.69 17.28 18.3 16.89L13.41 12L18.3 7.10997C18.68 6.72997 18.68 6.08997 18.3 5.70997Z" fill="#132930"></path>
</svg>

<span class="accessibility-hidden">Close</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<TextFieldBase id="example" label="Text field" type="text" name="example" isRequired validationState="error" messsage="validation failed" minlength="6" />
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<TextFieldBase id="example" label="Textarea" type="text" name="example" isRequired isMultiline validationState="error" messsage="validation failed" minlength="6" />

0 comments on commit 1a27cfc

Please sign in to comment.