style: 💄 add button component with styles, tests, and story

This commit is contained in:
Randall Morey committed 2020-04-28 11:46:05 -04:00
1 parent 883809ba63
commit af47c2457a
12 files changed
+242 -23

No files matched your search

@@ -0,0 +1,13 @@
import Component from '@ember/component';
import layout from '../../templates/components/rose/button';
/**
* A simple HTML `<button>` element.
*
* @example
* <Rose::Button @submit={{true}} @style="primary">Save</Rose::Button>
* <Rose::Button @disabled={{true}} @style="secondary">Disabled</Rose::Button>
*/
export default Component.extend({
layout,
});
+1 -4
View File
@@ -1,6 +1,3 @@
@import 'reset';
@import 'variables';
html {
background: pink;
}
@import 'components';
@@ -0,0 +1,56 @@
@use '../utilities/button';
@include button.button-style(
'primary',
(
color: var(--white),
background-color: var(--info),
border-color: var(--info-starker-2),
box-shadow: 0px 4px 4px rgba(var(--stark-components), var(--opacity-2)),
text-shadow: 0px 1px 1px rgba(var(--black-components), var(--opacity-2)),
),
(
background-color: var(--info-subtler-1),
box-shadow: (
0px 4px 4px rgba(var(--stark-components), var(--opacity-3)),
0px 4px 8px rgba(var(--stark-components), var(--opacity-4)),
),
),
(
background-color: var(--info-starker-1),
box-shadow: none,
),
(
opacity: var(--opacity-1),
box-shadow: none,
)
);
@include button.button-style(
'secondary',
(
color: var(--ui-gray-starker-3),
background-color: var(--ui-gray-subtler-5),
border-color: var(--ui-gray-subtler-2),
box-shadow: 0px 4px 4px rgba(var(--stark-components), var(--opacity-2)),
),
(
color: var(--ui-gray-starker-4),
background-color: var(--subtle),
border-color: var(--ui-gray-starker-1),
box-shadow: (
0px 4px 4px rgba(var(--stark-components), var(--opacity-3)),
0px 4px 8px rgba(var(--stark-components), var(--opacity-4)),
),
),
(
color: var(--ui-gray-starker-4),
background-color: var(--ui-gray-subtler-3),
border-color: var(--ui-gray-starker-1),
box-shadow: none,
),
(
opacity: var(--opacity-1),
box-shadow: none,
)
);
@@ -0,0 +1 @@
@import 'button';
@@ -0,0 +1,80 @@
@use 'sass:map';
@mixin button {
display: flex;
flex-direction: row;
padding: 5px 24px;
line-height: 1.846; // targeting 24px
border-radius: 2px;
border: 1px solid;
font-size: 0.8125rem;
font-weight: 600;
}
@mixin button-style($name, $default, $hover: &, $active: &, $disabled: &) {
.rose-button-#{$name} {
@include button;
border-color: map.get($default, border-color);
color: map.get($default, color);
background-color: map.get($default, background-color);
@if map.get($default, 'box-shadow') {
box-shadow: map.get($default, 'box-shadow');
}
@if map.get($default, 'text-shadow') {
text-shadow: map.get($default, 'text-shadow');
}
&:not(:disabled) {
@if $hover {
&:hover {
@if map.get($hover, 'border-color') {
border-color: map.get($hover, 'border-color');
}
@if map.get($hover, 'color') {
color: map.get($hover, 'color');
}
@if map.get($hover, 'background-color') {
background-color: map.get($hover, 'background-color');
}
@if map.get($hover, 'box-shadow') {
box-shadow: map.get($hover, 'box-shadow');
}
@if map.get($hover, 'text-shadow') {
text-shadow: map.get($hover, 'text-shadow');
}
}
}
@if $active {
&:active {
@if map.get($active, 'border-color') {
border-color: map.get($active, 'border-color');
}
@if map.get($active, 'color') {
color: map.get($active, 'color');
}
@if map.get($active, 'background-color') {
background-color: map.get($active, 'background-color');
}
@if map.get($active, 'box-shadow') {
box-shadow: map.get($active, 'box-shadow');
}
@if map.get($active, 'text-shadow') {
text-shadow: map.get($active, 'text-shadow');
}
}
}
}
@if $disabled {
&:disabled {
cursor: not-allowed;
@if map.get($disabled, 'opacity') {
opacity: map.get($disabled, 'opacity');
}
@if map.get($disabled, 'box-shadow') {
box-shadow: map.get($disabled, 'box-shadow');
}
}
}
}
}
@@ -0,0 +1 @@
@forward 'button';
@@ -0,0 +1,8 @@
<button
...attributes
type={{if @submit "submit" "button"}}
disabled={{if @disabled "disabled"}}
class={{if @style (concat "rose-button-" @style)}}
>
{{yield}}
</button>
@@ -0,0 +1 @@
export { default } from 'rose/components/rose/button';
+10
View File
@@ -1 +1,11 @@
Dummy app index template
<Rose::Button @style="primary">Primary</Rose::Button>
<br>
<Rose::Button @style="primary" @disabled={{true}}>Primary</Rose::Button>
<br>
<Rose::Button @style="secondary">Secondary</Rose::Button>
<br>
<Rose::Button @style="secondary" @disabled={{true}}>Secondary</Rose::Button>
<br>
-19
View File
@@ -1,19 +0,0 @@
import { hbs } from 'ember-cli-htmlbars';
import { action } from '@storybook/addon-actions';
import { text /*withKnobs, boolean, select */ } from '@storybook/addon-knobs';
export default {
title: 'Button',
};
export const Normal = () => ({
template: hbs`
<button {{action onClick}}>
{{text}}
</button>
`,
context: {
text: text('text', 'Button Text'),
onClick: action('clicked'),
},
});
@@ -0,0 +1,36 @@
import { hbs } from 'ember-cli-htmlbars';
import { action } from '@storybook/addon-actions';
import { text, boolean, select } from '@storybook/addon-knobs';
export default {
title: 'Rose::Button',
};
export const Normal = () => ({
template: hbs`
<Rose::Button
@submit={{submit}}
@disabled={{disabled}}
@style={{style}}
{{action onClick}}
>
{{text}}
</Rose::Button>
`,
context: {
text: text('text', 'Button 🌈'),
submit: boolean('submit', false),
disabled: boolean('disabled', false),
style: select(
'style',
{
primary: 'primary',
secondary: 'secondary',
warning: 'warning',
ghost: 'ghost',
},
'primary'
),
onClick: action('clicked'),
},
});
@@ -0,0 +1,35 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, find } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | rose/button', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
await render(hbs`<Rose::Button>Button 🌈</Rose::Button>`);
assert.equal(this.element.textContent.trim(), 'Button 🌈');
});
test('it is type="button" by default', async function (assert) {
await render(hbs`<Rose::Button>Button</Rose::Button>`);
assert.equal(await find('button').type, 'button');
});
test('it is type="submit" when @submit={{true}}', async function (assert) {
await render(hbs`<Rose::Button @submit={{true}} />`);
assert.equal(await find('button').type, 'submit');
});
test('it is disabled when @disabled={{true}}', async function (assert) {
await render(hbs`<Rose::Button @disabled={{true}} />`);
assert.equal(await find('button').disabled, true);
});
test('it adds a style class', async function (assert) {
await render(hbs`<Rose::Button @style="primary" />`);
assert.ok(await find('button.rose-button-primary'));
await render(hbs`<Rose::Button @style="secondary" />`);
assert.ok(await find('button.rose-button-secondary'));
});
});