[Retire] Rose::Dropdown (#2858)

* remove dropdown styling

* remove rose/dropdown child component integration tests

* refactor tests, delete tests

* remove rose dropdown component from addons/

* refactor tests, delete tests

* run yarn format

* remove additional rose dropdown files from addons

* remove ref to rose dropdown from readme

* remove skipped test, comment states no longer relevant

* remove unused ref to rose-header-dropdown selector

* refactor tests using .rose-dropdown selector, cleanup

* run yarn format

* add selector to commonSelectors, refactor more tests

* nest .hds-dropdown selector in place of .rose-dropdown

* revert @use dropdpwn

* remove line, styling already applied on btn selector

* removed unused dropdown-radio-btn selector
This commit is contained in:
Lauren authored and GitHub committed 2025-06-02 14:06:06 -04:00
1 parent 7c3b6d6d9e
commit 5555603a5c
46 files changed
+32 -1138

No files matched your search

-8
View File
@@ -77,14 +77,6 @@ Before submitting your work, be sure to run auto-formatters
To build a new component, start by generating it on the command line with
`ember g component rose/component-name`.
## Using Components
A few of the components have additional ember package dependencies that need to be installed before usage.
| Component | Dependency |
| -------------- | -------------- |
| Rose::Dropdown | ember-modifier |
## Running tests
- `yarn test` – Runs the test suite on the current Ember version
@@ -1,23 +0,0 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: BUSL-1.1
}}
<button
...attributes
type={{if @onSubmit 'submit' 'button'}}
disabled={{if @disabled 'disabled'}}
class='rose-dropdown-button
{{if @style (concat "rose-dropdown-button-" @style)}}
{{if @iconOnly "has-icon-only"}}'
>
<span class='rose-dropdown-button-wrapper'>
<Hds::Text::Body>
{{yield}}
</Hds::Text::Body>
{{#if @iconOnly}}
<Hds::Icon @name={{@iconOnly}} @isInline={{true}} />
{{/if}}
</span>
</button>
@@ -1,68 +0,0 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: BUSL-1.1
}}
<details
...attributes
class='rose-dropdown
{{if @dropdownRight "rose-dropdown-right"}}
{{if @style (concat "rose-dropdown-" @style)}}'
{{on-click-outside this.close}}
>
<summary
class='rose-dropdown-trigger
{{if @iconOnly "has-icon-only"}}
{{if this.showCaret "show-caret"}}'
title={{@text}}
>
{{#if @icon}}
<Hds::Icon @name={{@icon}} @isInline={{true}} />
{{/if}}
<span class='rose-dropdown-trigger-text'>
<Hds::Text::Body @weight='medium'>
{{@text}}
</Hds::Text::Body>
{{#if @count}}
<Hds::BadgeCount @text={{@count}} @size='small' />
{{/if}}
</span>
</summary>
{{#if @ignoreClickInside}}
<div class='rose-dropdown-content'>
{{yield
(hash
link=(component 'rose/dropdown/link' style=this.style)
button=(component 'rose/dropdown/button' style=this.style)
item=(component 'rose/anonymous' class='rose-dropdown-item')
separator=(component
'rose/anonymous' tagName='hr' class='rose-dropdown-separator'
)
section=(component 'rose/dropdown/section' style=this.style)
key-value=(component 'rose/dropdown/key-value')
)
}}
</div>
{{else}}
<div class='rose-dropdown-content' {{on-click-inside this.close}}>
{{yield
(hash
link=(component 'rose/dropdown/link' style=this.style)
button=(component 'rose/dropdown/button' style=this.style)
item=(component 'rose/anonymous' class='rose-dropdown-item')
separator=(component
'rose/anonymous' tagName='hr' class='rose-dropdown-separator'
)
section=(component 'rose/dropdown/section' style=this.style)
key-value=(component 'rose/dropdown/key-value')
)
}}
</div>
{{/if}}
</details>
@@ -1,35 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import Component from '@glimmer/component';
import { computed, action } from '@ember/object';
export default class RoseDropdownComponent extends Component {
// =attributes
/**
* @type {boolean}
*/
@computed('args.showCaret')
get showCaret() {
return this.args.showCaret ?? true;
}
// =actions
/**
* Closes the details element by setting its `open` attribute to `false`.
* While the details element handles open/close functionality when clicking
* 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
*/
@action
close(element) {
if (element.open) element.open = false;
if (element.parentElement.open) element.parentElement.open = false;
}
}
@@ -1,14 +0,0 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: BUSL-1.1
}}
<dl class='rose-dropdown-key-value rose-dropdown-item'>
<dt class='rose-dropdown-key'>
{{yield to='key'}}
</dt>
<dd class='rose-dropdown-value'>
{{yield to='value'}}
</dd>
</dl>
@@ -1,55 +0,0 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: BUSL-1.1
}}
{{!
Ember's LinkTo component won't accept nullish @query or @model, so we have to
overcompensate by duplicating it four times, one for every combination.
This is really unpleasant.
}}
{{#if @model}}
{{#if @query}}
<LinkTo
...attributes
@route={{@route}}
@query={{@query}}
@model={{@model}}
class='rose-dropdown-link
{{if @style (concat "rose-dropdown-link-" @style)}}'
>
{{yield}}
</LinkTo>
{{else}}
<LinkTo
...attributes
@route={{@route}}
@model={{@model}}
class='rose-dropdown-link
{{if @style (concat "rose-dropdown-link-" @style)}}'
>
{{yield}}
</LinkTo>
{{/if}}
{{else}}
{{#if @query}}
<LinkTo
...attributes
@route={{@route}}
@query={{@query}}
class='rose-dropdown-link
{{if @style (concat "rose-dropdown-link-" @style)}}'
>
{{yield}}
</LinkTo>
{{else}}
<LinkTo
...attributes
@route={{@route}}
class='rose-dropdown-link
{{if @style (concat "rose-dropdown-link-" @style)}}'
>
{{yield}}
</LinkTo>
{{/if}}
{{/if}}
@@ -1,24 +0,0 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: BUSL-1.1
}}
<section
class='rose-dropdown-section'
aria-labelledby={{concat 'dropdown-section-title-' this.id}}
>
{{#if @title}}
<Hds::Text::Display
@tag='h2'
id={{concat 'dropdown-section-title-' this.id}}
class='rose-dropdown-section-title'
>
{{#if @icon}}
<Hds::Icon @name={{@icon}} @isInline={{true}} />
{{/if}}
{{@title}}
</Hds::Text::Display>
{{/if}}
{{yield}}
</section>
@@ -1,16 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import Component from '@glimmer/component';
import { generateComponentID } from '../../../../utilities/component-auto-id';
export default class RoseDialogComponent extends Component {
// =attributes
/**
* @type {string}
*/
id = generateComponentID();
}
@@ -4,5 +4,5 @@
}}
<nav class='rose-header-nav' aria-label='header-nav'>
{{yield (hash dropdown=(component 'rose/dropdown'))}}
{{yield}}
</nav>
@@ -4,5 +4,5 @@
}}
<div class='rose-header-utilities'>
{{yield (hash dropdown=(component 'rose/dropdown' dropdownRight=true))}}
{{yield}}
</div>
@@ -1,6 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
export { default } from 'rose/components/rose/dropdown';
@@ -1,6 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
export { default } from 'rose/components/rose/dropdown/button';
@@ -1,6 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
export { default } from 'rose/components/rose/dropdown/key-value';
@@ -1,6 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
export { default } from 'rose/components/rose/dropdown/link';
@@ -1,6 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
export { default } from 'rose/components/rose/dropdown/section';
@@ -8,7 +8,6 @@
@use 'card';
@use 'cards';
@use 'code-editor';
@use 'dropdown';
@use 'form';
@use 'frame';
@use 'header';
@@ -1,45 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@use '../../variables/sizing';
@use '../../utilities/type';
@use 'sass:math';
.rose-dropdown-button {
@include type.type(s);
display: block;
box-sizing: border-box;
width: 100%;
min-width: (sizing.rems(m)) * 13;
border: 0;
padding: 0 sizing.rems(s);
text-decoration: none;
text-align: left;
$line-height: math.div(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(--subtle);
--color: var(--failure);
&:hover {
--color: var(--subtle);
--background-color: var(--failure);
}
}
}
@@ -1,151 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@use '../../variables/sizing';
@use '../../utilities/type';
$xs: sizing.rems(xs); // 8
$xxs: sizing.rems(xxs); // 4
$chevron: url("data:image/svg+xml;utf-8,<svg viewBox='0 0 24 24' fill='%231b1f26' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6-1.41-1.41z'></path></svg>");
$chevron-white: url("data:image/svg+xml;utf-8,<svg viewBox='0 0 24 24' fill='%23ffffff' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6-1.41-1.41z'></path></svg>");
$chevron-grey: url("data:image/svg+xml;utf-8,<svg viewBox='0 0 24 24' fill='%23626873' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6-1.41-1.41z'></path></svg>");
.rose-dropdown {
--background-image-light: #{$chevron};
--background-image-dark: #{$chevron-white};
--background-image: var(--background-image-light);
.ember-application.rose-theme-light & {
--background-image: var(--background-image-light);
}
@media (prefers-color-scheme: dark) {
--background-image: var(--background-image-dark);
}
.ember-application.rose-theme-dark & {
--background-image: var(--background-image-dark);
}
position: relative;
display: inline-block;
vertical-align: middle;
.rose-dropdown-trigger {
@include type.type(button, semibold);
cursor: default;
overflow: hidden;
display: flex;
align-items: center;
$y-padding: sizing.rems(xxs) + sizing.rems(xxxs);
padding: $y-padding sizing.rems(m) $y-padding sizing.rems(l);
color: var(--stark);
border-radius: sizing.rems(xxxs);
white-space: nowrap;
// Hide default twistie triangle
// Webkit / Chromium
&::-webkit-details-marker {
display: none;
}
// Firefox
&::marker {
display: none;
}
background-size: sizing.rems(m);
&:hover {
background-color: var(--ui-gray-subtler-5);
}
&:not(.has-icon-only) .hds-icon:first-child {
margin-left: -(sizing.rems(xs));
margin-right: sizing.rems(xxs);
}
&.has-icon-only {
padding-left: sizing.rems(s);
padding-right: sizing.rems(s);
background-position: right sizing.rems(xs) center;
.rose-dropdown-trigger-text {
position: absolute;
top: -1000px;
left: -1000px;
width: 1px;
height: 1px;
opacity: 0;
}
}
&.show-caret {
padding-right: sizing.rems(xl);
background: var(--background-image);
background-repeat: no-repeat;
background-position: right sizing.rems(m) center;
background-size: sizing.rems(m);
}
// Firefox
list-style-type: none;
}
&[open] > .rose-dropdown-trigger {
background-color: var(--ui-gray-subtler-4);
}
.rose-dropdown-content {
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;
}
&.rose-dropdown-right {
.rose-dropdown-content {
right: 0;
}
}
.rose-dropdown-separator {
background-color: var(--ui-gray-subtler-3);
height: sizing.rems(xxxxs);
border: none;
margin: $xxs 0;
}
// Styles for condensed verion. Some are overrides
&.rose-dropdown-condensed {
--background-image: #{$chevron-grey};
border: sizing.rems(xxxxs) solid var(--ui-border);
border-radius: sizing.rems(xxs);
.rose-dropdown-trigger {
color: var(--ui-gray-starker-1);
padding: 0 sizing.rems(s); // To clear the inherit padding.
&.show-caret {
padding-right: sizing.rems(l) + sizing.rems(xs); // 32
background-position: right sizing.rems(xs) center;
}
}
.rose-dropdown-content {
border: none;
border: sizing.rems(xxxxs) solid var(--ui-border);
}
}
}
@@ -1,10 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@use 'dropdown';
@use 'link';
@use 'item';
@use 'section';
@use 'key-value';
@@ -1,156 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@use '../../variables/sizing';
@use '../../utilities/type';
@use 'sass:math';
$checkmark: url("data:image/svg+xml;utf-8,<svg viewBox='0 0 24 24' fill='%231563ff' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z'></path></svg>");
.rose-dropdown-item {
@include type.type(s);
min-width: (sizing.rems(m)) * 20;
$y-padding: math.div(
sizing.rems(xl) - (sizing.rems(m) + sizing.rems(xxxs)),
2
);
$x-padding: sizing.rems(s);
padding: $y-padding $x-padding;
--color: var(--stark);
--background-color: transparent;
color: var(--color);
background-color: var(--background-color);
.rose-form-radio {
color: currentcolor;
margin-bottom: 0;
.rose-form-radio-label {
display: block;
margin: -#{$y-padding} -#{$x-padding};
padding-top: sizing.rems(xs) + sizing.rems(xxxxs);
padding-bottom: sizing.rems(xs) + sizing.rems(xxxxs);
padding-left: sizing.rems(s);
padding-right: sizing.rems(xl);
font-weight: normal;
&:hover {
background-color: var(--ui-gray-subtler-5);
}
&::after {
top: sizing.rems(xxs) + sizing.rems(xxxs);
right: sizing.rems(xs);
left: auto;
transform: scale(1.5);
}
}
.rose-form-radio-field {
&:not(:checked) {
~ .rose-form-radio-label {
&::after {
opacity: 0.25;
}
}
}
&:checked {
~ .rose-form-radio-label {
color: var(--action);
background-color: var(--action-subtler-1h);
}
}
&:disabled {
~ .rose-form-radio-label {
opacity: 0.5;
}
}
}
}
.rose-form-checkbox {
color: currentcolor;
margin-bottom: 0;
.rose-form-checkbox-label {
display: block;
margin: -#{$y-padding} -#{$x-padding};
padding-top: sizing.rems(xs) + sizing.rems(xxxxs);
padding-bottom: sizing.rems(xs) + sizing.rems(xxxxs);
padding-left: sizing.rems(s);
padding-right: sizing.rems(xl) + sizing.rems(l);
font-weight: normal;
&:hover {
background-color: var(--ui-gray-subtler-5);
}
&::after {
top: sizing.rems(xxs);
right: sizing.rems(xs);
left: auto;
border: sizing.rems(xxxs) solid var(--ui-gray-subtler-2);
border-radius: sizing.rems(xxxs);
transform: scale(0.66);
}
&::before {
position: absolute;
top: sizing.rems(xs);
left: 0;
display: block;
width: sizing.rems(m);
height: sizing.rems(m);
pointer-events: none;
content: ' ';
border: none;
}
}
.rose-form-checkbox-field {
&:hover {
~ .rose-form-checkbox-label {
&::after {
border-color: var(--ui-gray);
}
}
}
&:checked {
~ .rose-form-checkbox-label {
color: var(--action);
background-color: var(--action-subtler-1h);
&::after {
border-color: var(--action);
background-size: sizing.rems(m);
}
}
}
&:disabled {
~ .rose-form-checkbox-label {
opacity: 0.5;
&::after {
border-color: var(--ui-gray-subtler-2);
background-color: var(--ui-gray-subtler-4);
}
&::before {
background: none;
}
}
}
}
}
}
@@ -1,17 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@use '../../variables/sizing';
.rose-dropdown-key-value {
.rose-dropdown-key {
text-transform: capitalize;
}
.rose-dropdown-value {
color: var(--ui-gray);
padding: sizing.rems(xxs) sizing.rems(s) 0 0;
}
}
@@ -1,45 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@use '../../variables/sizing';
@use '../../utilities/type';
@use 'sass:math';
.rose-dropdown-link {
@include type.type(s);
display: block;
box-sizing: border-box;
width: 100%;
min-width: (sizing.rems(m)) * 13;
border: 0;
padding: 0 sizing.rems(s);
text-decoration: none;
text-align: left;
$line-height: math.div(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(--subtle);
--color: var(--failure);
&:hover {
--color: var(--subtle);
--background-color: var(--failure);
}
}
}
@@ -1,27 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
@use '../../variables/sizing';
@use '../../utilities/type';
@use 'sass:math';
.rose-dropdown-section {
.rose-dropdown-section-title {
@include type.type(xs, normal);
text-transform: uppercase;
padding: 0 sizing.rems(s);
margin: 0;
$line-height: math.div(36, 14);
line-height: $line-height;
color: var(--ui-gray);
.hds-icon {
vertical-align: text-top;
}
}
}
@@ -22,18 +22,4 @@
width: sizing.rems(l);
}
}
.rose-header-dropdown {
.rose-header-dropdown-trigger-text {
@include typography.type(h1, bold);
margin-top: sizing.rems(xs);
margin-bottom: sizing.rems(xs);
margin-right: sizing.rems(xs);
}
.rose-header-dropdown-trigger {
background-size: sizing.rems(l);
}
}
}
@@ -1,112 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, click, find, findAll } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | rose/dropdown', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
await render(hbs`<Rose::Dropdown />`);
assert.ok(find('.rose-dropdown'));
assert.notOk(find('.rose-dropdown-right'));
});
test('it renders with html attributes', async function (assert) {
await render(hbs`<Rose::Dropdown id="custom-id" class="custom-class"/>`);
assert.ok(find('#custom-id'));
assert.ok(find('.custom-class'));
});
test('it renders with trigger', async function (assert) {
await render(hbs`<Rose::Dropdown @text="Click me" />`);
assert.strictEqual(
find('.rose-dropdown-trigger').textContent.trim(),
'Click me',
);
});
test('it supports a count', async function (assert) {
await render(hbs`<Rose::Dropdown @text="Click me" @count="2" />`);
assert.strictEqual(find('.hds-badge-count').textContent.trim(), '2');
});
test('it supports an icon', async function (assert) {
await render(hbs`<Rose::Dropdown @icon="user-circle" />`);
assert.dom('svg').isVisible();
});
test('it supports icon-only display', async function (assert) {
await render(hbs`<Rose::Dropdown @iconOnly={{true}} />`);
assert.ok(find('.has-icon-only'));
});
test('it supports right aligned content', async function (assert) {
await render(hbs`
<Rose::Dropdown @dropdownRight={{true}} />
`);
assert.ok(find('.rose-dropdown-right'));
});
test('it supports hiding dropdown caret', async function (assert) {
await render(hbs`<Rose::Dropdown />`);
assert.ok(find('.show-caret'));
await render(hbs`<Rose::Dropdown @showCaret={{false}}/>`);
assert.notOk(find('.show-caret'));
});
test('it renders with content', async function (assert) {
await render(hbs`<Rose::Dropdown @text="Click me" as |dropdown|>
<dropdown.link @route="about"/>
<dropdown.link @route="about"/>
<dropdown.button />
<dropdown.button />
<dropdown.button />
</Rose::Dropdown>`);
assert.ok(find('.rose-dropdown-content'));
assert.strictEqual(findAll('a').length, 2);
assert.strictEqual(findAll('button').length, 3);
});
test('it is toggled on click on trigger content', async function (assert) {
await render(hbs`<Rose::Dropdown id="dropdown" />`);
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`
<div id="wrapper">
<Rose::Dropdown id="dropdown" />
</div>
`);
await click('summary');
assert.ok(find('#dropdown').open);
await click('#wrapper');
assert.notOk(find('#dropdown').open);
});
test('it is closed when inside content is clicked', async function (assert) {
await render(hbs`
<Rose::Dropdown as |dropdown|>
<dropdown.button>Button</dropdown.button>
</Rose::Dropdown>
`);
await click('summary');
assert.ok(find('.rose-dropdown').open);
await click('button');
assert.notOk(find('.rose-dropdown').open);
});
});
@@ -1,43 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, find } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | rose/dropdown/button', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
await render(hbs`<Rose::Dropdown::Button />`);
assert.ok(find('.rose-dropdown-button'));
});
test('it is type="button" by default', async function (assert) {
await render(hbs`<Rose::Dropdown::Button />`);
assert.strictEqual(find('button').type, 'button');
});
test('it is type="submit" when @onSubmit={{true}}', async function (assert) {
await render(hbs`<Rose::Dropdown::Button @onSubmit={{true}} />`);
assert.strictEqual(find('button').type, 'submit');
});
test('it is disabled when @disabled={{true}}', async function (assert) {
await render(hbs`<Rose::Dropdown::Button @disabled={{true}} />`);
assert.true(find('button').disabled);
});
test('it adds a style class', async function (assert) {
await render(hbs`<Rose::Dropdown::Button @style="warning" />`);
assert.ok(find('.rose-dropdown-button-warning'));
});
test('it supports an icon-only type', async function (assert) {
await render(hbs`<Rose::Dropdown::Button @iconOnly="chevron-left" />`);
assert.dom('.has-icon-only .hds-icon').isVisible();
});
});
@@ -1,28 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, find } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | rose/dropdown/key-value', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
await render(hbs`
<Rose::Dropdown::KeyValue>
<:key>key</:key>
<:value>value</:value>
</Rose::Dropdown::KeyValue>
`);
assert.strictEqual(find('.rose-dropdown-key').textContent.trim(), 'key');
assert.strictEqual(
find('.rose-dropdown-value').textContent.trim(),
'value',
);
});
});
@@ -1,39 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, find } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | rose/dropdown/link', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
await render(hbs`<Rose::Dropdown::Link />`);
assert.ok(find('a'));
assert.ok(find('.rose-dropdown-link'));
});
test('it renders with attributes', async function (assert) {
await render(hbs`<Rose::Dropdown::Link id="dropdown" />`);
assert.ok(find('#dropdown'));
});
test('it renders with content', async function (assert) {
await render(hbs`<Rose::Dropdown::Link>
content
</Rose::Dropdown::Link>`);
assert.strictEqual(
find('.rose-dropdown-link').textContent.trim(),
'content',
);
});
test('it supports style', async function (assert) {
await render(hbs`<Rose::Dropdown::Link @style='warning' />`);
assert.ok('.rose-dropdown-link-warning');
});
});
@@ -1,35 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, find } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | rose/dropdown/section', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
await render(hbs`
<Rose::Dropdown::Section>
template block text
</Rose::Dropdown::Section>
`);
assert.ok(find('.rose-dropdown-section'));
assert.strictEqual(this.element.textContent.trim(), 'template block text');
});
test('it renders with optional @title', async function (assert) {
await render(hbs`
<Rose::Dropdown::Section @title="Section Title">
template block text
</Rose::Dropdown::Section>
`);
assert.strictEqual(
find('.rose-dropdown-section-title').textContent.trim(),
'Section Title',
);
});
});
@@ -34,19 +34,6 @@ module('Integration | Component | rose/header', function (hooks) {
assert.notOk(find('.rose-header-utilities'));
});
test('it renders with nav elements', async function (assert) {
await render(hbs`<Rose::Header as |header| >
<header.nav as |nav|>
<nav.dropdown @text='org-name' 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>
</nav.dropdown>
</header.nav>
</Rose::Header>`);
assert.ok(find('.rose-dropdown'));
});
test('it renders with utilities', async function (assert) {
await render(hbs`<Rose::Header as |header| >
<header.utilities />
@@ -56,12 +43,14 @@ module('Integration | Component | rose/header', function (hooks) {
assert.ok(find('.rose-header-utilities'));
});
test('it renders with utility elements', async function (assert) {
test('it renders the hds dropdown within header utilities', async function (assert) {
await render(hbs`<Rose::Header as |header| >
<header.utilities as |utility| >
<utility.dropdown />
<header.utilities>
<Hds::Dropdown as |D|>
<D.ToggleButton @text="Menu" />
</Hds::Dropdown>
</header.utilities>
</Rose::Header>`);
assert.ok(find('.rose-dropdown'));
assert.ok(find('.hds-dropdown'));
});
});
@@ -5,7 +5,7 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, find, findAll } from '@ember/test-helpers';
import { render, find } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | rose/header/nav', function (hooks) {
@@ -15,12 +15,4 @@ module('Integration | Component | rose/header/nav', function (hooks) {
await render(hbs`<Rose::Header::nav />`);
assert.ok(find('.rose-header-nav'));
});
test('it renders nav dropdown elements', async function (assert) {
await render(hbs`<Rose::Header::nav as |nav| >
<nav.dropdown />
<nav.dropdown />
</Rose::Header::nav>`);
assert.strictEqual(findAll('.rose-dropdown').length, 2);
});
});
@@ -5,7 +5,7 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, find, findAll } from '@ember/test-helpers';
import { render, find } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | rose/header/utilities', function (hooks) {
@@ -15,19 +15,4 @@ module('Integration | Component | rose/header/utilities', function (hooks) {
await render(hbs`<Rose::Header::Utilities />`);
assert.ok(find('.rose-header-utilities'));
});
test('it renders nav dropdown elements', async function (assert) {
await render(hbs`<Rose::Header::Utilities as |nav| >
<nav.dropdown />
<nav.dropdown />
</Rose::Header::Utilities>`);
assert.strictEqual(findAll('.rose-dropdown').length, 2);
});
test('it renders nav dropdown elements as right aligned', async function (assert) {
await render(hbs`<Rose::Header::Utilities as |nav| >
<nav.dropdown />
</Rose::Header::Utilities>`);
assert.ok(find('.rose-dropdown.rose-dropdown-right'));
});
});
@@ -15,7 +15,6 @@
(if @model.isPrivate 'lock' 'check-circle')
}}
/>
{{#each @model.options.state as |state|}}
<dd.Radio
checked={{eq @model.state state}}
@@ -26,9 +25,7 @@
</dd.Radio>
{{/each}}
</Hds::Dropdown>
{{/if}}
<Hds::Dropdown data-test-manage-auth-method as |dd|>
<dd.ToggleButton @text={{t 'actions.manage'}} @color='secondary' />
{{#if @model.isPrimary}}
@@ -58,7 +55,6 @@
</dd.Interactive>
{{/if}}
{{/if}}
{{#if (can 'delete auth-method' @model)}}
<dd.Separator />
<dd.Interactive @color='critical' {{on 'click' (fn @delete @model)}}>
@@ -5,7 +5,6 @@
<Hds::Dropdown data-test-manage-dropdown-host-sets as |dd|>
<dd.ToggleButton @text={{t 'actions.manage'}} @color='secondary' />
{{#if (can 'addHosts hostSet' @model)}}
<dd.Interactive
@route='scopes.scope.host-catalogs.host-catalog.host-sets.host-set.create-and-add-host'
@@ -4,7 +4,6 @@
}}
<Hds::Dropdown data-test-manage-targets-dropdown as |dd|>
<dd.ToggleButton @text={{t 'actions.manage'}} @color='secondary' />
{{#if (can 'addHostSources target' @model)}}
<dd.Interactive @route='scopes.scope.targets.target.add-host-sources'>
{{t 'resources.target.actions.add-host-sources'}}
@@ -28,12 +27,10 @@
}}
</dd.Interactive>
{{/if}}
{{#if (can 'delete model' @model)}}
<dd.Separator />
<dd.Interactive @color='critical' {{on 'click' (fn @delete @model)}}>
{{t 'resources.target.actions.delete'}}
</dd.Interactive>
{{/if}}
</Hds::Dropdown>
-29
View File
@@ -47,29 +47,6 @@
&:not(.full-width) {
width: 66%;
}
.rose-dropdown {
$icon-width: sizing.rems(m) + sizing.rems(s);
$indent: $icon-width + sizing.rems(xs);
.rose-form-radio-label {
display: flex;
}
.indent-label-1 {
.rose-form-radio-label,
.rose-form-checkbox-label {
padding-left: $indent;
}
}
.indent-label-2 {
.rose-form-radio-label,
.rose-form-checkbox-label {
padding-left: $indent + $icon-width;
}
}
}
}
.rose-header {
@@ -998,12 +975,6 @@
margin-right: 1rem;
}
.dropdown-radio-btn {
.hds-form-group__control-field {
padding: 0.25rem 0.75rem;
}
}
// worker filter generator
.filter-generator-selection {
.hds-form-group__control-field {
@@ -9,6 +9,7 @@ import { setupApplicationTest } from 'admin/tests/helpers';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
import { authenticateSession } from 'ember-simple-auth/test-support';
import { setupIndexedDb } from 'api/test-support/helpers/indexed-db';
import * as commonSelectors from 'admin/tests/helpers/selectors';
module('Acceptance | aliases | delete', function (hooks) {
setupApplicationTest(hooks);
@@ -19,8 +20,6 @@ module('Acceptance | aliases | delete', function (hooks) {
const DROPDOWN_BUTTON_SELECTOR =
'tbody tr td:last-child .hds-dropdown-toggle-icon';
const DELETE_DROPDOWN_SELECTOR =
'.hds-dropdown-list-item--color-critical button';
const instances = {
scopes: {
@@ -68,7 +67,7 @@ module('Acceptance | aliases | delete', function (hooks) {
assert.true(instances.alias.authorized_actions.includes('delete'));
await visit(urls.aliases);
await click(DROPDOWN_BUTTON_SELECTOR);
await click(DELETE_DROPDOWN_SELECTOR);
await click(commonSelectors.DELETE_BTN);
assert.strictEqual(aliasCount(), count - 1);
});
@@ -84,6 +83,6 @@ module('Acceptance | aliases | delete', function (hooks) {
await click(`[href="${urls.aliases}"]`);
await click(DROPDOWN_BUTTON_SELECTOR);
assert.dom(DELETE_DROPDOWN_SELECTOR).doesNotExist();
assert.dom(commonSelectors.DELETE_BTN).doesNotExist();
});
});
@@ -9,7 +9,6 @@ import {
currentURL,
fillIn,
click,
findAll,
getRootElement,
} from '@ember/test-helpers';
import { setupApplicationTest } from 'admin/tests/helpers';
@@ -295,26 +294,6 @@ module('Acceptance | authentication', function (hooks) {
assert.ok(currentSession().isAuthenticated);
});
// This test is disabled because it is no longer relevant. On deauth,
// the page is reloaded. If the user was viewing a route requiring
// authentication, they will be redirected accordingly.
test.skip('deauthentication redirects to first global authenticate method', async function (assert) {
await visit(authMethodAuthenticateURL);
await fillIn('[name="identification"]', 'test');
await fillIn('[name="password"]', 'test');
await click('[type="submit"]');
assert.ok(currentSession().isAuthenticated);
// 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);
});
test('401 responses result in deauthentication', async function (assert) {
await authenticateSession({
scope: { id: globalScope.id, type: globalScope.type },
@@ -112,7 +112,9 @@ module('Acceptance | host-catalogs | host-sets | hosts', function (hooks) {
);
instances.hostSet.update({ authorized_actions });
await visit(urls.hostSetHosts);
assert.notOk(find('tbody tr .rose-dropdown-button-danger'));
assert.notOk(
find('tbody tr [data-test-host-set-hosts-dropdown-remove-host]'),
);
});
test('shows error message on host remove error', async function (assert) {
@@ -146,7 +146,9 @@ module('Acceptance | targets | host-sources', function (hooks) {
await click(`[href="${urls.targetHostSources}"]`);
assert.dom('tbody tr .rose-dropdown-button-danger').doesNotExist();
assert
.dom(`tbody tr ${commonSelectors.DELETE_BTN}`)
.doesNotExist();
});
test('removing a target host set which errors displays error messages', async function (assert) {
@@ -366,7 +366,9 @@ module(
(item) => item !== 'remove-credential-sources',
);
await visit(urls.injectedApplicationCredentialSources);
assert.dom('tbody tr .rose-dropdown-button-danger').doesNotExist();
assert
.dom(`tbody tr ${commonSelectors.DELETE_BTN}`)
.doesNotExist();
});
test('removing a target credential library which errors displays error messages', async function (assert) {
@@ -10,6 +10,7 @@ import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
import a11yAudit from 'ember-a11y-testing/test-support/audit';
import { authenticateSession } from 'ember-simple-auth/test-support';
import { TYPE_TARGET_TCP, TYPE_TARGET_SSH } from 'api/models/target';
import * as commonSelectors from 'admin/tests/helpers/selectors';
module('Acceptance | targets | manage-alias', function (hooks) {
setupApplicationTest(hooks);
@@ -19,7 +20,6 @@ module('Acceptance | targets | manage-alias', function (hooks) {
const ALIASES_SIDEBAR_LIST = '.link-list-item';
const DROPDOWN_ACTION = '[data-test-manage-target-alias] button';
const CLEAR_BTN_SELECTOR = '.hds-dropdown-list-item--color-action button';
const DELETE_BTN_SELECTOR = '.hds-dropdown-list-item--color-critical button';
const LINK_TO_NEW_ALIAS = '.target-sidebar-aliases .hds-button';
const DEST_FIELD_SELECTOR = '[name="destination_id"]';
const ITEM_SELECTOR = '.link-list-item a';
@@ -144,7 +144,7 @@ module('Acceptance | targets | manage-alias', function (hooks) {
assert.strictEqual(currentURL(), urls.tcpAlias);
await click(DROPDOWN_ACTION);
await click(DELETE_BTN_SELECTOR);
await click(commonSelectors.DELETE_BTN);
assert.strictEqual(getAliasCount(), aliasCount - 1);
+1
View File
@@ -6,6 +6,7 @@
export const SAVE_BTN = '[type=submit]';
export const CANCEL_BTN = '.rose-form-actions [type=button]';
export const EDIT_BTN = '.rose-form-actions [type=button]';
export const DELETE_BTN = '.hds-dropdown-list-item--color-critical button';
export const FIELD_NAME = '[name=name]';
export const FIELD_NAME_VALUE = 'Random name';
+2 -27
View File
@@ -69,29 +69,6 @@
width: 66%;
}
.rose-dropdown {
$icon-width: sizing.rems(m) + sizing.rems(s);
$indent: $icon-width + sizing.rems(xs);
.rose-form-radio-label {
display: flex;
}
.indent-label-1 {
.rose-form-radio-label,
.rose-form-checkbox-label {
padding-left: $indent;
}
}
.indent-label-2 {
.rose-form-radio-label,
.rose-form-checkbox-label {
padding-left: $indent * 1.5;
}
}
}
fieldset {
margin-bottom: sizing.rems(m);
}
@@ -105,12 +82,10 @@
.rose-header-brand,
.rose-header-nav,
.rose-header-utilities .rose-dropdown,
.rose-header-utilities button {
-webkit-app-region: no-drag;
}
&.header-cushion {
padding-left: sizing.rems(l) * 3;
}
@@ -456,4 +431,4 @@
flex-basis: 100%;
}
}
}
}
@@ -183,12 +183,12 @@ module('Acceptance | authentication', function (hooks) {
assert.ok(currentSession().isAuthenticated);
await click('.rose-header-utilities .header-dropdown-button-override button');
await click(
'.rose-header-utilities .header-dropdown-button-override button',
);
assert.strictEqual(
find(
'[data-test-sign-out]',
).textContent.trim(),
find('[data-test-sign-out]').textContent.trim(),
'Sign Out',
);
@@ -229,6 +229,7 @@ module('Acceptance | scopes', function (hooks) {
await visit(urls.targets);
await click('.rose-header-nav .hds-dropdown-toggle-button');
await click('.rose-header-nav .hds-dropdown-list-item:nth-of-type(3) a');
assert.strictEqual(currentURL(), urls.targets);