UI: Remove custom tag class and replace with Hds::Badge (#29475)

* replace custom tag class with Hds::Badge

* another wave of custom class replacements

* remove tag class styles and cleanup

* add changelog entry

* fix changelog name

* remove changelog entry and old styles and clean up

* remove extra classes and clean up

* one more clean up section

* update tests

* fix value check

* updated test

* update tests

* switch to code elements with specific styling and cleanup
This commit is contained in:
lane-wetmore
2025-02-07 15:29:12 -06:00
committed by GitHub
parent 784216310f
commit 4051cb4d4c
36 changed files with 103 additions and 155 deletions

View File

@@ -12,7 +12,7 @@
<h2 class="title is-4 has-left-margin-xxs" data-test-dashboard-card-header="Secrets engines">Secrets engines</h2>
{{#if this.filteredSecretsEngines}}
<LinkTo class="has-right-margin-xxs" @route="vault.cluster.secrets.backends">
<LinkTo class="has-right-margin-4" @route="vault.cluster.secrets.backends">
Details
</LinkTo>
{{/if}}

View File

@@ -24,7 +24,7 @@
{{/if}}
<div class="field">
<Toolbar aria-label="toolbar for managing {{or @model.name 'new'}} policy">
<label class="has-text-weight-bold has-right-margin-xxs">Policy</label>
<label class="has-text-weight-bold has-right-margin-4">Policy</label>
{{#if @renderPolicyExampleModal}}
{{! only true in policy create and edit routes }}
<ToolbarFilters aria-label="help tools for managing {{or @model.name 'new'}} policy">

View File

@@ -15,10 +15,4 @@
margin: $spacing-4 0 0;
opacity: 0.7;
position: absolute;
.tag {
background-color: $ui-gray-800;
color: $light-grey;
font-size: $size-9;
}
}

View File

@@ -40,7 +40,6 @@
@import './core/message';
@import './core/progress';
@import './core/select';
@import './core/tag';
@import './core/title';
@import './core/toggle';

View File

@@ -195,3 +195,8 @@ label {
cursor: not-allowed;
}
}
// <Hds::Text::Code> this applies to code elements that are placed within a surrounding text - not for standalone use
.hds-text.code-in-text {
background-color: var(--token-color-surface-strong);
}

View File

@@ -1,73 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
// This file defines the style for .tag
.tag:not(body) {
align-items: center;
// same as HDS::Badge @color=neutral
background-color: var(--token-color-surface-strong);
color: var(--token-color-foreground-primary);
border-radius: $radius;
display: inline-flex;
font-size: $size-8;
font-weight: $font-weight-normal;
height: auto;
justify-content: center;
line-height: 1.5;
margin-right: $spacing-8;
padding: 0 $spacing-8;
white-space: nowrap;
vertical-align: middle;
code {
color: var(--token-color-foreground-primary);
}
.icon {
height: 12px;
margin-left: -0.25em;
margin-right: 0.25em;
min-width: 0;
width: 12px;
}
&.has-extra-padding {
padding: $spacing-4 $spacing-4;
}
}
.tag {
&.is-bold {
font-weight: bold;
}
&.is-light {
background-color: whitesmoke;
color: rgba(0, 0, 0, 0.7);
}
&.is-outlined {
background-color: transparent;
border: 1px solid $grey-light;
}
&.is-transparent {
background-color: transparent;
}
&.is-small {
height: auto;
}
&.is-medium {
font-size: $size-6;
}
&.is-success {
background-color: $green-500;
color: $white;
}
}

View File

@@ -21,6 +21,11 @@
padding: $spacing-36;
}
.has-side-padding-8 {
padding-left: $spacing-8;
padding-right: $spacing-8;
}
.has-side-padding-s {
padding-left: $spacing-12;
padding-right: $spacing-12;
@@ -122,10 +127,6 @@
margin-top: -$spacing-48;
}
.has-right-margin-xxs {
margin-right: $spacing-4;
}
.has-left-margin-xxs {
margin-left: $spacing-4;
}
@@ -218,6 +219,14 @@
margin-left: $spacing-36;
}
.has-right-margin-4 {
margin-right: $spacing-4;
}
.has-right-margin-8 {
margin-right: $spacing-8;
}
.has-right-margin-m {
margin-right: $spacing-16;
}

View File

@@ -18,7 +18,7 @@
<div>
{{@model.mountPath}}
<div>
<span class="tag">{{@model.mountType}}</span>
<Hds::Badge @text={{@model.mountType}} class="has-right-margin-8" />
<code class="has-text-grey is-size-8">{{@model.mountAccessor}}</code>
</div>
</div>

View File

@@ -18,7 +18,7 @@
<div class="has-text-grey">
{{item.id}}
</div>
<span class="tag">{{item.mountType}}</span>
<Hds::Badge @text={{item.mountType}} />
<span class="has-text-grey is-size-8">
{{item.mountAccessor}}
</span>

View File

@@ -14,7 +14,7 @@
<LinkTo @route="vault.cluster.access.identity.show" @models={{array "groups" gid "details"}} class="has-text-black">
<Icon @name="folder" class="has-text-grey-light" />{{gid}}
</LinkTo>
<span class="tag has-text-grey is-size-8">inherited</span>
<Hds::Badge @text="inherited" />
</LinkedBlock>
{{/each}}
{{else}}

View File

@@ -16,9 +16,7 @@
<span class="has-text-weight-semibold has-text-black">
{{@model.name}}
</span>
<span class="tag has-left-margin-xs">
{{@model.id}}
</span>
<Hds::Badge @text={{@model.id}} class="has-left-margin-xs" />
<div class="has-top-margin-xs">
<code class="is-size-9">
Namespace:

View File

@@ -63,7 +63,7 @@
<InfoTableRow @label={{target.label}} class="is-flex-grow-1 has-no-shadow">
{{#if target.value.id}}
{{target.value.name}}
<span class="tag has-left-margin-s">{{target.value.id}}</span>
<Hds::Badge @text={{target.value.id}} class="has-left-margin-s" />
{{else}}
{{target.value}}
{{/if}}

View File

@@ -21,7 +21,9 @@
<Icon @name="user" class="has-text-grey-light is-pulled-left" />
<div class="role-item-details">
<span class="is-underline">{{if (eq @item.id " ") "(self)" (or @item.keyWithoutParent @item.id)}}</span>
<span class="tag has-text-grey-dark">{{this.keyTypeValue}}</span>
{{#if this.keyTypeValue}}
<Hds::Badge @text={{this.keyTypeValue}} />
{{/if}}
</div>
</LinkTo>
</div>

View File

@@ -27,7 +27,7 @@
<div class="role-item-details">
<span class="is-underline">{{if (eq @item.id " ") "(self)" (or @item.keyWithoutParent @item.id)}}</span>
<br />
<span class="tag has-text-grey-dark">{{@item.keyType}}</span>
<Hds::Badge @text={{@item.keyType}} />
{{#if @item.zeroAddress}}
<span class="has-text-grey is-size-7">Zero-Address</span>
{{/if}}

View File

@@ -25,7 +25,7 @@
<div class="has-text-grey">
{{item.id}}
</div>
<span class="tag">{{item.mountType}}</span>
<Hds::Badge @text={{item.mountType}} class="has-right-margin-8" />
<span class="has-text-grey is-size-8">
{{item.mountAccessor}}
</span>

View File

@@ -58,4 +58,5 @@
</ToolbarLink>
</ToolbarActions>
</Toolbar>
{{! renders either the identity item-aliases or item-groups component}}
{{component (concat "identity/item-" this.section) model=this.model}}

View File

@@ -10,9 +10,7 @@
{{uppercase this.policyType}}
Policies
{{#if (not-eq this.policyType "acl")}}
<span class="tag" aria-label="Enforcement level: {{this.model.enforcementLevel}}">
Sentinel
</span>
<Hds::Badge @text="Sentinel" />
{{/if}}
</h1>
</p.levelLeft>

View File

@@ -20,9 +20,7 @@
<h1 class="title is-3">
{{this.model.id}}
{{#if this.model.enforcementLevel}}
<span class="tag is-medium" aria-label="Enforcement level: {{this.model.enforcementLevel}}">
{{this.model.enforcementLevel}}
</span>
<Hds::Badge @text={{this.model.enforcementLevel}} aria-label="Enforcement level: {{this.model.enforcementLevel}}" />
{{/if}}
</h1>
</p.levelLeft>

View File

@@ -19,9 +19,7 @@
<h1 class="title is-3" data-test-policy-name="true">
{{this.model.id}}
{{#if this.model.enforcementLevel}}
<span class="tag" aria-label="Enforcement level: {{this.model.enforcementLevel}}">
{{this.model.enforcementLevel}}
</span>
<Hds::Badge @text={{this.model.enforcementLevel}} aria-label="Enforcement level: {{this.model.enforcementLevel}}" />
{{/if}}
</h1>
</p.levelLeft>

View File

@@ -13,10 +13,12 @@
{{#if (is-wildcard-string item)}}
{{#let (filter-wildcard item this.allOptions) as |wildcardCount|}}
<span>{{item}}</span>
<span class="tag is-light has-text-grey-dark" data-test-count={{wildcardCount}}>
{{if (not-eq wildcardCount undefined) (concat "includes " wildcardCount)}}
{{if (eq wildcardCount 1) @wildcardLabel (pluralize @wildcardLabel)}}
</span>
{{#if (not-eq wildcardCount undefined)}}
<Hds::Badge
@text="includes {{pluralize wildcardCount this.wildcardLabel}}"
data-test-count={{wildcardCount}}
/>
{{/if}}
{{#if (eq this.displayArrayTruncated.lastObject item)}}
<LinkTo @route={{this.rootRoute}} @query={{hash tab=@queryParam}}>
<span data-test-view-all={{lowercase @label}}>View all {{lowercase @label}}.</span>

View File

@@ -4,9 +4,10 @@
*/
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { service } from '@ember/service';
import { assert } from '@ember/debug';
import { action } from '@ember/object';
import { service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
/**
* @module InfoTableItemArray
@@ -36,6 +37,11 @@ export default class InfoTableItemArray extends Component {
@tracked itemNameById; // object is only created if renderItemName=true
@tracked fetchComplete = false;
constructor() {
super(...arguments);
assert('@label is required for InfoTableItemArray components', this.args.label);
}
get rootRoute() {
return this.args.rootRoute || 'vault.cluster.secrets.backend.list-root';
}
@@ -58,6 +64,10 @@ export default class InfoTableItemArray extends Component {
return displayArray;
}
get wildcardLabel() {
return this.args.wildcardLabel || '';
}
@action async fetchOptions() {
if (this.args.isLink && this.args.modelType) {
const queryOptions = this.args.backend ? { backend: this.args.backend } : {};

View File

@@ -15,7 +15,8 @@
will be
{{this.modeVerb}}
in the
<span class="tag">{{this.namespace.path}}/</span>namespace.
<Hds::Badge @text="{{this.namespace.path}}/" />
namespace.
</p>
{{/if}}
{{/if}}

View File

@@ -25,17 +25,17 @@
</p>
<p>
Here is an example policy that uses RGP to restrict access to the
<code class="tag is-marginless is-paddingless">admin</code>
<Hds::Text::Code class="code-in-text">admin</Hds::Text::Code>
policy such that a user named "James Thomas" or has the
<code class="tag is-marginless is-paddingless">Team Lead</code>
<Hds::Text::Code class="code-in-text">Team Lead</Hds::Text::Code>
role can manage the
<code class="tag is-marginless is-paddingless">admin</code>
<Hds::Text::Code class="code-in-text">admin</Hds::Text::Code>
policy:
</p>
{{else}}
<p class="has-bottom-margin-s" data-test-example-modal-text="egp">
Endpoint Governing Policies (EGPs) are tied to particular paths (e.g.
<code class="tag is-marginless is-paddingless">aws/creds/</code>
<Hds::Text::Code class="code-in-text">aws/creds/</Hds::Text::Code>
) instead of tokens. They use
<Hds::Link::Inline
@isHrefExternal={{true}}

View File

@@ -16,12 +16,10 @@
<h1 class="title is-3" data-test-replication-title={{@title}}>
{{@title}}
{{#if @data.anyReplicationEnabled}}
<span class="tag is-light has-text-grey-dark" data-test-mode>
{{if @isSecondary "secondary" "primary"}}
</span>
<span class="tag is-light has-text-grey-dark" data-test-secondaryId>
{{@secondaryId}}
</span>
<Hds::Badge @text={{if @isSecondary "secondary" "primary"}} data-test-mode />
{{#if @secondaryId}}
<Hds::Badge @text={{@secondaryId}} data-test-secondaryId />
{{/if}}
{{/if}}
</h1>
</p.levelLeft>

View File

@@ -68,16 +68,15 @@
{{get selected this.idKey}}
</small>
{{else}}
<div class="list-item-text has-right-margin-xxs text-overflow-ellipsis">
<div class="list-item-text has-right-margin-4 text-overflow-ellipsis">
{{selected.id}}
{{#if @wildcardLabel}}
{{#if (is-wildcard-string selected.id)}}
{{#let (filter-wildcard selected this.allOptions) as |wildcardCount|}}
<span class="tag is-light has-text-grey-dark" data-test-count={{wildcardCount}}>
includes
{{wildcardCount}}
{{if (eq wildcardCount 1) @wildcardLabel (pluralize @wildcardLabel)}}
</span>
<Hds::Badge
@text="includes {{pluralize wildcardCount @wildcardLabel}}"
data-test-count={{wildcardCount}}
/>
{{/let}}
{{/if}}
{{/if}}

View File

@@ -24,10 +24,7 @@
<Icon @name={{@model.icon}} @size="24" class="has-text-grey-light" />
{{@model.id}}
{{#if this.isKV}}
<span class="tag" data-test-kv-version-badge>
version
{{or @model.version "1"}}
</span>
<Hds::Badge @text="version {{or @model.version '1'}}" data-test-kv-version-badge />
{{/if}}
</h1>

View File

@@ -12,7 +12,7 @@
{{#if @mountName}}
<Icon @name="key-values" @size="24" class="has-text-grey-light" />
{{@mountName}}
<span class="tag">version 2</span>
<Hds::Badge @text="version 2" />
{{else if @secretPath}}
{{@secretPath}}
<Hds::Copy::Button @isIconOnly={{true}} @text="Copy your secret path" @textToCopy={{@secretPath}} />

View File

@@ -65,22 +65,22 @@
<span class="has-text-weight-semibold is-underline">
{{pkiIssuer.issuerRef}}
{{#if pkiIssuer.issuerName}}
<span class="tag has-text-grey-dark">{{pkiIssuer.id}}</span>
<Hds::Badge @text={{pkiIssuer.id}} />
{{/if}}
</span>
<div class="is-flex-row has-left-margin-l has-top-margin-xs">
{{#if pkiIssuer.isDefault}}
<span class="tag has-text-grey-dark" data-test-is-default={{idx}}>default issuer</span>
<Hds::Badge @text="default issuer" data-test-is-default={{idx}} class="has-right-margin-8" />
{{/if}}
{{#if (not-eq pkiIssuer.isRoot undefined)}}
<span class="tag has-text-grey-dark" data-test-is-root-tag={{idx}}>{{if
pkiIssuer.isRoot
"root"
"intermediate"
}}</span>
<Hds::Badge
@text={{if pkiIssuer.isRoot "root" "intermediate"}}
data-test-is-root-tag={{idx}}
class="has-right-margin-8"
/>
{{/if}}
{{#if pkiIssuer.serialNumber}}
<span class="tag is-transparent has-right-margin-none" data-test-serial-number={{idx}}>
<span class="is-flex-v-centered has-side-padding-8" data-test-serial-number={{idx}}>
<InfoTooltip>
Serial number
</InfoTooltip>
@@ -88,7 +88,7 @@
</span>
{{/if}}
{{#if pkiIssuer.parsedCertificate.common_name}}
<span class="tag is-transparent has-left-margin-none" data-test-common-name={{idx}}>
<span class="is-flex-v-centered has-side-padding-8" data-test-common-name={{idx}}>
<InfoTooltip>
Common name
</InfoTooltip>

View File

@@ -37,7 +37,7 @@
</span>
<div class="is-flex-row has-left-margin-l has-top-margin-xs">
{{#if pkiKey.keyName}}
<span class="tag has-text-grey-dark" data-test-key="id">{{pkiKey.id}}</span>
<Hds::Badge @text={{pkiKey.id}} data-test-key="id" />
{{/if}}
</div>
</div>

View File

@@ -32,9 +32,11 @@
<LinkTo @route="keys.key.details" @models={{array @model.backend @model.keyId}}>
{{@model.keyId}}
</LinkTo>
{{else if value}}
{{value}}
{{! it's unlikely but if a value is returned for privateKey and privateKeyType we want to display it, otherwise we show the "internal" badge below }}
{{else}}
{{! this block only ever renders privateKey and privateKeyType }}
<span class="{{unless value 'tag'}}">{{or value "internal"}}</span>
<Hds::Badge @text="internal" />
{{/if}}
</InfoTableRow>
{{/let}}

View File

@@ -37,11 +37,15 @@
{{#if @model.privateKey}}
<CertificateCard @data={{@model.privateKey}} />
{{else}}
<span class="tag">internal</span>
<Hds::Badge @text="internal" />
{{/if}}
</InfoTableRow>
<InfoTableRow @label="Private key type" @value={{@model.privateKeyType}}>
<span class="{{unless @model.privateKeyType 'tag'}}">{{or @model.privateKeyType "internal"}}</span>
{{#if @model.privateKeyType}}
{{@model.privateKeyType}}
{{else}}
<Hds::Badge @text="internal" />
{{/if}}
</InfoTableRow>
<ParsedCertificateInfoRows @model={{@model.parsedCertificate}} />
</main>

View File

@@ -18,7 +18,11 @@
{{else if attr.options.detailLinkTo}}
<LinkTo @route={{attr.options.detailLinkTo}} @model={{value}}>{{value}}</LinkTo>
{{else if (or (eq attr.name "privateKey") (eq attr.name "privateKeyType"))}}
<span class="{{unless value 'tag'}}">{{or value "internal"}}</span>
{{#if value}}
{{value}}
{{else}}
<Hds::Badge @text="internal" />
{{/if}}
{{else if attr.options.formatDate}}
{{date-format value "MMM d yyyy HH:mm:ss a zzzz"}}
{{else}}

View File

@@ -19,9 +19,7 @@
<p.levelLeft>
<h1 class="has-top-margin-m title is-3" data-test-replication-title={{this.model.replicationModeForDisplay}}>
{{this.model.replicationModeForDisplay}}
<span class="tag is-light has-text-grey-dark" data-test-replication-mode-display>
{{this.model.replicationAttrs.modeForHeader}}
</span>
<Hds::Badge @text={{this.model.replicationAttrs.modeForHeader}} data-test-replication-mode-display />
</h1>
</p.levelLeft>
</PageHeader>

View File

@@ -249,7 +249,9 @@ module('Acceptance | mfa-method', function (hooks) {
test('it should edit methods', async function (assert) {
await visit('/vault/access/mfa/methods');
const id = this.element.querySelector('[data-test-mfa-method-list-item] .tag').textContent.trim();
const id = this.element
.querySelector('[data-test-mfa-method-list-item] .hds-badge div')
.textContent.trim();
const model = this.store.peekRecord('mfa-method', id);
await click('[data-test-mfa-method-list-item] [data-test-popup-menu-trigger]');
await click('[data-test-mfa-method-menu-link="edit"]');

View File

@@ -70,6 +70,7 @@ module('Integration | Component | InfoTableItemArray', function (hooks) {
test('it renders', async function (assert) {
await render(hbs`<InfoTableItemArray
@displayArray={{this.displayArray}}
@label="my label"
/>`);
assert.dom('[data-test-info-table-item-array]').exists();
@@ -86,6 +87,7 @@ module('Integration | Component | InfoTableItemArray', function (hooks) {
<InfoTableItemArray
@displayArray={{this.displayArray}}
@isLink={{this.isLink}}
@label="my label"
@modelType={{this.modelType}}
@queryParam={{this.queryParam}}
@backend={{this.backend}}

View File

@@ -215,7 +215,7 @@ module('Integration | Component | page/pki-issuer-rotate-root', function (hooks)
assert.dom(GENERAL.infoRowValue('Issuer name')).exists();
assert.dom(GENERAL.infoRowValue('Issuing CA')).exists();
assert.dom(GENERAL.infoRowValue('Private key')).exists();
assert.dom(`${GENERAL.infoRowValue('Private key type')} span`).hasText('rsa');
assert.dom(`${GENERAL.infoRowValue('Private key type')}`).hasText('rsa');
assert.dom(GENERAL.infoRowValue('Serial number')).hasText(this.returnedData.serial_number);
assert.dom(GENERAL.infoRowValue('Key ID')).hasText(this.returnedData.key_id);
@@ -254,8 +254,8 @@ module('Integration | Component | page/pki-issuer-rotate-root', function (hooks)
assert.dom(GENERAL.infoRowValue('Certificate')).exists();
assert.dom(GENERAL.infoRowValue('Issuer name')).exists();
assert.dom(GENERAL.infoRowValue('Issuing CA')).exists();
assert.dom(`${GENERAL.infoRowValue('Private key')} span`).hasText('internal');
assert.dom(`${GENERAL.infoRowValue('Private key type')} span`).hasText('internal');
assert.dom(`${GENERAL.infoRowValue('Private key')} div`).hasText('internal');
assert.dom(`${GENERAL.infoRowValue('Private key type')} div`).hasText('internal');
assert.dom(GENERAL.infoRowValue('Serial number')).hasText(this.returnedData.serial_number);
assert.dom(GENERAL.infoRowValue('Key ID')).hasText(this.returnedData.key_id);