Skip to content

Commit

Permalink
Add optional icon to buttons [fix mozilla#893]
Browse files Browse the repository at this point in the history
  • Loading branch information
craigcook committed Mar 25, 2024
1 parent a4328a2 commit d8b0536
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 13 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# HEAD

## Features
* **component:** Allow an optional icon in buttons (#893)

# 19.0.0

## Features
Expand Down
32 changes: 32 additions & 0 deletions assets/sass/protocol/components/_button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,35 @@ a.mzp-c-button {
text-decoration: underline;
}
}

// * -------------------------------------------------------------------------- */
// Icon

/* stylelint-disable-next-line no-duplicate-selectors */
.mzp-c-button,
a.mzp-c-button {
&.mzp-t-icon-start {
.mzp-c-button-icon {
@include bidi(((margin-right, 0.5ch, 0), (margin-left, 0, 0.5ch),));
}
}

&.mzp-t-icon-end {
.mzp-c-button-icon {
@include bidi(((margin-left, 0.5ch, 0), (margin-right, 0, 0.5ch),));
}
}
}

.mzp-c-button-icon {
display: inline-block;
height: 1em;
vertical-align: text-top;
width: 1em;

img,
svg {
height: 100%;
width: 100%;
}
}
55 changes: 55 additions & 0 deletions components/button/button--with-icon.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<p>
{% render '@button', { class: 'mzp-t-icon-end', label: 'Button with Icon',
icon:
'<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 24 24" width="24" height="24" fill="currentColor">
<path d="m21.3 4.5-8-4c-.8-.4-1.8-.4-2.7 0l-8 4C1.6 5.1 1 6.1 1 7.2v9.5c0 1.1.6 2.2 1.7 2.7l8 4c.4.2.9.3 1.3.3s.9-.1 1.3-.3l8-4c1-.5 1.7-1.5 1.7-2.7V7.2c0-1.1-.6-2.1-1.7-2.7zm-9.7-2.2c.1-.1.3-.1.4-.1.2 0 .3 0 .4.1L19.8 6 12 9.9 4.2 6l7.4-3.7zm-8 15.4c-.4-.2-.6-.6-.6-.9V7.6l8 4v9.8l-7.4-3.7zm16.8 0L13 21.4v-9.8l8-4v9.2c0 .3-.2.7-.6.9z"/>
</svg>' }
%}
</p>

<p>
{% render '@button', { class: 'mzp-t-icon-start', label: 'Button with Icon',
icon:
'<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 24 24" width="24" height="24" fill="currentColor">
<path d="m21.3 4.5-8-4c-.8-.4-1.8-.4-2.7 0l-8 4C1.6 5.1 1 6.1 1 7.2v9.5c0 1.1.6 2.2 1.7 2.7l8 4c.4.2.9.3 1.3.3s.9-.1 1.3-.3l8-4c1-.5 1.7-1.5 1.7-2.7V7.2c0-1.1-.6-2.1-1.7-2.7zm-9.7-2.2c.1-.1.3-.1.4-.1.2 0 .3 0 .4.1L19.8 6 12 9.9 4.2 6l7.4-3.7zm-8 15.4c-.4-.2-.6-.6-.6-.9V7.6l8 4v9.8l-7.4-3.7zm16.8 0L13 21.4v-9.8l8-4v9.2c0 .3-.2.7-.6.9z"/>
</svg>' }
%}
</p>

<p>
{% render '@button', { class: 'mzp-t-xl mzp-t-product mzp-t-icon-end', label: 'Download Firefox', link: 'https://www.mozilla.org/firefox/new/',
icon:
'<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
<path d="M8 13c.2 0 .4-.1.5-.2l4.4-4.4-1.1-1.1-3.1 3.1V1H7.2v9.4L4.1 7.3l-1 1.1 4.4 4.4c.1.1.3.2.5.2z"/>
<path d="M13.5 12v2c0 .3-.2.5-.5.5H3c-.3 0-.5-.2-.5-.5v-2H1v2c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2v-2h-1.5z"/>
</svg>' }
%}
</p>

<p>
{% render '@button', { class: 'mzp-t-product mzp-t-secondary mzp-t-icon-start', label: 'Try Reader Mode',
icon:
'<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
<path d="M12 15H4c-1.1 0-2-.9-2-2V2c0-1.1.9-2 2-2h8c1.1 0 2 .9 2 2v11c0 1.1-.9 2-2 2zM4 1.5c-.3 0-.5.2-.5.5v11c0 .3.2.5.5.5h8c.3 0 .5-.2.5-.5V2c0-.3-.2-.5-.5-.5H4z"/>
<path d="M5.5 3.5h5V5h-5z"/>
<path d="M5.5 6.5h5V8h-5z"/>
<path d="M5.5 9.5h3V11h-3z"/>
</svg>' }
%}
</p>

<p>
{% render '@button', { class: 'mzp-t-sm mzp-t-secondary mzp-t-icon-start', label: 'Previous', link: '#',
icon:
'<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
<path d="m1.2 7.7 5.5-5.5 1.1 1.1-4.2 4.2H15V9H3.6l4.2 4.2-1.1 1.1-5.5-5.5c-.1-.2-.2-.4-.2-.6s.1-.3.2-.5z"/>
</svg>' }
%}

{% render '@button', { class: 'mzp-t-sm mzp-t-secondary mzp-t-icon-end', label: 'Next', link: '#',
icon:
'<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
<path d="M14.8 7.7 9.3 2.2 8.2 3.3l4.2 4.2H1V9h11.4l-4.2 4.2 1.1 1.1 5.5-5.5c.1-.2.2-.4.2-.6s-.1-.3-.2-.5z"/>
</svg>' }
%}
</p>
44 changes: 44 additions & 0 deletions components/button/button--with-icon.readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
You can add an icon to a button by including the theme class `mzp-t-icon-start`
to position the icon before the text label, or `mzp-t-icon-end` to position it
after the text label.

The icon itself is enclosed in a `span` with the class `mzp-c-button-icon`.
It should precede the label text when using `mzp-t-icon-start` and follow the label
text when using `mzp-t-icon-end`. Think of it almost like a character of text.

### 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 inline SVG over an external `img` (whether SVG or other format). Inline
SVG can more easily change color for the different button states and style
variants.

- 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 actually a good example.
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.


20 changes: 10 additions & 10 deletions components/button/button.config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: |
Expand Down
30 changes: 27 additions & 3 deletions components/button/button.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,32 @@
# type - type attribute value (button, submit, reset)
# disabled - Boolean
#}
{%- if href -%}
<a class="mzp-c-button{% if class %} {{ class }}{% endif %}" href="{{ link }}">{{ label }}</a>
{%- if link -%}
<a class="mzp-c-button{% if class %} {{ class }}{% endif %}" href="{{ link }}">
{%- if icon and class and "mzp-t-icon-start" in class %}
<span class="mzp-c-button-icon">
{{ icon | safe }}
</span>
{% endif -%}
{{ label }}
{%- if icon and class and "mzp-t-icon-end" in class %}
<span class="mzp-c-button-icon">
{{ icon | safe }}
</span>
{% endif -%}
</a>
{%- else -%}
<button class="mzp-c-button{% if class %} {{ class }}{% endif %}" type="{% if type %}{{ type }}{% else %}button{% endif %}"{{ " disabled" if disabled }}>{{ label }}</button>
<button class="mzp-c-button{% if class %} {{ class }}{% endif %}" type="{% if type %}{{ type }}{% else %}button{% endif %}"{{ " disabled" if disabled }}>
{%- if icon and class and "mzp-t-icon-start" in class %}
<span class="mzp-c-button-icon">
{{ icon | safe }}
</span>
{% endif -%}
{{ label }}
{%- if icon and class and "mzp-t-icon-end" in class %}
<span class="mzp-c-button-icon">
{{ icon | safe }}
</span>
{% endif -%}
</button>
{%- endif -%}

0 comments on commit d8b0536

Please sign in to comment.