diff --git a/components/atoms/spinner/README.md b/components/atoms/spinner/README.md index 9c53f84c82963d7828887f5fb688ff67ec5ebbbf..88bfb89eebabdb70db7b16243c5f015249363b0b 100644 --- a/components/atoms/spinner/README.md +++ b/components/atoms/spinner/README.md @@ -2,3 +2,66 @@ Indicate the loading state of a component or page with Bootstrap spinners, built entirely with HTML, CSS, and no JavaScript. +> ### [Bootstrap ~5.3.0 Documentation on Spinners](https://getbootstrap.com/docs/5.3/components/spinners/) +> * [Border spinner](https://getbootstrap.com/docs/5.3/components/spinners/#border-spinner) +> * [Growing spinner](https://getbootstrap.com/docs/5.3/components/spinners/#growing-spinner) +> * [Colors](https://getbootstrap.com/docs/5.3/components/spinners/#colors) +> * [Size](https://getbootstrap.com/docs/5.3/components/spinners/#size) +> * [Hidden Status](https://getbootstrap.com/docs/5.3/components/spinners/#buttons) + +### Properties: +* `html_tag`: Having the spinner as div or span. +* `type`: Use the border spinners for a lightweight loading indicator. If you do not fancy a border spinner, switch to the grow spinner. While it does not technically spin, it does repeatedly grow! +* `color`: Built with current Color, so you can easily change its appearance with text color utilities. + (primary|secondary|success|danger|warning|info|dark|light) +* `size`: Make a smaller spinner that can quickly be used within other components. +* `hidden_status`: Hidden spinner status message. +* `utility_classes`: An array of utility classes. Use to add extra Bootstrap utility classes or custom CSS classes over to this component. + +### Attributes: +* `attributes`: A list of HTML attributes for the Spinner element. +* `spinner_status_attributes`: A list of HTML attributes for the Spinner status element. + +### Slots: +* `content`: Spinner content. + +### Examples +**Example #1:** Secondary Spinner +``` + {% include 'varbase_components:spinner' with { + color: 'secondary', + content: 'Loading ...'|t, + } %} +``` + +**Example #2:** Grow Spinner +``` + {% include 'varbase_components:spinner' with { + type: 'grow', + content: 'Please, waite ...'|t, + color: 'info', + } %} +``` + +**Example #3:** Small saving border spinner with status +``` +{% include 'varbase_components:spinner' with { + color: 'primary', + type: 'border', + content: 'Saving ...', + size: 'sm', + hidden_status: false + } %} +``` + +**Example #4:** Small saving grow spinner with status +``` + {% include 'varbase_components:spinner' with { + color: 'primary', + type: 'grow', + content: 'Saving ...'|t, + size: 'sm', + hidden_status: false + } %} +``` + diff --git a/components/atoms/spinner/spinner.component.yml b/components/atoms/spinner/spinner.component.yml index a563adbac8672492a6faa2ca4b22f14d997cf2ee..b67fed61cfe1bf8097a69ebabf3cfa6199dfbe89 100644 --- a/components/atoms/spinner/spinner.component.yml +++ b/components/atoms/spinner/spinner.component.yml @@ -9,6 +9,7 @@ props: type: string title: HTML tag description: Having the spinner as div or span + default: div enum: - div - span @@ -16,36 +17,58 @@ props: type: string title: Type description: Use the border spinners for a lightweight loading indicator. If you do not fancy a border spinner, switch to the grow spinner. While it does not technically spin, it does repeatedly grow! + default: border enum: - - spinner-border - - spinner-grow + - '' + - border + - grow color: type: string title: Color - description: Once again, this spinner is built with currentColor, so you can easily change its appearance with text color utilities. Here it is in blue, along with the supported variants. + description: Built with current Color, so you can easily change its appearance with text color utilities. + default: '' enum: - - text-primary - - text-secondary - - text-success - - text-danger - - text-warning - - text-info - - text-dark - - text-light + - '' + - primary + - secondary + - success + - danger + - warning + - info + - dark + - light size: type: string title: Size - description: Add `.spinner-border-sm` and `.spinner-grow-sm` to make a smaller spinner that can quickly be used within other components. + description: Make a smaller spinner that can quickly be used within other components. + default: '' enum: - '' - sm - content: - type: string - title: Content - description: Spinner text - examples: - - Processing - - Saving - - Loading + hidden_status: + type: boolean + title: Hidden status + description: Hidden spinner status message. + default: true + utility_classes: + type: array + title: Utility Classes + default: [] + description: An array of utility classes. Use to add extra Bootstrap utility classes or custom CSS classes over to this component. attributes: type: Drupal\Core\Template\Attribute + title: Attributes + description: A list of HTML attributes for the Spinner element. + spinner_status_attributes: + type: Drupal\Core\Template\Attribute + title: Spinner Status Attributes + description: A list of HTML attributes for the Spinner status element. +slots: + content: + type: string + title: Content + description: Spinner content + examples: + - Processing + - Saving + - Loading diff --git a/components/atoms/spinner/spinner.mdx b/components/atoms/spinner/spinner.mdx new file mode 100644 index 0000000000000000000000000000000000000000..3bdefe28a9e15bfc698588b90de19caf14759bab --- /dev/null +++ b/components/atoms/spinner/spinner.mdx @@ -0,0 +1,78 @@ +{/* Spinner.mdx */} + +import { Canvas, Title, Subtitle, ArgTypes, Source, Meta, Description, Primary, Story, Stories, Controls } from '@storybook/blocks'; +import * as comStories from './spinner.stories.json'; +import templateSource from './spinner.twig?raw'; + +<Meta of={comStories} name="Docs"/> + +<Title /> +<Subtitle /> +<Description /> + + +> ### [Bootstrap ~5.3.0 Documentation on Spinners](https://getbootstrap.com/docs/5.3/components/spinners/) +> * [Border spinner](https://getbootstrap.com/docs/5.3/components/spinners/#border-spinner) +> * [Growing spinner](https://getbootstrap.com/docs/5.3/components/spinners/#growing-spinner) +> * [Colors](https://getbootstrap.com/docs/5.3/components/spinners/#colors) +> * [Size](https://getbootstrap.com/docs/5.3/components/spinners/#size) +> * [Hidden Status](https://getbootstrap.com/docs/5.3/components/spinners/#buttons) + + +<Canvas of={comStories.Spinner} /> + +## Properties +<Controls of={comStories.Spinner} /> + +<Stories of={comStories} /> + +## Attributes: +* `attributes`: A list of HTML attributes for the Spinner element. +* `spinner_status_attributes`: A list of HTML attributes for the Spinner status element. + +## Slots: +* `content`: Spinner content. + +### Examples +**Example #1:** Secondary Spinner +``` + {% include 'varbase_components:spinner' with { + color: 'secondary', + content: 'Loading ...'|t, + } %} +``` + +**Example #2:** Grow Spinner +``` + {% include 'varbase_components:spinner' with { + type: 'grow', + content: 'Please, waite ...'|t, + color: 'info', + } %} +``` + +**Example #3:** Small saving border spinner with status +``` +{% include 'varbase_components:spinner' with { + color: 'primary', + type: 'border', + content: 'Saving ...', + size: 'sm', + hidden_status: false + } %} +``` + +**Example #4:** Small saving grow spinner with status +``` + {% include 'varbase_components:spinner' with { + color: 'primary', + type: 'grow', + content: 'Saving ...'|t, + size: 'sm', + hidden_status: false + } %} +``` + +## Source code +[//]: # (Twig Template source code) +<Source code={templateSource} /> diff --git a/components/atoms/spinner/spinner.stories.json b/components/atoms/spinner/spinner.stories.json new file mode 100644 index 0000000000000000000000000000000000000000..484839bc3355d8f42599cd598fe7d0ad0bf9d3d2 --- /dev/null +++ b/components/atoms/spinner/spinner.stories.json @@ -0,0 +1,213 @@ +{ + "title": "Varbase Components/Atoms/Spinner", + "tags": [ + "autodocs" + ], + "parameters": { + "componentSubtitle": "Bootstrap Spinner Component", + "docs": { + "description": { + "component": "Indicate the loading state of a component or page with Bootstrap spinners, built entirely with HTML, CSS, and no JavaScript." + }, + "story": { + "inline": true + } + } + }, + "argTypes": { + "html_tag": { + "name": "HTML tag", + "description": "Having the spinner as div or span", + "defaultValue": "div", + "control": "select", + "options": { + "div": "div", + "span": "span" + } + }, + "type": { + "name": "Type", + "description": "Use the border spinners for a lightweight loading indicator. If you do not fancy a border spinner, switch to the grow spinner. While it does not technically spin, it does repeatedly grow!", + "defaultValue": "border", + "control": "select", + "options": { + "'- none -'": "", + "Border": "border", + "Grow": "grow" + } + }, + "color": { + "name": "Color", + "description": "Built with current Color, so you can easily change its appearance with text color utilities.", + "defaultValue": "", + "control": "select", + "options": { + "'- none -'": "", + "Primary": "primary", + "Secondary": "secondary", + "Success": "success", + "Danger": "danger", + "Warning": "warning", + "Info": "info", + "Light": "light", + "Dark": "dark" + } + }, + "size": { + "name": "Size", + "description": "Make a smaller spinner that can quickly be used within other components.", + "defaultValue": "", + "control": "select", + "options": { + "'- none -'": "", + "Small": "sm" + } + }, + "hidden_status": { + "name": "Hidden status", + "description": "Hidden spinner status message.", + "defaultValue": true, + "control": "boolean" + }, + "content": { + "name": "Content", + "description": "Spinner text", + "defaultValue": "", + "control": "text" + } + }, + "stories": [ + { + "name": "Spinner", + "args": { + "html_tag": "div", + "type": "border", + "color": "", + "size": "", + "hidden_status": true, + "content": "Processing ..." + } + }, + { + "name": "Grow", + "args": { + "html_tag": "div", + "type": "grow", + "color": "", + "size": "", + "hidden_status": true, + "content": "Loading ..." + } + }, + { + "name": "Border - small", + "args": { + "html_tag": "div", + "type": "border", + "color": "", + "size": "sm", + "hidden_status": false, + "content": "Saving ..." + } + }, + { + "name": "Grow - small", + "args": { + "html_tag": "div", + "type": "grow", + "color": "", + "size": "sm", + "hidden_status": false, + "content": "Saving ..." + } + }, + { + "name": "Primary", + "args": { + "html_tag": "div", + "type": "border", + "color": "primary", + "size": "", + "hidden_status": true, + "content": "Loading ..." + } + }, + { + "name": "Secondary", + "args": { + "html_tag": "div", + "type": "border", + "color": "secondary", + "size": "", + "hidden_status": true, + "content": "Loading ..." + } + }, + { + "name": "Success", + "args": { + "html_tag": "div", + "type": "border", + "color": "success", + "size": "", + "hidden_status": true, + "content": "Loading ..." + } + }, + { + "name": "Danger", + "args": { + "html_tag": "div", + "type": "border", + "color": "danger", + "size": "", + "hidden_status": true, + "content": "Loading ..." + } + }, + { + "name": "Warning", + "args": { + "html_tag": "div", + "type": "border", + "color": "warning", + "size": "", + "hidden_status": true, + "content": "Loading ..." + } + }, + { + "name": "Info", + "args": { + "html_tag": "div", + "type": "border", + "color": "info", + "size": "", + "hidden_status": true, + "content": "Loading ..." + } + }, + { + "name": "Dark", + "args": { + "html_tag": "div", + "type": "border", + "color": "dark", + "size": "", + "hidden_status": true, + "content": "Loading ..." + } + }, + { + "name": "Light", + "args": { + "html_tag": "div", + "type": "border", + "color": "light", + "size": "", + "hidden_status": true, + "content": "Loading ..." + } + } + ] +} diff --git a/components/atoms/spinner/spinner.twig b/components/atoms/spinner/spinner.twig index 70b02d8877bc6321feffbe8ca45fb9ae8cbfe49f..2afd6fe66a8cd290bf151aaa6b2b97993a29a02d 100644 --- a/components/atoms/spinner/spinner.twig +++ b/components/atoms/spinner/spinner.twig @@ -3,26 +3,61 @@ * @file * Varbase Components implementation for a Spinner component. * - * Available config: - * - tag: div | span - * - type: spinner-border | spinner-grow - * - color: text-primary | text-secondary | text-success | text-danger | text-warning | text-info | text-dark | text-light - * - size: sm - * - attributes: Attributes array. - * - utility_classes: An array of utility classes. + * Available properties: + * - html_tag: Having the spinner as div or span. + * - type: Use the border spinners for a lightweight loading indicator. If you do not fancy a border spinner, switch to the grow spinner. While it does not technically spin, it does repeatedly grow! + * - color: Built with current Color, so you can easily change its appearance with text color utilities. + * (primary|secondary|success|danger|warning|info|dark|light) + * - size: Make a smaller spinner that can quickly be used within other components. + * - hidden_status: Hidden spinner status message. + * - utility_classes: An array of utility classes. Use to add extra Bootstrap utility classes or custom CSS classes over to this component. + * + * Available attributes: + * - attributes: A list of HTML attributes for the Spinner element. + * - spinner_status_attributes: A list of HTML attributes for the Spinner status element. + * + * Available slots: + * - content: Spinner content. + * **Examples:** + * - Processing + * - Saving + * - Loading + * */ #} +{% set html_tag = html_tag ? html_tag : 'div' %} +{% set type = type ?? 'border' %} +{% set type_classes = type ? ['spinner-' ~ type] : ['spinner-border'] %} +{% set size_classes = size ? ['spinner-' ~ type ~ '-' ~ size] : [] %} +{% set color_classes = color ? ['text-' ~ color] : [] %} +{% set hidden_status = hidden_status ?? true %} {% set utility_classes = utility_classes ? utility_classes : [] %} -{% set classes = [ - type ? type : 'spinner-border', - color ? color : '', - size ? type ~ '-' ~ size : '', -]|merge(utility_classes) %} +{% set classes = []|merge(type_classes)|merge(size_classes)|merge(color_classes)|merge(utility_classes) %} + +{% if not attributes %} + {% set attributes = create_attribute() %} +{% endif %} +{% set attributes = attributes.addClass(classes) %} + +{% if not spinner_status_attributes %} + {% set spinner_status_attributes = create_attribute() %} +{% endif %} + +{% if hidden_status %} + {% set attributes = attributes.setAttribute('role', 'status') %} + {% set attributes = attributes.setAttribute('aria-hidden', 'true') %} + {% set spinner_status_attributes = spinner_status_attributes.addClass('visually-hidden') %} +{% else %} + {% set spinner_status_attributes = spinner_status_attributes.setAttribute('role', 'status') %} +{% endif %} -<{{ tag }} {{ attributes.addClass(classes) }} role="status"> - {% if content %} - <span class="visually-hidden">{{ content }}</span> +<{{ html_tag }}{{ attributes }}>{% apply spaceless %} + {% if content and hidden_status %} + <span{{ spinner_status_attributes }}>{{ content }}</span> {% endif %} -</{{ tag }}> +{% endapply %}</{{ html_tag }}> +{% if content and not hidden_status %}{% apply spaceless %} + <span{{ spinner_status_attributes }}>{{ content }}</span> +{% endapply %}{% endif %}