refactor: 💡 add right-align and icon options to dropdowns
This commit is contained in:
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"/>
|
||||
|
||||
Reference in new issue
Block a user