Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Toggle Button component (resolves #336) #338

Merged
merged 4 commits into from
May 13, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/assets/scripts/Pinecone/ToggleButton/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Toggle Button class.
*/
class ToggleButton {
/**
* Constructor.
*
* @param {Object} options
*/
constructor( options ) {
this.config = {
...{
selector: '.button--toggle'
},
...options
};

this.handleClick = this.handleClick.bind( this );
this.addEventListeners();
}

/**
* Handle click.
*
* @param {Event} event
*/
handleClick( event ) {
if ( ! event.target.closest( this.config.selector ) ) return;

const btn = event.target.closest( this.config.selector );
const pressedSiblings = btn.parentNode.querySelectorAll( '[aria-pressed="true"]' );
const pressed = 'true' === btn.getAttribute( 'aria-pressed' ) || false;
if ( 0 < pressedSiblings.length && !pressed ) {
Array.prototype.forEach.call( pressedSiblings, pressedBtn => {
pressedBtn.setAttribute( 'aria-pressed', false );
} );
}
btn.setAttribute( 'aria-pressed', !pressed );
}

/**
* Add event listeners.
*/
addEventListeners() {
document.addEventListener( 'click', this.handleClick );
}
}

export default ToggleButton;
4 changes: 3 additions & 1 deletion src/assets/scripts/Pinecone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ import MenuButton from './MenuButton/index.js';
import NestedCheckbox from './NestedCheckbox/index.js';
import Notification from './Notification/index.js';
import SearchToggle from './SearchToggle/index.js';
import ToggleButton from './ToggleButton/index.js';

export default { Accordion, Card, DeselectAll, Dialog, DisclosureButton, FilterList, Icon, Menu, MenuButton, NestedCheckbox, Notification, SearchToggle, ToggleButton };

export default { Accordion, Card, DeselectAll, Dialog, DisclosureButton, FilterList, Icon, Menu, MenuButton, NestedCheckbox, Notification, SearchToggle };
2 changes: 2 additions & 0 deletions src/assets/scripts/pinecone.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,5 @@ const searchToggle = document.querySelector( '.search-toggle' );
if ( searchToggle ) {
new Pinecone.SearchToggle( searchToggle, searchToggle.nextElementSibling );
}

new Pinecone.ToggleButton();
63 changes: 63 additions & 0 deletions src/assets/styles/components/_button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,69 @@ button:-moz-focusring {
}
}

.button--toggle {
border-radius: rem(5);
font-weight: $font-weight-normal;
margin: rem(8) rem(9);
min-height: rem(32);
padding: 0 rem(10);
width: auto;
}

.button--toggle.button--inverse {
--color: var(--off-white);
--background-color: var(--blue-500);
--border-color: var(--off-white);

--active-background-color: var(--off-white);
--active-color: var(--blue-500);
--active-box-shadow: 0 0 0 calc(2 * var(--border-width)) var(--parent-background-color), 0 0 0 calc(4 * var(--border-width)) var(--focus-border-color);

--focus-background-color: var(--blue-500);
--focus-border-color: var(--color);
--focus-color: inherit;
--focus-box-shadow: 0 0 0 calc(1 * var(--border-width)) var(--focus-border-color) inset, 0 0 0 calc(2 * var(--border-width)) var(--parent-background-color), 0 0 0 calc(4 * var(--border-width)) var(--focus-border-color);

--hover-background-color: var(--blue-600);

&:active {
border-color: transparent;
}

&:focus {
border-color: var(--focus-border-color);
}

&[aria-pressed="true"] {
--color: var(--blue-700);
--background-color: var(--blue-50);
--border-color: var(--background-color);

--focus-background-color: var(--background-color);
--focus-border-color: var(--background-color);
--focus-color: inherit;
--focus-box-shadow: 0 0 0 calc(2 * var(--border-width)) var(--parent-background-color), 0 0 0 calc(4 * var(--border-width)) var(--focus-border-color);

--hover-background-color: var(--blue-150);
--hover-border-color: var(--blue-150);

&:hover {
border-color: var(--hover-border-color);
}

&:active {
border-color: transparent;
}
}
}

.toggle-group {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-left: rem(-9);
}

.button[disabled] {
background-color: var(--disabled-background-color);
color: var(--disabled-color);
Expand Down
4 changes: 4 additions & 0 deletions src/assets/styles/mandelbrot.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@ a:hover {
.Pen-previewLink svg {
fill: var(--blue-400);
}

.Prose a:hover {
color: var(--blue-400);
}
7 changes: 7 additions & 0 deletions src/components/atoms/button/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Toggle Button

The Toggle Button is a button with an `aria-pressed` attribute representing a boolean (true or false) value. To use a toggle button, the following JavaScript must be executed on the page where the component is used:

```javascript
new PineCone.ToggleButton();
```
25 changes: 25 additions & 0 deletions src/components/atoms/button/button.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,31 @@ module.exports = {
icon: 'close',
iconPosition: 'end',
}
},
{
name: 'Toggle Button',
label: 'Toggle Button',
context: {
id: false,
label: 'Toggle',
modifiers: ['toggle'],
ariaPressed: true,
pressed: false,
icon: false
}
},
{
name: 'Toggle Button Inverse',
label: 'Toggle Button (Inverse)',
context: {
id: false,
label: 'Toggle',
modifiers: ['toggle', 'inverse'],
ariaPressed: true,
pressed: false,
bodyClass: 'has-dark-mint-500-background-color',
icon: false
}
}
]
};
2 changes: 1 addition & 1 deletion src/components/atoms/button/button.njk
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% if not standAlone %}<div class="spacer"></div>{% endif %}
<button {% if id %}id="{{ id }}" {% endif %}type="{{ type }}" class="button{% if modifiers %}{% for modifier in modifiers %} button--{{ modifier }}{% endfor %}{% endif %}{% if className %} {{ className }}{% endif %}">
<button {% if id %}id="{{ id }}" {% endif %}type="{{ type }}" {% if ariaPressed %}aria-pressed="{{ pressed }}" {% endif %}class="button{% if modifiers %}{% for modifier in modifiers %} button--{{ modifier }}{% endfor %}{% endif %}{% if className %} {{ className }}{% endif %}">
{% if icon and iconPosition === 'start' %}{% render '@svg', {svg:icon}, true %}{% endif %}<span class="button__label{{ ' screen-reader-text' if labelVisuallyHidden }}">{{ label | safe }}</span>{% if icon and iconPosition === 'end' %}{% render '@svg', {svg:icon}, true %}{% endif %}
</button>
5 changes: 5 additions & 0 deletions src/components/molecules/toggle-button-group/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Toggle Button Group

The Toggle Button Group displays a group of related [Toggle Buttons](/components/detail/button--toggle-button/) using flexbox. The parent element must have a class of `.toggle-group` and the buttons must be the direct descendants of the parent element.

When a group of related Toggle Buttons are siblings (children of the same parent element), toggling the `pressed` state of one Toggle Button to `true` will set the `pressed` state of all the other buttons to `false`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module.exports = {
title: 'Toggle Button Group',
status: 'wip',
order: 16,
context: {
label: 'Niches',
buttons: [
'Collaboration',
'Communication',
'Customer or member relations',
'Decision making',
'Developer tools',
'Finance',
'Marketing',
'Time management'
],
buttonVariant: 'toggle-button'
},
variants: [
{
name: 'Inverse',
label: 'Inverse',
context: {
modifier: 'inverse',
bodyClass: 'has-blue-500-background-color',
buttonVariant: 'toggle-button-inverse'
}
}
]
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div class="niches toggle-group">
{% render '@button--' + buttonVariant, {standAlone: true, label: 'All', pressed: true}, true %}
{% for button in buttons %}
{% render '@button--' + buttonVariant, {standAlone: true, label: button}, true %}
{% endfor %}
</div>