refactor: 💡 add right-align and icon options to dropdowns

This commit is contained in:
Randall Morey committed 2020-05-26 15:58:27 -04:00
1 parent d7b044b2f7
commit de5814699a
10 files changed
+120 -40

No files matched your search

@@ -1,7 +1,7 @@
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
import { hbs } from 'ember-cli-htmlbars';
import { action } from '@storybook/addon-actions';
import { text, boolean } from '@storybook/addon-knobs';
import { text, boolean, select } from '@storybook/addon-knobs';
<Meta title="Rose|Header" component="Header" />
@@ -24,12 +24,14 @@ A header component that allows three distinct sections to be configured: brand,
</header.nav>
<header.utilities as |utilities|>
<utilities.dropdown as |dropdown|>
<dropdown.trigger>Click me</dropdown.trigger>
<dropdown.content as |content|>
<content.link @route="about">link</content.link>
<content.button>button</content.button>
</dropdown.content>
<utilities.dropdown
@text="user@example.net"
@iconOnly={{true}}
@icon="user-square-fill" as |dropdown|
>
<dropdown.link @route="index">Menu item</dropdown.link>
<dropdown.link @route="about">Menu item</dropdown.link>
<dropdown.button>Button menu item</dropdown.button>
</utilities.dropdown>
</header.utilities>
</Rose::Header>
@@ -39,7 +41,7 @@ A header component that allows three distinct sections to be configured: brand,
<Story name="Basic">{{
template: hbs`
<Rose::Header as |header|>
<header.brand @logo="logo" @text="Product Name" />
<header.brand @logo="logo" @text={{brandName}} />
<header.nav as |nav|>
<nav.dropdown @text="org-name" as |dropdown|>
<dropdown.link @route="index">Menu item</dropdown.link>
@@ -50,21 +52,31 @@ A header component that allows three distinct sections to be configured: brand,
<nav.link @route="about">Section</nav.link>
</header.nav>
<header.utilities as |utilities|>
<utilities.dropdown @alignRight={{true}} as |dropdown|>
<dropdown.trigger><Rose::Icon @name="user-square-outline" /></dropdown.trigger>
<dropdown.content as |content|>
<content.link @route="about">link</content.link>
<content.button>button</content.button>
</dropdown.content>
<utilities.dropdown
@text="user@example.net"
@iconOnly={{true}}
@icon={{dropdownIcon}} as |dropdown|
>
<dropdown.link @route="index">Menu item</dropdown.link>
<dropdown.link @route="about">Menu item</dropdown.link>
<dropdown.button>Button menu item</dropdown.button>
</utilities.dropdown>
</header.utilities>
</Rose::Header>
`,
context: {
'nav-dropdown-label': text('nav-dropdown-label', 'org-name'),
'nav-dropdown-link-label': text('nav-dropdown-link-label', 'Menu Item'),
'nav-dropdown-button-label': text('nav-dropdown-button-label', 'Menu Item'),
'nav-link-label': text('nav-link-label', 'Section'),
brandName: text('brandName', 'Brand Name'),
dropdownIcon: select(
'dropdownIcon',
{
'user-square-fill': 'user-square-fill',
'check-circle-outline': 'check-circle-outline',
'copy-action': 'copy-action',
'unfold-more': 'unfold-more',
'unfold-less': 'unfold-less',
},
'user-square-fill'
),
},
}}</Story>
</Preview>
@@ -12,7 +12,6 @@
.rose-header-nav,
.rose-header-utilities {
.rose-header-dropdown {
.rose-header-dropdown-content {
position: absolute;
background-color: var(--white);
@@ -24,7 +23,6 @@
&.rose-header-dropdown-content-right {
right: sizing.rems(s);
}
}
}
}
@@ -12,10 +12,30 @@ $dropdown-chevron: (
.rose-header-dropdown-trigger {
cursor: default;
overflow: hidden;
display: flex;
align-items: center;
color: var(--white);
background: url(map.get($dropdown-chevron, default)) no-repeat right center;
background-size: sizing.rems(m);
margin-right: sizing.rems(s);
padding-right: sizing.rems(l);
padding-right: sizing.rems(l) - sizing.rems(xxs);
$lineHeight: 48 / 16;
line-height: $lineHeight;
&.icon-only {
padding-right: sizing.rems(m);
.rose-header-dropdown-trigger-text {
// TODO: factor out into visually-hidden mixin utility
position: absolute;
left: -1000px;
top: -1000px;
width: 1px;
height: 1px;
opacity: 0;
}
}
// Hide default twistie triangle
// Webkit / Chromium
@@ -27,6 +47,15 @@ $dropdown-chevron: (
&::marker {
display: none;
}
.rose-icon {
display: inline-block;
height: var(--size);
> svg {
vertical-align: top;
}
}
}
.rose-header-dropdown-content {
@@ -4,6 +4,7 @@
@import 'brand';
@import 'nav';
@import 'utilities';
@import 'link';
@import 'dropdown';
@@ -0,0 +1,9 @@
@use '../../variables/sizing';
.rose-header-utilities {
grid-area: utilities;
display: flex;
flex-wrap: wrap;
flex-direction: row-reverse;
align-items: center;
}
@@ -1,5 +1,7 @@
<header ...attributes
class="rose-header" >
<header
...attributes
class="rose-header"
>
{{yield (hash
brand=(component 'rose/header/brand')
utilities=(component 'rose/header/utilities')
@@ -4,8 +4,22 @@
{{on-click-outside this.close}}
>
<summary class="rose-header-dropdown-trigger">
{{@text}}
<summary
class="rose-header-dropdown-trigger{{if @iconOnly " icon-only"}}"
title={{@text}}
>
{{#if @icon}}
<Rose::Icon
@name={{@icon}}
@size="large"
/>
{{/if}}
<span class="rose-header-dropdown-trigger-text">
{{@text}}
</span>
</summary>
<div class="rose-header-dropdown-content">
@@ -1,7 +1,5 @@
<span class="rose-header-utilities">
<span class="rose-header-utilities-flex">
{{yield (hash
dropdown=(component 'rose/header/dropdown' position="true")
)}}
</span>
</span>
<div class="rose-header-utilities">
{{yield (hash
dropdown=(component 'rose/header/dropdown' alignRight=true)
)}}
</div>
@@ -12,17 +12,19 @@
<nav.link @route="about">Section</nav.link>
</header.nav>
{{!--
<header.utilities as |utilities|>
<utilities.dropdown @alignRight={{true}} as |dropdown|>
<dropdown.trigger><Rose::Icon @name="user-square-outline" /></dropdown.trigger>
<dropdown.content as |content|>
<content.link @route="about">link</content.link>
<content.button>button</content.button>
</dropdown.content>
<utilities.dropdown
@text="user@example.net"
@iconOnly={{true}}
@icon="user-square-fill" as |dropdown|
>
<dropdown.link @route="index">Menu item</dropdown.link>
<dropdown.link @route="about">Menu item</dropdown.link>
<dropdown.button>Button menu item</dropdown.button>
</utilities.dropdown>
</header.utilities>
--}}
</Rose::Header>
@@ -27,6 +27,21 @@ module('Integration | Component | rose/header/dropdown', function (hooks) {
);
});
test('it supports an icon', async function (assert) {
await render(hbs`<Rose::Header::Dropdown @icon="user-square-fill" />`);
assert.ok(find('svg'));
});
test('it supports icon-only display', async function (assert) {
await render(hbs`<Rose::Header::Dropdown @iconOnly={{true}} />`);
assert.ok(find('.icon-only'));
});
test('it supports right-aligned content', async function (assert) {
await render(hbs`<Rose::Header::Dropdown @alignRight={{true}} />`);
assert.ok(find('.dropdown-right'));
});
test('it renders with content', async function (assert) {
await render(hbs`<Rose::Header::Dropdown @text="Click me" as |dropdown|>
<dropdown.link @route="about"/>