diff --git a/addons/rose/addon/components/rose/dropdown.js b/addons/rose/addon/components/rose/dropdown.js index 4e6ffea81..8ae6f56e6 100644 --- a/addons/rose/addon/components/rose/dropdown.js +++ b/addons/rose/addon/components/rose/dropdown.js @@ -2,6 +2,9 @@ import Component from '@ember/component'; import layout from '../../templates/components/rose/dropdown'; import { action } from '@ember/object'; +/** + * A dropdown component composed of HTML disclosure elements: details and summary + */ export default Component.extend({ // =attributes @@ -13,7 +16,7 @@ export default Component.extend({ /** * Closes the details element by setting its `open` attribute to `false`. * While the details element handles open/close functionality when clicking - * directly on the summar elemenet without JavaScript, we include this helper + * directly on the summary element without JavaScript, we include this helper * action to ensure that when the user clicks _outside_ of the element, * or _inside_ the content, it still closes. * @param {HTMLElement} element diff --git a/addons/rose/addon/components/rose/dropdown.stories.mdx b/addons/rose/addon/components/rose/dropdown.stories.mdx index 87c50f1f1..c2f71d82f 100644 --- a/addons/rose/addon/components/rose/dropdown.stories.mdx +++ b/addons/rose/addon/components/rose/dropdown.stories.mdx @@ -1,7 +1,5 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; import { hbs } from 'ember-cli-htmlbars'; -import { action } from '@storybook/addon-actions'; -import { text, boolean, select } from '@storybook/addon-knobs'; @@ -15,10 +13,10 @@ A simple dropdown component with support for links and buttons. Menu item Menu item + Button menu item `, - context: {} }} @@ -28,10 +26,10 @@ A simple dropdown component with support for links and buttons. Menu item Menu item + Button menu item `, - context: {} }} @@ -43,3 +41,23 @@ A simple dropdown component with support for links and buttons. Button menu item ``` + +Dropdown content can be aligned to right edge of the component instead of the default left edge, which is the default setting. The following example floats the component to right edge of the page inorder to provide enough space to display right aligned dropdown content. + +```htmlbars + + Menu item + Menu item + + Button menu item + +``` + +Dropdown supports `danger` styling through `style` attribute. + +```htmlbars + + Link - danger + Button - danger + +``` diff --git a/addons/rose/addon/components/rose/dropdown/button.js b/addons/rose/addon/components/rose/dropdown/button.js new file mode 100644 index 000000000..6f776e15d --- /dev/null +++ b/addons/rose/addon/components/rose/dropdown/button.js @@ -0,0 +1,10 @@ +import Component from '@ember/component'; +import layout from '../../../templates/components/rose/dropdown/button'; + +/** + * A dropdown button component based on simplified rose/button + */ +export default Component.extend({ + layout, + tagName: '', +}); diff --git a/addons/rose/addon/components/rose/dropdown/link.js b/addons/rose/addon/components/rose/dropdown/link.js new file mode 100644 index 000000000..c6609fe05 --- /dev/null +++ b/addons/rose/addon/components/rose/dropdown/link.js @@ -0,0 +1,10 @@ +import Component from '@ember/component'; +import layout from '../../../templates/components/rose/dropdown/link'; + +/** + * A dropdown link wrapper for LinkTo component. + */ +export default Component.extend({ + layout, + tagName: '', +}); diff --git a/addons/rose/addon/components/rose/header/dropdown.js b/addons/rose/addon/components/rose/header/dropdown.js deleted file mode 100644 index 4a5897084..000000000 --- a/addons/rose/addon/components/rose/header/dropdown.js +++ /dev/null @@ -1,16 +0,0 @@ -import Component from '@ember/component'; -import layout from '../../../templates/components/rose/header/dropdown'; -import { action } from '@ember/object'; - -export default Component.extend({ - layout, - tagName: '', - - // Uses details widget state to close dropdown - @action - close(element) { - if (element.open) { - element.open = false; - } - }, -}); diff --git a/addons/rose/addon/styles/rose/components/dropdown/_button.scss b/addons/rose/addon/styles/rose/components/dropdown/_button.scss new file mode 100644 index 000000000..58b78e4a1 --- /dev/null +++ b/addons/rose/addon/styles/rose/components/dropdown/_button.scss @@ -0,0 +1,36 @@ +@use '../../variables/sizing'; +@use '../../utilities/type'; + +.rose-dropdown-button { + @include type.type(s); + display: block; + box-sizing: border-box; + width: 100%; + // Targeting min-width of ~200 + min-width: (sizing.rems(m) + sizing.rems(xs)) * 10; + border: 0; + padding: 0 sizing.rems(s); + text-decoration: none; + text-align: left; + $line-height: 36 / 14; + line-height: $line-height; + + --background-color: transparent; + --color: var(--stark); + color: var(--color); + background-color: var(--background-color); + + &:hover { + --background-color: var(--ui-gray-subtler-5); + } + + &.rose-dropdown-button-danger { + --background-color: var(--white); + --color: var(--failure); + + &:hover { + --color: var(--white); + --background-color: var(--failure); + } + } +} diff --git a/addons/rose/addon/styles/rose/components/_dropdown.scss b/addons/rose/addon/styles/rose/components/dropdown/_dropdown.scss similarity index 54% rename from addons/rose/addon/styles/rose/components/_dropdown.scss rename to addons/rose/addon/styles/rose/components/dropdown/_dropdown.scss index bd87f3acb..34b2753b0 100644 --- a/addons/rose/addon/styles/rose/components/_dropdown.scss +++ b/addons/rose/addon/styles/rose/components/dropdown/_dropdown.scss @@ -1,6 +1,9 @@ -@use '../variables/sizing'; -@use '../utilities/type'; -@use '../utilities/dropdown'; +@use '../../variables/sizing'; +@use '../../utilities/type'; + +$xs: sizing.rems(xs); // 8 +$xxs: sizing.rems(xxs); // 4 +$chevron: "data:image/svg+xml;utf-8,"; .rose-dropdown { position: relative; @@ -12,18 +15,27 @@ overflow: hidden; display: flex; align-items: center; - margin-right: sizing.rems(s); - padding: 0 sizing.rems(xl) 0 sizing.rems(l); - $lineHeight: 36 / 13; - line-height: $lineHeight; + $yPadding: sizing.rems(xxs) + sizing.rems(xxxs); + padding: $yPadding sizing.rems(xl) $yPadding sizing.rems(l); + color: var(--black); + background: url($chevron) no-repeat right sizing.rems(m) center; + border-radius: sizing.rems(xxxs); + + // Hide default twistie triangle + // Webkit / Chromium + &::-webkit-details-marker { + display: none; + } + // Firefox + list-style-type: none; + &::marker { + display: none; + } - //color: var(--subtle); - background: url("data:image/svg+xml;utf-8,") - no-repeat right sizing.rems(s) center; background-size: sizing.rems(m); &:hover { - background-color: var(--ui-gray-subtler-5); + background-color: var(--ui-gray-subtler-4); } &:not(.has-icon-only) .rose-icon:first-child { @@ -58,14 +70,11 @@ } } - .rose-dropdown-trigger:active, &[open] > .rose-dropdown-trigger { background-color: var(--ui-gray-subtler-4); } .rose-dropdown-content { - $xs: sizing.rems(xs); // 8 - $xxs: sizing.rems(xxs); // 4 position: absolute; padding: $xxs 0; border: 1px solid var(--ui-gray-subtler-2); @@ -76,36 +85,16 @@ z-index: 99; } - &.dropdown-right { + &.rose-dropdown-right { .rose-dropdown-content { right: 0; } } - .rose-dropdown-link, - .rose-button-dropdown { - @include type.type(m, normal); - display: block; - // Targeting min-width of 200 - min-width: (sizing.rems(m) + sizing.rems(xxs)) * 10; - padding: 0 sizing.rems(s); - margin: 0; - border: 0; - color: var(--stark); - background-color: transparent; - // target line height is 36, which is not a standard line height for this - // font size - $lineHeight: 36 / 16; - line-height: $lineHeight; - text-align: left; - text-decoration: none; - - &:hover { - background-color: var(--ui-gray-subtler-4); - } - } - - .rose-button-dropdown { - width: 100%; + .rose-dropdown-separator { + background-color: var(--ui-gray-subtler-3); + height: sizing.rems(xxxxs); + border: none; + margin: $xxs 0; } } diff --git a/addons/rose/addon/styles/rose/components/dropdown/_index.scss b/addons/rose/addon/styles/rose/components/dropdown/_index.scss new file mode 100644 index 000000000..665c33f0f --- /dev/null +++ b/addons/rose/addon/styles/rose/components/dropdown/_index.scss @@ -0,0 +1,3 @@ +@import 'dropdown'; +@import 'button'; +@import 'link'; \ No newline at end of file diff --git a/addons/rose/addon/styles/rose/components/dropdown/_link.scss b/addons/rose/addon/styles/rose/components/dropdown/_link.scss new file mode 100644 index 000000000..38e9d8cb9 --- /dev/null +++ b/addons/rose/addon/styles/rose/components/dropdown/_link.scss @@ -0,0 +1,36 @@ +@use '../../variables/sizing'; +@use '../../utilities/type'; + +.rose-dropdown-link { + @include type.type(s); + display: block; + box-sizing: border-box; + width: 100%; + // Targeting min-width of ~200 + min-width: (sizing.rems(m) + sizing.rems(xs)) * 10; + border: 0; + padding: 0 sizing.rems(s); + text-decoration: none; + text-align: left; + $line-height: 36 / 14; + line-height: $line-height; + + --background-color: transparent; + --color: var(--stark); + color: var(--color); + background-color: var(--background-color); + + &:hover { + --background-color: var(--ui-gray-subtler-5); + } + + &.rose-dropdown-link-danger { + --background-color: var(--white); + --color: var(--failure); + + &:hover { + --color: var(--white); + --background-color: var(--failure); + } + } +} diff --git a/addons/rose/addon/styles/rose/components/header/_dropdown.scss b/addons/rose/addon/styles/rose/components/header/_dropdown.scss index 5436c1b57..8dfe39547 100644 --- a/addons/rose/addon/styles/rose/components/header/_dropdown.scss +++ b/addons/rose/addon/styles/rose/components/header/_dropdown.scss @@ -1,116 +1,42 @@ @use '../../variables/sizing'; @use '../../utilities/type'; -@use '../../utilities/dropdown'; -@include dropdown.dropdown-style( - 'light', - ( - color: var(--white), - chevron: 'light', - ) -); +$chevron: "data:image/svg+xml;utf-8,"; -@include dropdown.dropdown-style( - 'dark', - ( - color: var(--black), - chevron: 'dark', - ) -); +.rose-header { + .rose-dropdown { + &, + &[open] { + .rose-dropdown-trigger { + color: var(--white); + background: url($chevron) no-repeat right sizing.rems(s) center; + background-size: sizing.rems(m); -.rose-header-dropdown { - position: relative; - display: inline-block; + $yPadding: sizing.rems(xxxs); + $rightPadding: sizing.rems(xs) + sizing.rems(l); + padding: $yPadding $rightPadding $yPadding sizing.rems(s); - .rose-header-dropdown-trigger { - cursor: default; - overflow: hidden; - display: flex; - align-items: center; - background-size: sizing.rems(m); - margin-right: sizing.rems(s); - padding-right: sizing.rems(l) - sizing.rems(xxs); - $lineHeight: 48 / 16; - line-height: $lineHeight; + &.has-icon-only { + padding-left: sizing.rems(xs); + } - &.icon-only { - padding-right: sizing.rems(m); + .rose-icon { + --size: #{sizing.rems(l)}; + } - .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; + .rose-icon { + display: inline-block; + height: var(--size); + + > svg { + vertical-align: top; + } + } + + &:hover, &:focus { + background-color: transparent; + } } } - - // Hide default twistie triangle - // Webkit / Chromium - &::-webkit-details-marker { - display: none; - } - // Firefox - list-style-type: none; - &::marker { - display: none; - } - - .rose-icon { - display: inline-block; - height: var(--size); - - > svg { - vertical-align: top; - } - } - } - - .rose-header-dropdown-content { - $xs: sizing.rems(xs); // 8 - $xxs: sizing.rems(xxs); // 4 - position: absolute; - padding: $xxs 0; - border: 1px solid var(--ui-gray-subtler-2); - border-radius: sizing.rems(xxxs); - background: var(--subtle); - box-shadow: 0 $xxs $xxs rgba(var(--stark-components), var(--opacity-3)), - 0 $xxs $xs rgba(var(--stark-components), var(--opacity-4)); - z-index: 99; - } - - &.dropdown-right { - .rose-header-dropdown-content { - right: 0; - } - } - - .rose-header-dropdown-link, - .rose-button-header-dropdown { - @include type.type(m, normal); - display: block; - // Targeting min-width of 200 - min-width: (sizing.rems(m) + sizing.rems(xxs)) * 10; - padding: 0 sizing.rems(s); - margin: 0; - border: 0; - color: var(--stark); - background-color: transparent; - // target line height is 36, which is not a standard line height for this - // font size - $lineHeight: 36 / 16; - line-height: $lineHeight; - text-align: left; - text-decoration: none; - - &:hover { - background-color: var(--ui-gray-subtler-4); - } - } - - .rose-button-header-dropdown { - width: 100%; } } diff --git a/addons/rose/addon/styles/rose/components/header/_nav.scss b/addons/rose/addon/styles/rose/components/header/_nav.scss index 6e50ec714..1eee38086 100644 --- a/addons/rose/addon/styles/rose/components/header/_nav.scss +++ b/addons/rose/addon/styles/rose/components/header/_nav.scss @@ -6,6 +6,7 @@ display: flex; flex-wrap: wrap; align-items: center; + margin-right: sizing.rems(s); @media (max-width: media.width(small)) { padding: 0 20px; diff --git a/addons/rose/addon/styles/rose/components/header/_utilities.scss b/addons/rose/addon/styles/rose/components/header/_utilities.scss index ad28137ff..6632a2597 100644 --- a/addons/rose/addon/styles/rose/components/header/_utilities.scss +++ b/addons/rose/addon/styles/rose/components/header/_utilities.scss @@ -6,4 +6,5 @@ flex-wrap: wrap; flex-direction: row-reverse; align-items: center; + margin-right: sizing.rems(s); } diff --git a/addons/rose/addon/styles/rose/utilities/_dropdown.scss b/addons/rose/addon/styles/rose/utilities/_dropdown.scss deleted file mode 100644 index 059d2d56d..000000000 --- a/addons/rose/addon/styles/rose/utilities/_dropdown.scss +++ /dev/null @@ -1,18 +0,0 @@ -@use 'sass:map'; - -$dropdown-chevron: ( - 'light': - "data:image/svg+xml;utf-8,", - 'dark': - "data:image/svg+xml;utf-8,", -); - -@mixin dropdown-style($name, $default) { - .rose-header-dropdown-#{$name} { - .rose-header-dropdown-trigger { - color: map.get($default, color); - background: url(map.get($dropdown-chevron, map.get($default, chevron))) - no-repeat right center; - } - } -} diff --git a/addons/rose/addon/templates/components/rose/button.hbs b/addons/rose/addon/templates/components/rose/button.hbs index a8ac2acbd..cd87dd8d8 100644 --- a/addons/rose/addon/templates/components/rose/button.hbs +++ b/addons/rose/addon/templates/components/rose/button.hbs @@ -2,7 +2,7 @@ ...attributes type={{if @submit "submit" "button"}} disabled={{if @disabled "disabled"}} - class="{{if @style (concat "rose-button-" @style)}} {{if @iconLeft "has-icon-left"}} {{if @iconRight "has-icon-right"}} {{if @iconOnly "has-icon-only"}}" + class="{{@classNames}} {{if @style (concat "rose-button-" @style)}} {{if @iconLeft "has-icon-left"}} {{if @iconRight "has-icon-right"}} {{if @iconOnly "has-icon-only"}}" > diff --git a/addons/rose/addon/templates/components/rose/dropdown.hbs b/addons/rose/addon/templates/components/rose/dropdown.hbs index c65c640ba..991bdf085 100644 --- a/addons/rose/addon/templates/components/rose/dropdown.hbs +++ b/addons/rose/addon/templates/components/rose/dropdown.hbs @@ -1,11 +1,11 @@
@@ -24,8 +24,9 @@
{{yield (hash - link=(component "link-to" class="rose-dropdown-link") - button=(component "rose/button" style="dropdown") + link=(component "rose/dropdown/link" style=this.style) + button=(component "rose/dropdown/button" style=this.style) + separator=(component "rose/anonymous" tagName="hr" class="rose-dropdown-separator") )}}
diff --git a/addons/rose/addon/templates/components/rose/dropdown/button.hbs b/addons/rose/addon/templates/components/rose/dropdown/button.hbs new file mode 100644 index 000000000..364a2ef18 --- /dev/null +++ b/addons/rose/addon/templates/components/rose/dropdown/button.hbs @@ -0,0 +1,19 @@ + diff --git a/addons/rose/addon/templates/components/rose/dropdown/link.hbs b/addons/rose/addon/templates/components/rose/dropdown/link.hbs new file mode 100644 index 000000000..6b3bd413a --- /dev/null +++ b/addons/rose/addon/templates/components/rose/dropdown/link.hbs @@ -0,0 +1,8 @@ + + {{yield}} + \ No newline at end of file diff --git a/addons/rose/addon/templates/components/rose/header/dropdown.hbs b/addons/rose/addon/templates/components/rose/header/dropdown.hbs deleted file mode 100644 index cc874c284..000000000 --- a/addons/rose/addon/templates/components/rose/header/dropdown.hbs +++ /dev/null @@ -1,32 +0,0 @@ -
- - - - {{#if @icon}} - - {{/if}} - - - {{@text}} - - - - -
- {{yield (hash - link=(component "link-to" class="rose-header-dropdown-link") - button=(component "rose/button" style="header-dropdown") - )}} -
- -
diff --git a/addons/rose/addon/templates/components/rose/header/nav.hbs b/addons/rose/addon/templates/components/rose/header/nav.hbs index 2b2978e00..a0858cc1a 100644 --- a/addons/rose/addon/templates/components/rose/header/nav.hbs +++ b/addons/rose/addon/templates/components/rose/header/nav.hbs @@ -1,6 +1,6 @@ diff --git a/addons/rose/addon/templates/components/rose/header/utilities.hbs b/addons/rose/addon/templates/components/rose/header/utilities.hbs index 6ee49e33f..e00d45e75 100644 --- a/addons/rose/addon/templates/components/rose/header/utilities.hbs +++ b/addons/rose/addon/templates/components/rose/header/utilities.hbs @@ -1,5 +1,5 @@
{{yield (hash - dropdown=(component 'rose/header/dropdown' alignRight=true) + dropdown=(component 'rose/dropdown' dropdownRight=true) )}}
diff --git a/addons/rose/app/components/rose/dropdown/button.js b/addons/rose/app/components/rose/dropdown/button.js new file mode 100644 index 000000000..0def7a1c0 --- /dev/null +++ b/addons/rose/app/components/rose/dropdown/button.js @@ -0,0 +1 @@ +export { default } from 'rose/components/rose/dropdown/button'; \ No newline at end of file diff --git a/addons/rose/app/components/rose/dropdown/link.js b/addons/rose/app/components/rose/dropdown/link.js new file mode 100644 index 000000000..99ec355d3 --- /dev/null +++ b/addons/rose/app/components/rose/dropdown/link.js @@ -0,0 +1 @@ +export { default } from 'rose/components/rose/dropdown/link'; \ No newline at end of file diff --git a/addons/rose/app/components/rose/header/dropdown.js b/addons/rose/app/components/rose/header/dropdown.js deleted file mode 100644 index 16d89ac10..000000000 --- a/addons/rose/app/components/rose/header/dropdown.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'rose/components/rose/header/dropdown'; diff --git a/addons/rose/tests/dummy/app/templates/index.hbs b/addons/rose/tests/dummy/app/templates/index.hbs index 5c6efcf85..529b6c7c5 100644 --- a/addons/rose/tests/dummy/app/templates/index.hbs +++ b/addons/rose/tests/dummy/app/templates/index.hbs @@ -1,23 +1,38 @@ - - - - Address - Host Set - Name - Description - - - - - 1.1.1.1 - host-set-1, host-set-2 - optional name - description - - - - - Footer - - - \ No newline at end of file + + + + + + Menu item + Menu item - danger + + Button menu item + + + Section + Section + + + + + Menu item + Menu item - danger + Button - default + + Button - danger + + + + + + Menu item + Menu item - danger + + + Button menu item + Button - danger + diff --git a/addons/rose/tests/integration/components/rose/dropdown-test.js b/addons/rose/tests/integration/components/rose/dropdown-test.js index 3d4597c95..0c0c22695 100644 --- a/addons/rose/tests/integration/components/rose/dropdown-test.js +++ b/addons/rose/tests/integration/components/rose/dropdown-test.js @@ -9,6 +9,7 @@ module('Integration | Component | rose/dropdown', function (hooks) { test('it renders', async function (assert) { await render(hbs``); assert.ok(find('.rose-dropdown')); + assert.notOk(find('.rose-dropdown-right')); }); test('it renders with html attributes', async function (assert) { @@ -32,6 +33,13 @@ module('Integration | Component | rose/dropdown', function (hooks) { assert.ok(find('.has-icon-only')); }); + test('it supports right aligned content', async function (assert) { + await render(hbs` + + `); + assert.ok(find('.rose-dropdown-right')); + }); + test('it renders with content', async function (assert) { await render(hbs` diff --git a/addons/rose/tests/integration/components/rose/dropdown/button-test.js b/addons/rose/tests/integration/components/rose/dropdown/button-test.js new file mode 100644 index 000000000..11fc945a6 --- /dev/null +++ b/addons/rose/tests/integration/components/rose/dropdown/button-test.js @@ -0,0 +1,38 @@ +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/dropdown/button', function(hooks) { + setupRenderingTest(hooks); + + test('it renders', async function (assert) { + await render(hbs``); + assert.ok(find('.rose-dropdown-button')); + }); + + test('it is type="button" by default', async function (assert) { + await render(hbs``); + assert.equal(find('button').type, 'button'); + }); + + test('it is type="submit" when @submit={{true}}', async function (assert) { + await render(hbs``); + assert.equal(find('button').type, 'submit'); + }); + + test('it is disabled when @disabled={{true}}', async function (assert) { + await render(hbs``); + assert.equal(find('button').disabled, true); + }); + + test('it adds a style class', async function (assert) { + await render(hbs``); + assert.ok(find('.rose-dropdown-button-warning')); + }); + + test('it supports an icon-only type', async function (assert) { + await render(hbs``); + assert.ok(find('.has-icon-only .rose-icon')); + }); +}); diff --git a/addons/rose/tests/integration/components/rose/dropdown/link-test.js b/addons/rose/tests/integration/components/rose/dropdown/link-test.js new file mode 100644 index 000000000..a64b51bf8 --- /dev/null +++ b/addons/rose/tests/integration/components/rose/dropdown/link-test.js @@ -0,0 +1,31 @@ +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/dropdown/link', function(hooks) { + setupRenderingTest(hooks); + + test('it renders', async function (assert) { + await render(hbs``); + assert.ok(find('a')); + assert.ok(find('.rose-dropdown-link')); + }); + + test('it renders with attributes', async function (assert) { + await render(hbs``); + assert.ok(find('#dropdown')); + }); + + test('it renders with content', async function (assert) { + await render(hbs` + content + `); + assert.equal(find('.rose-dropdown-link').textContent.trim(), 'content'); + }); + + test('it supports style', async function (assert) { + await render(hbs``); + assert.ok('.rose-dropdown-link-warning'); + }); +}); diff --git a/addons/rose/tests/integration/components/rose/header-test.js b/addons/rose/tests/integration/components/rose/header-test.js index 7e0f57da7..2feb23438 100644 --- a/addons/rose/tests/integration/components/rose/header-test.js +++ b/addons/rose/tests/integration/components/rose/header-test.js @@ -53,6 +53,6 @@ module('Integration | Component | rose/header', function (hooks) { `); - assert.ok(find('.rose-header-dropdown')); + assert.ok(find('.rose-dropdown')); }); }); diff --git a/addons/rose/tests/integration/components/rose/header/dropdown-test.js b/addons/rose/tests/integration/components/rose/header/dropdown-test.js deleted file mode 100644 index 96806b98b..000000000 --- a/addons/rose/tests/integration/components/rose/header/dropdown-test.js +++ /dev/null @@ -1,80 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, click, find, findAll } from '@ember/test-helpers'; -import hbs from 'htmlbars-inline-precompile'; - -module('Integration | Component | rose/header/dropdown', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - await render(hbs``); - assert.ok(find('.rose-header-dropdown')); - }); - - test('it renders with html attributes', async function (assert) { - await render( - hbs`` - ); - assert.ok(find('#custom-id')); - assert.ok(find('.custom-class')); - }); - - test('it renders with trigger', async function (assert) { - await render(hbs``); - assert.equal( - find('.rose-header-dropdown-trigger').textContent.trim(), - 'Click me' - ); - }); - - test('it supports an icon', async function (assert) { - await render(hbs``); - assert.ok(find('svg')); - }); - - test('it supports icon-only display', async function (assert) { - await render(hbs``); - assert.ok(find('.icon-only')); - }); - - test('it supports right-aligned content', async function (assert) { - await render(hbs``); - assert.ok(find('.dropdown-right')); - }); - - test('it renders with content', async function (assert) { - await render(hbs` - - - - - - `); - assert.ok(find('.rose-header-dropdown-content')); - assert.equal(findAll('a').length, 2); - assert.equal(findAll('button').length, 3); - }); - - test('it is toggled on click on trigger content', async function (assert) { - await render(hbs``); - - assert.notOk(find('#dropdown').open); - await click('summary'); - assert.ok(find('#dropdown').open); - await click('summary'); - assert.notOk(find('#dropdown').open); - }); - - test('it is closed with outside click is triggered', async function (assert) { - await render(hbs` -
- -
- `); - - await click('summary'); - assert.ok(find('#dropdown').open); - await click('#wrapper'); - assert.notOk(find('#dropdown').open); - }); -}); diff --git a/addons/rose/tests/integration/components/rose/header/nav-test.js b/addons/rose/tests/integration/components/rose/header/nav-test.js index d1c5a688d..fd713c0db 100644 --- a/addons/rose/tests/integration/components/rose/header/nav-test.js +++ b/addons/rose/tests/integration/components/rose/header/nav-test.js @@ -24,6 +24,6 @@ module('Integration | Component | rose/header/nav', function (hooks) { `); - assert.equal(findAll('.rose-header-dropdown').length, 2); + assert.equal(findAll('.rose-dropdown').length, 2); }); }); diff --git a/addons/rose/tests/integration/components/rose/header/utilities-test.js b/addons/rose/tests/integration/components/rose/header/utilities-test.js index 884266d8f..1bb44de8e 100644 --- a/addons/rose/tests/integration/components/rose/header/utilities-test.js +++ b/addons/rose/tests/integration/components/rose/header/utilities-test.js @@ -16,6 +16,13 @@ module('Integration | Component | rose/header/utilities', function (hooks) { `); - assert.equal(findAll('.rose-header-dropdown').length, 2); + assert.equal(findAll('.rose-dropdown').length, 2); + }); + + test('it renders nav dropdown elements as right aligned', async function (assert) { + await render(hbs` + + `); + assert.ok(find('.rose-dropdown.rose-dropdown-right')); }); }); diff --git a/ui/core/app/templates/application.hbs b/ui/core/app/templates/application.hbs index 15d146e9a..2422a624e 100644 --- a/ui/core/app/templates/application.hbs +++ b/ui/core/app/templates/application.hbs @@ -14,7 +14,9 @@ @iconOnly={{true}} @icon="user-square-fill" as |dropdown| > - + {{t 'actions.deauthenticate'}} diff --git a/ui/core/app/templates/scopes/scope/groups/group/index.hbs b/ui/core/app/templates/scopes/scope/groups/group/index.hbs index ac8915f59..e78a0c548 100644 --- a/ui/core/app/templates/scopes/scope/groups/group/index.hbs +++ b/ui/core/app/templates/scopes/scope/groups/group/index.hbs @@ -16,20 +16,24 @@ + + + + {{t 'actions.delete-group'}} + + + + - - - {{t 'actions.delete'}} - diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/index.hbs index cb0a4a0cf..6d7c05659 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/index.hbs @@ -16,20 +16,24 @@ + + + + {{t 'actions.delete-host-catalog'}} + + + + - - - {{t 'actions.delete'}} - diff --git a/ui/core/app/templates/scopes/scope/projects/project/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/index.hbs index 5dccae834..c3bec3790 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/index.hbs @@ -16,20 +16,24 @@ + + + + {{t 'actions.delete-project'}} + + + + - - - {{t 'actions.delete'}} - diff --git a/ui/core/app/templates/scopes/scope/roles/role.hbs b/ui/core/app/templates/scopes/scope/roles/role.hbs index 0cd189b0a..397e9f504 100644 --- a/ui/core/app/templates/scopes/scope/roles/role.hbs +++ b/ui/core/app/templates/scopes/scope/roles/role.hbs @@ -10,6 +10,18 @@

