Skip to content

Commit

Permalink
Add optional icon to buttons [fix #893]
Browse files Browse the repository at this point in the history
  • Loading branch information
craigcook committed Mar 28, 2024
1 parent a4328a2 commit 285f90a
Show file tree
Hide file tree
Showing 6 changed files with 164 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
25 changes: 25 additions & 0 deletions assets/sass/protocol/components/_button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,28 @@ a.mzp-c-button {
text-decoration: underline;
}
}

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

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

img,
svg {
height: 100%;
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),));
}
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', { label: 'Button with Icon',
iconEnd:
'<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', { label: 'Button with Icon',
iconStart:
'<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', label: 'Download Firefox', link: 'https://www.mozilla.org/firefox/new/',
iconEnd:
'<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', label: 'Try Reader Mode',
iconStart:
'<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', label: 'Previous', link: '#',
iconStart:
'<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', label: 'Next', link: '#',
iconEnd:
'<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>
40 changes: 40 additions & 0 deletions components/button/button--with-icon.readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
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.

### 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.

- 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.


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
32 changes: 29 additions & 3 deletions components/button/button.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,35 @@
# link - URL
# type - type attribute value (button, submit, reset)
# disabled - Boolean
# iconStart - markup
# iconEnd - markup
#}
{%- 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 iconStart %}
<span class="mzp-c-button-icon-start">
{{ iconStart | safe }}
</span>
{% endif -%}
{{ label }}
{%- if iconEnd %}
<span class="mzp-c-button-icon-end">
{{ iconEnd | 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 iconStart %}
<span class="mzp-c-button-icon-start">
{{ iconStart | safe }}
</span>
{% endif -%}
{{ label }}
{%- if iconEnd %}
<span class="mzp-c-button-icon-end">
{{ iconEnd | safe }}
</span>
{% endif -%}
</button>
{%- endif -%}

0 comments on commit 285f90a

Please sign in to comment.