Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ describe('indicators-storybook', () => {
.should('exist')
.should('be.visible')
// Capture the focus style of the first token.
.get('sky-tokens:first-child sky-token:first-child > .sky-token')
.click({ multiple: true })
.get(
'sky-tokens:first-child sky-token:first-child .sky-token-btn-action'
)
.click()
.get('app-tokens')
.screenshot(`tokenscomponent-tokens--tokens-${theme}`)
.percySnapshot(`tokenscomponent-tokens--tokens-${theme}`, {
Expand Down
2 changes: 1 addition & 1 deletion apps/e2e/split-view-storybook/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
"maximumError": "5kb"
}
],
"fileReplacements": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<sky-tokens
data-sky-id="non-dismissible-tokens"
[dismissible]="false"
[focusable]="false"
[tokens]="data"
></sky-tokens>

<sky-tokens
data-sky-id="dismissible-tokens"
[dismissible]="true"
[focusable]="true"
[tokens]="data"
></sky-tokens>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Component } from '@angular/core';

import { SkyToken } from '../types/token';

@Component({
selector: 'sky-token-a11y-test',
templateUrl: './token-a11y.component.fixture.html',
})
export class SkyTokenA11yTestComponent {
public data: SkyToken<{ name: string }>[] = [
{
value: { name: 'Apple' },
},
{
value: { name: 'Orange' },
},
{
value: { name: 'Strawberry' },
},
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations';

import { SkyTokensModule } from '../tokens.module';

import { SkyTokenA11yTestComponent } from './token-a11y.component.fixture';
import { SkyTokenTestComponent } from './token.component.fixture';
import { SkyTokensTestComponent } from './tokens.component.fixture';

@NgModule({
declarations: [SkyTokenTestComponent, SkyTokensTestComponent],
declarations: [
SkyTokenA11yTestComponent,
SkyTokenTestComponent,
SkyTokensTestComponent,
],
imports: [CommonModule, NoopAnimationsModule, SkyTokensModule],
exports: [SkyTokenTestComponent, SkyTokensTestComponent],
exports: [
SkyTokenA11yTestComponent,
SkyTokenTestComponent,
SkyTokensTestComponent,
],
})
export class SkyTokensFixturesModule {}
Original file line number Diff line number Diff line change
@@ -1,39 +1,69 @@
<div
class="sky-token sky-btn sky-btn-default"
role="button"
[attr.aria-disabled]="disabled"
[attr.tabindex]="tabIndex"
[attr.role]="role"
[ngClass]="{
'sky-btn-disabled': disabled,
'sky-token-dismissable': dismissible,
'sky-token-active': tokenActive && !closeActive
'sky-token-disabled': disabled,
'sky-token-dismissible': dismissible,
'sky-token-active': tokenActive && !closeActive,
'sky-token-focused': isFocused
}"
(document:mouseup)="setTokenActive(false)"
(focus)="tokenFocus.emit()"
(focusin)="onFocusIn()"
(focusout)="onFocusOut($event)"
(mousedown)="setTokenActive(true)"
>
<ng-content></ng-content>
<button
<span
[attr.role]="role === 'row' ? 'gridcell' : undefined"
class="sky-token-cell"
>
<button
class="sky-btn sky-btn-default sky-token-btn sky-token-btn-action"
type="button"
[attr.tabindex]="tabIndex"
[disabled]="disabled"
[ngClass]="{
'sky-btn-disabled': disabled
}"
#actionButton
>
<ng-content></ng-content>
</button>
</span>
<span
*ngIf="dismissible"
class="sky-btn sky-token-btn-close"
type="button"
[attr.aria-label]="ariaLabel"
[attr.tabindex]="tabIndex"
[attr.title]="ariaLabel"
[disabled]="disabled"
[ngClass]="{
'sky-token-btn-close-active': closeActive
}"
(click)="dismissToken($event)"
(document:mouseup)="setCloseActive(false)"
(mousedown)="setCloseActive(true)"
class="sky-token-cell"
[attr.role]="role === 'row' ? 'gridcell' : undefined"
>
<sky-icon class="sky-token-btn-close-icon-default" icon="times"></sky-icon>
<sky-icon
class="sky-token-btn-close-icon-modern"
icon="close"
iconType="skyux"
<button
class="sky-btn sky-token-btn sky-token-btn-close"
type="button"
[attr.aria-label]="
ariaLabel || ('skyux_tokens_dismiss_button_title' | skyLibResources)
"
[attr.tabindex]="tabIndex"
[attr.title]="
ariaLabel || ('skyux_tokens_dismiss_button_title' | skyLibResources)
"
[disabled]="disabled"
[ngClass]="{
'sky-btn-disabled': disabled,
'sky-token-btn-close-active': closeActive
}"
(click)="dismissToken($event)"
(document:mouseup)="setCloseActive(false)"
(mousedown)="setCloseActive(true)"
>
</sky-icon>
</button>
<sky-icon
class="sky-token-btn-close-icon-default"
icon="times"
></sky-icon>
<sky-icon
class="sky-token-btn-close-icon-modern"
icon="close"
iconType="skyux"
>
</sky-icon>
</button>
</span>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,60 @@
.sky-token {
background-color: $sky-background-color-info-light;
border: 1px solid $sky-highlight-color-info;
overflow: hidden;
padding: 2px 8px;
padding: 0;
display: inline-block;
user-select: none;

&:hover,
&:focus {
&.sky-token-focused {
background-color: darken($sky-background-color-info-light, 10%);
border-color: darken($sky-highlight-color-info, 10%);
cursor: pointer;
}

&:focus {
&.sky-token-focused {
@include mixins.sky-field-status('active');
}

&.sky-btn-disabled {
.sky-btn-disabled {
opacity: 1;
}
}
}

.sky-btn-disabled {
cursor: default;
user-select: none;
}

.sky-token-btn-close {
background: transparent;
padding: 0;
.sky-token-btn {
background-color: transparent;
border: 0;
margin-left: 2px;
padding: 2px 8px;
}

.sky-token-btn-action {
&:focus-visible {
outline: none;
}
}

.sky-token-btn-close {
margin-left: -2px;
opacity: 0.9;

&:hover,
&:focus {
&:focus-visible {
opacity: 1;
}
}

.sky-token-dismissible {
.sky-token-btn-action {
padding-right: 0;
}
}

.sky-token-btn-close-icon-modern {
display: none;
}
Expand All @@ -47,19 +66,18 @@
.sky-token {
align-items: center;
display: inline-flex;
padding: 1px 5px;
font-size: 14px;

&.sky-btn-disabled {
color: $sky-text-color-default;
}

&:not(.sky-btn-disabled) {
@include mixins.sky-theme-modern-border($sky-background-color-info);
}

&.sky-token-dismissable {
&.sky-token-dismissible {
padding-right: 1px;

.sky-token-btn-action {
padding-right: 0;
}
}

&:hover:not(:active) {
Expand All @@ -70,23 +88,39 @@
@include mixins.sky-theme-modern-border-active;
}

&:focus:not(:active) {
&.sky-token-focused:not(:active) {
@include mixins.sky-theme-modern-border-focus;
}

&:focus,
&.sky-token-focused,
&:hover {
background-color: $sky-background-color-info-light;
}
}

.sky-token-btn {
padding: 1px 5px;
border: 0;
box-shadow: none;
background-color: transparent;

&.sky-btn-disabled {
color: $sky-text-color-default;
}
}

.sky-token-btn-action {
font-size: 14px;
}

.sky-token-btn-close {
align-items: center;
border-radius: $sky-theme-modern-border-radius-md - 1;
display: flex;
height: 20px;
margin-left: $sky-theme-modern-margin-inline-xs;
width: 20px;
padding: 0;

&:hover {
@include mixins.sky-theme-modern-border-hover(transparent);
Expand All @@ -96,7 +130,7 @@
@include mixins.sky-theme-modern-border-active;
}

&:focus {
&:focus-visible {
outline: none;

&:not(:active) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,37 @@ describe('Token component', () => {
validateActive('sky-token-btn-close');
});

it('should emit when token focused', () => {
const fixture = TestBed.createComponent(SkyTokenComponent);
const tokenEl = fixture.nativeElement.querySelector('.sky-token');

const focusSpy = spyOn(
fixture.componentInstance.tokenFocus,
'emit'
).and.callThrough();

fixture.componentInstance.focusable = true;
fixture.detectChanges();

SkyAppTestUtility.fireDomEvent(tokenEl, 'focusin');
fixture.detectChanges();

// Ensure CSS class is added on focus.
expect(tokenEl).toHaveClass('sky-token-focused');
expect(focusSpy).toHaveBeenCalled();

SkyAppTestUtility.fireDomEvent(tokenEl, 'focusout', {
customEventInit: {
// Mock an element that is not a child of the token.
relatedTarget: document.createElement('div'),
},
});
fixture.detectChanges();

// Ensure CSS class is removed on blur.
expect(tokenEl).not.toHaveClass('sky-token-focused');
});

it('should use the specified ARIA label', () => {
const fixture = TestBed.createComponent(SkyTokenTestComponent);

Expand All @@ -59,4 +90,12 @@ describe('Token component', () => {

expect(btnEl.getAttribute('aria-label')).toBe('Remove item');
});

it('should not have a role by default', () => {
const fixture = TestBed.createComponent(SkyTokenTestComponent);
fixture.detectChanges();
expect(
fixture.nativeElement.querySelector('.sky-token').getAttribute('role')
).toBeNull();
});
});
Loading