Skip to content

Commit

Permalink
Feat(web-twig): Add Message and Link for ToastBar #DS-1213
Browse files Browse the repository at this point in the history
  • Loading branch information
curdaj committed May 28, 2024
1 parent e60fabb commit d0f9663
Show file tree
Hide file tree
Showing 18 changed files with 269 additions and 77 deletions.
12 changes: 5 additions & 7 deletions apps/web-twig-demo/assets/scripts/toast-dynamic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ const addDynamicToast = (event, containerId) => {
hasIcon: formElement.querySelector('#toast-has-icon').checked,
id: `my-dynamic-toast-${Date.now()}`,
isDismissible: formElement.querySelector('#toast-is-dismissible').checked,
link: formElement.querySelector('#toast-link').value,
message: formElement.querySelector('#toast-message').value,
linkContent: formElement.querySelector('#toast-enable-link').checked
? formElement.querySelector('#toast-link').value
: null,
linkProps: {
href: formElement.querySelector('#toast-link-href').value,
target: formElement.querySelector('#toast-link-target').value,
color: formElement.querySelector('#toast-link-color').value,
isUnderlined: formElement.querySelector('#toast-link-underlined').checked,
isDisabled: formElement.querySelector('#toast-link-disabled').checked,
elementType: formElement.querySelector('#toast-link-element').value,
href: '#',
},
};

Expand Down
34 changes: 29 additions & 5 deletions packages/web-twig/src/Resources/components/Toast/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,21 +186,31 @@ Alternatively, a custom icon can be used:

### ToastBar Components

The content of `ToastBar` can be assembled from the following components:
The content of `ToastBar` can be assembled from the following subcomponents:

#### ToastBarMessage

`ToastBarMessage` is a component designates for main message in `ToastBar`.
`ToastBarMessage` is a subcomponent designated for the main message in `ToastBar`.

```twig
<ToastBar>
<ToastBarMessage>Message</ToastBarMessage>
</ToastBar>
```

#### API

| Name | Type | Default | Required | Description |
| ---------- | -------- | ------- | -------- | ---------------------- |
| `children` | `string` ||| Content of the message |

On top of the API options, the components accept [additional attributes][readme-additional-attributes].
If you need more control over the styling of a component, you can use [style props][readme-style-props]
and [escape hatches][readme-escape-hatches].

#### ToastBarLink

`ToastBarLink` is a component designated to create an action link within `ToastBar`.
`ToastBarLink` is a subcomponent designated to create an action link within `ToastBar`.