{{t "resources.role"}}

+ + + + {{t 'actions.delete-role'}} + + + + diff --git a/ui/core/app/templates/scopes/scope/roles/role/index.hbs b/ui/core/app/templates/scopes/scope/roles/role/index.hbs index bbb671abe..e72610ec6 100644 --- a/ui/core/app/templates/scopes/scope/roles/role/index.hbs +++ b/ui/core/app/templates/scopes/scope/roles/role/index.hbs @@ -3,11 +3,4 @@ @submit={{route-action "save" @model}} @cancel={{route-action "cancel" @model}} /> - - - {{t 'actions.delete'}} - + diff --git a/ui/core/app/templates/scopes/scope/users/user/index.hbs b/ui/core/app/templates/scopes/scope/users/user/index.hbs index d80978336..6392e84f7 100644 --- a/ui/core/app/templates/scopes/scope/users/user/index.hbs +++ b/ui/core/app/templates/scopes/scope/users/user/index.hbs @@ -8,6 +8,18 @@

{{t "resources.user"}}

+ + + + {{t 'actions.delete-user'}} + + + + @@ -17,19 +29,11 @@ - - - - {{t 'actions.delete'}} - diff --git a/ui/core/tests/acceptance/authentication-test.js b/ui/core/tests/acceptance/authentication-test.js index 04107a7a9..fa43f2247 100644 --- a/ui/core/tests/acceptance/authentication-test.js +++ b/ui/core/tests/acceptance/authentication-test.js @@ -1,5 +1,5 @@ import { module, test } from 'qunit'; -import { visit, currentURL, fillIn, click, find } from '@ember/test-helpers'; +import { visit, currentURL, fillIn, click, find, findAll } from '@ember/test-helpers'; import { setupApplicationTest } from 'ember-qunit'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; import { Response } from 'miragejs'; @@ -172,7 +172,11 @@ module('Acceptance | authentication', function (hooks) { await fillIn('[name="password"]', 'test'); await click('[type="submit"]'); assert.ok(currentSession().isAuthenticated); - await click('.rose-button-header-dropdown'); + // Open header utilities dropdown + await click('.rose-header-utilities .rose-dropdown summary'); + // Find and click on last element in dropdown - should be deauthenticate button + const menu = findAll('.rose-header-utilities .rose-dropdown .rose-dropdown-content button'); + await click(menu[menu.length - 1]); assert.notOk(currentSession().isAuthenticated); assert.equal(currentURL(), authMethodGlobalAuthenticateURL); }); diff --git a/ui/core/tests/acceptance/groups-test.js b/ui/core/tests/acceptance/groups-test.js index b619d09ce..0d622f1f0 100644 --- a/ui/core/tests/acceptance/groups-test.js +++ b/ui/core/tests/acceptance/groups-test.js @@ -133,7 +133,7 @@ module('Acceptance | groups', function (hooks) { assert.expect(1); const groupsCount = this.server.db.groups.length; await visit(groupURL); - await click('.rose-button-warning'); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); assert.equal(this.server.db.groups.length, groupsCount - 1); }); @@ -210,7 +210,7 @@ module('Acceptance | groups', function (hooks) { ); }); await visit(groupURL); - await click('.rose-button-warning'); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); assert.ok( find('[role="alert"]').textContent.trim(), 'Oops.', diff --git a/ui/core/tests/acceptance/host-catalogs-test.js b/ui/core/tests/acceptance/host-catalogs-test.js index 59bc08dcc..fada1730e 100644 --- a/ui/core/tests/acceptance/host-catalogs-test.js +++ b/ui/core/tests/acceptance/host-catalogs-test.js @@ -80,7 +80,7 @@ module('Acceptance | host catalogs', function (hooks) { authenticateSession({}); await visit(urls.hostCatalog); assert.equal(currentURL(), urls.hostCatalog); - await click('.rose-button-warning'); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); assert.equal(this.server.db.hostCatalogs.length, hostCatalogsCount - 1); }); @@ -162,7 +162,7 @@ module('Acceptance | host catalogs', function (hooks) { }); authenticateSession({}); await visit(urls.hostCatalog); - await click('.rose-button-warning'); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); await a11yAudit(); assert.ok( find('[role="alert"]').textContent.trim(), diff --git a/ui/core/tests/acceptance/projects-test.js b/ui/core/tests/acceptance/projects-test.js index ced4a8f13..4af813592 100644 --- a/ui/core/tests/acceptance/projects-test.js +++ b/ui/core/tests/acceptance/projects-test.js @@ -135,7 +135,7 @@ module('Acceptance | projects', function (hooks) { test('can delete project', async function (assert) { assert.expect(1); await visit(existingProjectURL); - await click('.rose-button-warning'); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); assert.equal(getProjectScopesCount(), initialProjectScopesCount - 1); }); @@ -212,7 +212,7 @@ module('Acceptance | projects', function (hooks) { ); }); await visit(existingProjectURL); - await click('.rose-button-warning'); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); assert.ok( find('[role="alert"]').textContent.trim(), 'Oops.', diff --git a/ui/core/tests/acceptance/roles-test.js b/ui/core/tests/acceptance/roles-test.js index 2aa364f1b..14bd45a24 100644 --- a/ui/core/tests/acceptance/roles-test.js +++ b/ui/core/tests/acceptance/roles-test.js @@ -133,7 +133,7 @@ module('Acceptance | roles', function (hooks) { assert.expect(1); const rolesCount = this.server.db.roles.length; await visit(roleURL); - await click('.rose-button-warning'); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); assert.equal(this.server.db.roles.length, rolesCount - 1); }); @@ -210,7 +210,7 @@ module('Acceptance | roles', function (hooks) { ); }); await visit(roleURL); - await click('.rose-button-warning'); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); assert.ok( find('[role="alert"]').textContent.trim(), 'Oops.', diff --git a/ui/core/tests/acceptance/users-test.js b/ui/core/tests/acceptance/users-test.js index 31fa5c98e..55e4ac108 100644 --- a/ui/core/tests/acceptance/users-test.js +++ b/ui/core/tests/acceptance/users-test.js @@ -133,7 +133,7 @@ module('Acceptance | users', function (hooks) { assert.expect(1); const usersCount = this.server.db.users.length; await visit(userURL); - await click('.rose-button-warning'); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); assert.equal(this.server.db.users.length, usersCount - 1); }); @@ -210,7 +210,7 @@ module('Acceptance | users', function (hooks) { ); }); await visit(userURL); - await click('.rose-button-warning'); + await click('.rose-layout-page-actions .rose-dropdown-button-danger'); assert.ok( find('[role="alert"]').textContent.trim(), 'Oops.', diff --git a/ui/core/translations/en-us.yaml b/ui/core/translations/en-us.yaml index 7f207f658..cd73f8bbb 100644 --- a/ui/core/translations/en-us.yaml +++ b/ui/core/translations/en-us.yaml @@ -9,6 +9,11 @@ actions: deauthenticate: Deauthenticate choose-org: Choose Scope choose-different-org: Choose a Different Scope + delete-user: Delete user + delete-group: Delete group + delete-role: Delete role + delete-project: Delete project + delete-host-catalog: Delete host catalog auth: titles: no-scopes: No Scopes Available @@ -76,6 +81,7 @@ form: type: Type identification: Username password: Password + manage: Manage grant: Grant principal: Principal errors: