From 6138683db18f2d57277177b082be092ca1f08951 Mon Sep 17 00:00:00 2001 From: Craig Cook Date: Thu, 4 Apr 2024 15:57:19 -0700 Subject: [PATCH] Add optional icon to buttons [fix #893] (#925) --- CHANGELOG.md | 1 + assets/sass/protocol/components/_button.scss | 28 +++++++++ components/button/button--with-icon.html | 63 +++++++++++++++++++ components/button/button--with-icon.readme.md | 47 ++++++++++++++ components/button/button.config.yml | 20 +++--- components/button/button.html | 32 +++++++++- 6 files changed, 178 insertions(+), 13 deletions(-) create mode 100644 components/button/button--with-icon.html create mode 100644 components/button/button--with-icon.readme.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f79af7f..ac0feba7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Features * **component** Remove the format option from Newsletter component +* **component:** Allow an optional icon in buttons (#893) # 19.0.0 diff --git a/assets/sass/protocol/components/_button.scss b/assets/sass/protocol/components/_button.scss index 702832a6..5272c1b2 100644 --- a/assets/sass/protocol/components/_button.scss +++ b/assets/sass/protocol/components/_button.scss @@ -291,3 +291,31 @@ a.mzp-c-button { text-decoration: underline; } } + +// * -------------------------------------------------------------------------- */ +// Icon + +.mzp-c-button-icon-start, +.mzp-c-button-icon-end { + display: inline-block; + font-size: 1em; + height: 1em; + line-height: 1em; + vertical-align: baseline; + width: 1em; + + img, + svg { + height: 100%; + margin-bottom: -0.15em; + width: 100%; + } +} + +.mzp-c-button-icon-start { + @include bidi(((margin-right, 0.5ch, 0), (margin-left, 0, 0.5ch),)); +} + +.mzp-c-button-icon-end { + @include bidi(((margin-left, 0.5ch, 0), (margin-right, 0, 0.5ch),)); +} diff --git a/components/button/button--with-icon.html b/components/button/button--with-icon.html new file mode 100644 index 00000000..08115d4d --- /dev/null +++ b/components/button/button--with-icon.html @@ -0,0 +1,63 @@ +

+{% render '@button', { label: 'Button with Icon', + iconEnd: + ' + + ' } +%} +

+ +

+{% render '@button', { label: 'Button with Icon', + iconStart: + ' + + ' } +%} +

+ +

+{% render '@button', { class: 'mzp-t-xl mzp-t-product', label: 'Download Firefox', link: 'https://www.mozilla.org/firefox/new/', + iconEnd: + ' + + + ' } +%} +

+ +

+{% render '@button', { class: 'mzp-t-product mzp-t-secondary', label: 'Try Reader Mode', + iconStart: + ' + + + + + ' } +%} +

+ +

+{% render '@button', { class: 'mzp-t-sm mzp-t-secondary', label: 'Previous', link: '#', + iconStart: + ' + + ' } +%} + +{% render '@button', { class: 'mzp-t-sm mzp-t-secondary', label: 'Next', link: '#', + iconEnd: + ' + + ' } +%} +

+ +

+ {% render '@button', { label: 'Character', iconEnd: '❤︎' } %} +

+ +

+ {% render '@button', { label: 'Emoji', iconEnd: '❤️' } %} +

diff --git a/components/button/button--with-icon.readme.md b/components/button/button--with-icon.readme.md new file mode 100644 index 00000000..9e0cdba9 --- /dev/null +++ b/components/button/button--with-icon.readme.md @@ -0,0 +1,47 @@ +You can add an icon to a button as an inline image enclosed in a `span` with the +class `mzp-c-button-icon-start` if the icon appears before the text label or +`mzp-c-button-icon-end` if it appears after the label. + +You can optionally use a standard unicode character or symbol, but be aware not +all platforms will support all characters. Icon fonts are also an option, with +all the usual caveats about using webfonts. You can use an emoji but they also +may not be supported equally across platforms and even on supporting platforms +they’ll be rendered in completely different styles by different systems. For +consistency and reliability, use an image. + +### Tips +- Prefer simple, single-color icons. Complex images likely won’t render well at + such a small size. Multicolored icons or logos may not adapt to different + backgrounds as the button state changes. + +- Prefer embedded SVG over an external `img` (whether SVG or other format). An + inline SVG icon can more easily change color for the different button states + and style variants. Be aware that very old browsers don’t support SVG. + +- Consider the text direction of the page language. Arrows in particular indicate + a specific orientation that may be confusing in text that flows the opposite + direction. The “Next” and “Previous” buttons shown here are a good example of + how this can go wrong. In a right-to-left language, the “Next” arrow moves to + the left of the text label, but still points to the right. A properly + bi-directional design should reverse those icons as well. + +### Tips for inline SVG +- Optimize SVG files for embedding inline in the HTML document. Strip out unnecessary + comments or metadata added by editing tools. Use [SVGO](https://svgo.dev/) + either locally on [online](https://jakearchibald.github.io/svgomg/). + +- Merge shapes and paths where possible to reduce the number of elements and points. + +- Avoid unnecessary grouping of elements. + +- Define colors with `currentColor`. This will inherit the icon’s color from the + button text, including color changes in hover and focus states. An icon with + its own defined colors will need to accommodate background color changes, + either with a color that is visible on all backgrounds, or facilitating a + color change some other way besides `currentColor` (e.g. with additional CSS). + +### No-Nos +- Don’t add multiple icons to a button. Technically Protocol doesn’t prevent it, + it’s just a bad idea. + + diff --git a/components/button/button.config.yml b/components/button/button.config.yml index 2f9cb6e8..a5624c35 100644 --- a/components/button/button.config.yml +++ b/components/button/button.config.yml @@ -16,54 +16,54 @@ variants: preview: '@preview-dark' notes: A light variation of the secondary button for dark backgrounds, adding the class `mzp-t-dark` (the button itself is light). context: - class: mzp-t-secondary mzp-t-dark + class: 'mzp-t-secondary mzp-t-dark' label: Secondary Button - name: Product notes: Use this theme style for product-related transactions, such as downloading software or creating an account. context: - class: mzp-t-product + class: 'mzp-t-product' label: Download Firefox - name: Product Secondary notes: This secondary product button theme should be used when the CTA is a product-related transaction, but not the main action a person should take on a page. context: - class: mzp-t-product mzp-t-secondary + class: 'mzp-t-product mzp-t-secondary' label: Download Firefox - name: Product Secondary Dark preview: '@preview-dark' notes: A light variation of the secondary product button for use on dark backgrounds. Add the class `mzp-t-dark` (the button itself is light). context: - class: mzp-t-product mzp-t-secondary mzp-t-dark + class: 'mzp-t-product mzp-t-secondary mzp-t-dark' label: Download Firefox - name: Neutral notes: A neutral button for less important actions. context: - class: mzp-t-neutral + class: 'mzp-t-neutral' label: Neutral Button - name: Neutral Dark preview: '@preview-dark' notes: A light variation of the neutral button for use on dark backgrounds. Add the class `mzp-t-dark` (the button itself is light). context: - class: mzp-t-neutral mzp-t-dark + class: 'mzp-t-neutral mzp-t-dark' label: Neutral Button - name: Size small notes: A small button. Use this size with caution because small buttons are harder to read and present smaller targets for pointing devices (clicks and taps). context: - class: mzp-t-sm + class: 'mzp-t-sm' label: Small Button - name: Size medium notes: A medium button. context: - class: mzp-t-md + class: 'mzp-t-md' label: Medium Button - name: Size large notes: This is the default size if no size class is provided. context: - class: mzp-t-lg + class: 'mzp-t-lg' label: Large Button - name: Size Extra Large notes: An extra large button. Use this sparingly. context: - class: mzp-t-xl + class: 'mzp-t-xl' label: Extra Large Button - name: Disabled notes: | diff --git a/components/button/button.html b/components/button/button.html index 8a9c6f4b..5bb67e49 100644 --- a/components/button/button.html +++ b/components/button/button.html @@ -6,9 +6,35 @@ # link - URL # type - type attribute value (button, submit, reset) # disabled - Boolean +# iconStart - markup +# iconEnd - markup #} -{%- if href -%} -{{ label }} +{%- if link -%} + + {%- if iconStart %} + + {{ iconStart | safe }} + + {% endif -%} + {{ label }} + {%- if iconEnd %} + + {{ iconEnd | safe }} + + {% endif -%} + {%- else -%} - + {%- endif -%}