```twig
<ToastBar>
Expand All @@ -213,11 +223,16 @@ The content of `ToastBar` can be assembled from the following components:

| Name | Type | Default | Required | Description |
| -------------- | ------------------------------------------------ | ---------- | -------- | ------------------------------ |
| `children` | `string` ||| Content of the link |
| `color` | [Action Link Color dictionary][dictionary-color] | `inverted` || Color of the link |
| `href` | `string` ||| ToastBarLink's href attribute |
| `isDisabled` | `bool` | `false` || Whether is the link disabled |
| `isUnderlined` | `bool` | `true` || Whether is the link underlined |

On top of the API options, the components accept [additional attributes][readme-additional-attributes].
If you need more control over the styling of a component, you can use [style props][readme-style-props]
and [escape hatches][readme-escape-hatches].

👉 **Do not put any important actions** like "Undo" in the ToastBar component (unless there are other means to perform
said action), as it is very hard (if not impossible) to reach for users with assistive technologies. Read more about
[Toast accessibility][scott-o-hara-toast] at Scott O'Hara's blog.
Expand Down Expand Up @@ -348,12 +363,21 @@ Then configure and create a new Toast instance and call the `show` method on it,
import Toast from '@lmc-eu/spirit-web/dist/js/Toast';

const toast = new Toast(null, {
autoCloseInterval: 3000 // Set interval after ToastBar will be closed in ms, default: 3000
autoCloseInterval: 3000, // Set interval after ToastBar will be closed in ms, default: 3000
color: 'informative', // One of ['inverted' (default), 'success', 'warning, 'danger', 'informative']
containerId: 'toast-example', // Must match the ID of the Toast container in HTML
content: 'Hello, this is my toast message!', // Can be plain text or HTML
enableAutoClose: true, // If true, ToastBar will close after `autoCloseInterval`, default: true
hasIcon: true,
message: 'Hello, this is my toast message!', // Can be plain text or HTML
linkContent: 'Action', // Link text
linkProps: {
href: 'https://example.com', // Link URL
target: '_blank', // Optional link target attribute
isUnderlined: false, // Optional link underlining, default: true
isDisabled: false, // Optional link disabling, default: false
elementType: 'a', // Optional link element type, default: 'a'
color: 'inverted', // Optional link color variant, default: 'inverted'
},
iconName: 'info', // Optional icon name used as the #fragment in the SVG sprite URL
id: 'my-toast', // An ID is required for dismissible ToastBar
isDismissible: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
{%- set _rootColorClassName = _spiritClassPrefix ~ 'ToastBar--' ~ _color -%}
{%- set _rootDismissibleClassName = _isDismissible is same as(true) and _isTemplate is same as(false) ? _spiritClassPrefix ~ 'ToastBar--dismissible' : null -%}
{%- set _boxClassName = _spiritClassPrefix ~ 'ToastBar__box' -%}
{%- set _containerClassName = _spiritClassPrefix ~ 'ToastBar__container' -%}
{%- set _contentClassName = _spiritClassPrefix ~ 'ToastBar__content' -%}
{%- set _messageClassName = _spiritClassPrefix ~ 'ToastBar__message' -%}
{%- set _isOpenClassName = _isOpen or _isTemplate ? 'is-open' : 'is-hidden' -%}

{# Attributes #}
Expand Down Expand Up @@ -43,7 +43,7 @@
data-spirit-populate-field="item"
>
<div class="{{ _boxClassName }}">
<div class="{{ _contentClassName }}">
<div class="{{ _containerClassName }}">
{% if _hasIcon or _iconName %}
{% if _isTemplate %}
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true" data-spirit-populate-field="icon">
Expand All @@ -53,7 +53,7 @@
<Icon boxSize="20" name="{{ _iconNameValue }}" isReusable={ false } />
{% endif %}
{% endif %}
<div class="{{ _messageClassName }}" data-spirit-populate-field="message">
<div class="{{ _contentClassName }}">
{% block content %}{% endblock %}
</div>
</div>
Expand Down
24 changes: 24 additions & 0 deletions packages/web-twig/src/Resources/components/Toast/ToastBarLink.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{# API #}
{%- set props = props | default([]) -%}
{%- set _color = props.color | default('inverted') -%}
{%- set _isUnderlined = props.isUnderlined ?? true -%}
{%- set _children = block('content') -%}

{# Class names #}
{%- set _rootClassName = _spiritClassPrefix ~ 'ToastBar__link' -%}

{# Miscellaneous #}
{%- set _styleProps = useStyleProps(props) -%}
{%- set _allowedAttributes = [ 'target', 'title' ] -%}
{%- set _classNames = [ _rootClassName, _styleProps.className ] -%}

{% embed "@spirit/link.twig" with { props: props | merge({
color: _color,
isUnderlined: _isUnderlined,
'data-spirit-populate-field': 'link',
UNSAFE_className: _classNames | join(' '),
UNSAFE_style: _styleProps.style,
}) } %}
{% block content %}{{ _children }}{% endblock %}
{% endembed %}

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{# API #}
{%- set props = props | default([]) -%}

{# Miscellaneous #}
{%- set _styleProps = useStyleProps(props) -%}
{%- set _textTruncateClassName = _spiritClassPrefix ~ 'text-truncate-multiline' -%}
{%- set _classNames = [ _styleProps.className, _textTruncateClassName ] -%}


<div
{{ mainProps(props) }}
{{ styleProp(_styleProps) }}
{{ classProp(_classNames) }}
data-spirit-populate-field="message"
>
{% block content %}{% endblock %}
</div>
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
<ToastBar>Message only</ToastBar>
<ToastBar>
<ToastBarMessage>Message only</ToastBarMessage>
</ToastBar>

<!-- Render with default icon -->
<ToastBar hasIcon>
Message with icon
<ToastBarMessage>Message with icon</ToastBarMessage>
</ToastBar>

<!-- Render with custom icon using `iconName` alone -->
<ToastBar iconName="download">
Message with custom icon
<ToastBarMessage>Message with custom icon</ToastBarMessage>
</ToastBar>

<!-- Render in success color with matching icon and close button -->
<ToastBar color="success" id="toast-dismiss" isDismissible>
Dismissible message with success color
<ToastBarMessage>Dismissible message with success color</ToastBarMessage>
</ToastBar>

<!-- Render as template -->
Expand All @@ -33,8 +35,8 @@
UNSAFE_className="custom-class"
UNSAFE_style="outline: 5px solid blue; outline-offset: -5px;"
>
Dismissible message with custom icon and action
<Link href="#" color="inverted" isUnderlined>Action</Link>
<ToastBarMessage>Dismissible message with custom icon and action</ToastBarMessage>
<ToastBarLink href="#">Action</ToastBarLink>
</ToastBar>

<!-- Render as template with all props -->
Expand All @@ -50,6 +52,6 @@
UNSAFE_className="custom-class"
UNSAFE_style="outline: 5px solid blue; outline-offset: -5px;"
>
Dismissible message with custom icon and action
<Link href="#" color="inverted" isUnderlined>Action</Link>
<ToastBarMessage>Dismissible message with custom icon and action</ToastBarMessage>
<ToastBarLink href="#">Action</ToastBarLink>
</ToastBar>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<ToastBarLink>ToastBar Link</ToastBarLink>

<!-- Render with all props -->
<ToastBarLink
color="primary"
href="https://www.google.com"
target="_blank"
isUnderlined={false}
isDisabled={false}
UNSAFE_className="custom-class"
UNSAFE_style="outline: 5px solid blue; outline-offset: -5px;"
>
ToastBar Link
</ToastBarLink>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<ToastBarMessage>ToastBar Message</ToastBarMessage>

<!-- Render with all props -->
<ToastBarMessage
UNSAFE_className="custom-class"
UNSAFE_style="outline: 5px solid blue; outline-offset: -5px;"
>
ToastBar Message
</ToastBarMessage>
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
<body>
<div class="ToastBar ToastBar--inverted is-open" data-spirit-populate-field="item">
<div class="ToastBar__box">
<div class="ToastBar__content">
<div class="ToastBar__message" data-spirit-populate-field="message">
Message only
<div class="ToastBar__container">
<div class="ToastBar__content">
<div class="text-truncate-multiline" data-spirit-populate-field="message">
Message only
</div>
</div>
</div>
</div>
Expand All @@ -18,12 +20,14 @@

<div class="ToastBar ToastBar--inverted is-open" data-spirit-populate-field="item">
<div class="ToastBar__box">
<div class="ToastBar__content">
<div class="ToastBar__container">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM13 17H11V11H13V17ZM13 9H11V7H13V9Z" fill="currentColor">
</path></svg>
<div class="ToastBar__message" data-spirit-populate-field="message">
Message with icon
<div class="ToastBar__content">
<div class="text-truncate-multiline" data-spirit-populate-field="message">
Message with icon
</div>
</div>
</div>
</div>
Expand All @@ -32,12 +36,14 @@

<div class="ToastBar ToastBar--inverted is-open" data-spirit-populate-field="item">
<div class="ToastBar__box">
<div class="ToastBar__content">
<div class="ToastBar__container">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M12 16.575C11.8667 16.575 11.7417 16.5542 11.625 16.5125C11.5083 16.4708 11.4 16.4 11.3 16.3L6.7 11.7C6.51667 11.5167 6.425 11.2833 6.425 11C6.425 10.7167 6.51667 10.4833 6.7 10.3C6.88333 10.1167 7.12083 10.0208 7.4125 10.0125C7.70417 10.0042 7.94167 10.0917 8.125 10.275L11 13.15V4C11 3.71667 11.0958 3.47917 11.2875 3.2875C11.4792 3.09583 11.7167 3 12 3C12.2833 3 12.5208 3.09583 12.7125 3.2875C12.9042 3.47917 13 3.71667 13 4V13.15L15.875 10.275C16.0583 10.0917 16.2958 10.0042 16.5875 10.0125C16.8792 10.0208 17.1167 10.1167 17.3 10.3C17.4833 10.4833 17.575 10.7167 17.575 11C17.575 11.2833 17.4833 11.5167 17.3 11.7L12.7 16.3C12.6 16.4 12.4917 16.4708 12.375 16.5125C12.2583 16.5542 12.1333 16.575 12 16.575ZM5 21C4.45 21 3.97917 20.8042 3.5875 20.4125C3.19583 20.0208 3 19.55 3 19V17C3 16.7167 3.09583 16.4792 3.2875 16.2875C3.47917 16.0958 3.71667 16 4 16C4.28333 16 4.52083 16.0958 4.7125 16.2875C4.90417 16.4792 5 16.7167 5 17V19H19V17C19 16.7167 19.0958 16.4792 19.2875 16.2875C19.4792 16.0958 19.7167 16 20 16C20.2833 16 20.5208 16.0958 20.7125 16.2875C20.9042 16.4792 21 16.7167 21 17V19C21 19.55 20.8042 20.0208 20.4125 20.4125C20.0208 20.8042 19.55 21 19 21H5Z" fill="currentColor">
</path></svg>
<div class="ToastBar__message" data-spirit-populate-field="message">
Message with custom icon
<div class="ToastBar__content">
<div class="text-truncate-multiline" data-spirit-populate-field="message">
Message with custom icon
</div>
</div>
</div>
</div>
Expand All @@ -46,9 +52,11 @@

<div class="ToastBar ToastBar--success ToastBar--dismissible is-open" id="toast-dismiss" data-spirit-populate-field="item">
<div class="ToastBar__box">
<div class="ToastBar__content">
<div class="ToastBar__message" data-spirit-populate-field="message">
Dismissible message with success color
<div class="ToastBar__container">
<div class="ToastBar__content">
<div class="text-truncate-multiline" data-spirit-populate-field="message">
Dismissible message with success color
</div>
</div>
</div>
<button data-spirit-dismiss="toast" data-spirit-populate-field="close-button" data-spirit-target="#toast-dismiss" aria-controls="toast-dismiss" aria-expanded="true" class="Button Button--success Button--small Button--square" type="button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="none" aria-hidden="true">
Expand All @@ -60,8 +68,8 @@

<div class="ToastBar ToastBar--inverted is-open" data-spirit-populate-field="item">
<div class="ToastBar__box">
<div class="ToastBar__content">
<div class="ToastBar__message" data-spirit-populate-field="message">
<div class="ToastBar__container">
<div class="ToastBar__content">
</div>
</div>
</div>
Expand All @@ -70,11 +78,11 @@

<div class="ToastBar ToastBar--inverted is-open" id="template-toast" data-spirit-populate-field="item">
<div class="ToastBar__box">
<div class="ToastBar__content">
<div class="ToastBar__container">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 24 24" fill="none" aria-hidden="true" data-spirit-populate-field="icon">
<use xlink:href="#">
</use></svg>
<div class="ToastBar__message" data-spirit-populate-field="message">
<div class="ToastBar__content">
</div>
</div>
<button data-spirit-dismiss="toast" data-spirit-populate-field="close-button" data-spirit-target="#template-toast" aria-controls="template-toast" aria-expanded="true" class="Button Button--inverted Button--small Button--square" type="button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="none" aria-hidden="true">
Expand All @@ -86,12 +94,15 @@

<div style="outline: 5px solid blue; outline-offset: -5px;" class="ToastBar ToastBar--success ToastBar--dismissible is-hidden custom-class" id="my-toast" data-spirit-populate-field="item">
<div class="ToastBar__box">
<div class="ToastBar__content">
<div class="ToastBar__container">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M12 16.575C11.8667 16.575 11.7417 16.5542 11.625 16.5125C11.5083 16.4708 11.4 16.4 11.3 16.3L6.7 11.7C6.51667 11.5167 6.425 11.2833 6.425 11C6.425 10.7167 6.51667 10.4833 6.7 10.3C6.88333 10.1167 7.12083 10.0208 7.4125 10.0125C7.70417 10.0042 7.94167 10.0917 8.125 10.275L11 13.15V4C11 3.71667 11.0958 3.47917 11.2875 3.2875C11.4792 3.09583 11.7167 3 12 3C12.2833 3 12.5208 3.09583 12.7125 3.2875C12.9042 3.47917 13 3.71667 13 4V13.15L15.875 10.275C16.0583 10.0917 16.2958 10.0042 16.5875 10.0125C16.8792 10.0208 17.1167 10.1167 17.3 10.3C17.4833 10.4833 17.575 10.7167 17.575 11C17.575 11.2833 17.4833 11.5167 17.3 11.7L12.7 16.3C12.6 16.4 12.4917 16.4708 12.375 16.5125C12.2583 16.5542 12.1333 16.575 12 16.575ZM5 21C4.45 21 3.97917 20.8042 3.5875 20.4125C3.19583 20.0208 3 19.55 3 19V17C3 16.7167 3.09583 16.4792 3.2875 16.2875C3.47917 16.0958 3.71667 16 4 16C4.28333 16 4.52083 16.0958 4.7125 16.2875C4.90417 16.4792 5 16.7167 5 17V19H19V17C19 16.7167 19.0958 16.4792 19.2875 16.2875C19.4792 16.0958 19.7167 16 20 16C20.2833 16 20.5208 16.0958 20.7125 16.2875C20.9042 16.4792 21 16.7167 21 17V19C21 19.55 20.8042 20.0208 20.4125 20.4125C20.0208 20.8042 19.55 21 19 21H5Z" fill="currentColor">
</path></svg>
<div class="ToastBar__message" data-spirit-populate-field="message">
Dismissible message with custom icon and action <a href="#" class="link-inverted link-underlined">Action</a>
<div class="ToastBar__content">
<div class="text-truncate-multiline" data-spirit-populate-field="message">
Dismissible message with custom icon and action
</div>
<a data-spirit-populate-field="link" href="#" class="link-inverted link-underlined ToastBar__link">Action</a>
</div>
</div>
<button data-spirit-dismiss="toast" data-spirit-populate-field="close-button" data-spirit-target="#my-toast" aria-controls="my-toast" aria-expanded="true" class="Button Button--success Button--small Button--square" type="button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="none" aria-hidden="true">
Expand All @@ -103,12 +114,15 @@

<div style="outline: 5px solid blue; outline-offset: -5px;" class="ToastBar ToastBar--success is-open custom-class" id="my-toast-template" data-spirit-populate-field="item">
<div class="ToastBar__box">
<div class="ToastBar__content">
<div class="ToastBar__container">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 24 24" fill="none" aria-hidden="true" data-spirit-populate-field="icon">
<use xlink:href="#">
</use></svg>
<div class="ToastBar__message" data-spirit-populate-field="message">
Dismissible message with custom icon and action <a href="#" class="link-inverted link-underlined">Action</a>
<div class="ToastBar__content">
<div class="text-truncate-multiline" data-spirit-populate-field="message">
Dismissible message with custom icon and action
</div>
<a data-spirit-populate-field="link" href="#" class="link-inverted link-underlined ToastBar__link">Action</a>
</div>
</div>
<button data-spirit-dismiss="toast" data-spirit-populate-field="close-button" data-spirit-target="#my-toast-template" aria-controls="my-toast-template" aria-expanded="true" class="Button Button--success Button--small Button--square" type="button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="none" aria-hidden="true">
Expand Down
Loading

0 comments on commit d0f9663

Please sign in to comment.