Skip to content

Commit

Permalink
feat(copy-updates): align copy component impl with latest designs
Browse files Browse the repository at this point in the history
improve tests
fix tooltip flutter
add tooltip for copy buttons
use input element for copy value container
remove redundant triggers
clean up view templates
use obj for storing common values in copyBase

add project flag to tslint script to avoid "rule requires type information" warning
use readonly input instead of span so copy value is scrollable
use tooltipText input prop instead of tooltip to avoid namespace collision
both focus and hover can launch a tooltip
specify body for container attribute to fix tooltip styling issues
avoid breaking changes by setting buttonAriaLabel to buttonLabel value when passed in
update tests to use new property name
  • Loading branch information
seanforyou23 committed Aug 9, 2018
1 parent 28749c6 commit b640c9e
Show file tree
Hide file tree
Showing 19 changed files with 154 additions and 43 deletions.
29 changes: 21 additions & 8 deletions src/app/copy/block-copy/block-copy.component.html
@@ -1,14 +1,15 @@
<div class="pfng-block-copy">
<div class="pfng-block-copy" [ngStyle]="{'width': width}">
<label
*ngIf="label"
class="pfng-block-copy-label"
[attr.for]="buttonId">{{label}}</label>
<div class="pfng-block-copy-inner-container">
<div class="pfng-block-copy-preview" [ngClass]="{'pf-is-open': expanded}">
<button
type="button"
[attr.aria-label]="expandToggleAriaLabel"
[attr.aria-expanded]="expanded"
class="pfng-block-copy-preview-btn"
class="btn btn-default pfng-block-copy-preview-btn"
(click)="togglePanel()">
<i
aria-hidden="true"
Expand All @@ -17,20 +18,32 @@
</button>
<div
class="pfng-block-copy-preview-txt-cont"
placement="{{tooltipPlacement ? tooltipPlacement : null}}"
tooltip="{{tooltip ? tooltip : null}}">
<span class="pfng-block-copy-preview-txt">{{value}}</span>
[placement]="tooltipPlacement"
[tooltip]="tooltipText"
container="body">
<input
type="text"
tabindex="-1"
[value]="value"
class="pfng-block-copy-preview-txt"
readonly="readonly">
</div>
<button
type="button"
[attr.id]="buttonId"
class="btn btn-lg btn-default pfng-block-copy-btn"
class="btn btn-default pfng-block-copy-btn"
[attr.aria-label]="buttonAriaLabel"
[tooltip]="copyBtnTooltipText"
[placement]="copyBtnTooltipPlacement"
triggers="hover"
container="body"
(click)="copy()">
<span>
<ng-container *ngIf="!recentlyCopied">{{buttonLabel}}</ng-container>
<ng-container *ngIf="!recentlyCopied">
<i class="fa fa-clipboard" aria-hidden="true"></i>
</ng-container>
<ng-container *ngIf="recentlyCopied">
<i class="fa fa-check" aria-hidden="true"></i>
Copied
</ng-container>
</span>
</button>
Expand Down
10 changes: 6 additions & 4 deletions src/app/copy/block-copy/block-copy.component.less
@@ -1,24 +1,24 @@
.pfng-block-copy {
max-width: 100%;
&-inner-container {
background: #fff;
border: 1px solid #bbb;
}
&-preview {
display: flex;
&.pf-is-open {
border-bottom: 1px solid #bbb;
background: #ddd;
}
&-btn {
background: none;
border: none;
border-right: 1px solid #bbb;
padding: 0;
}
&-icon {
cursor: pointer;
padding: 0 1em;
padding: 0 .679em;
&.fa-angle-right {
padding: 0 1.15em;
padding: 0 .822em;
}
}
&-txt-cont {
Expand All @@ -33,6 +33,8 @@
text-overflow: ellipsis;
margin-right: 1em;
margin-left: .75em;
border: none;
width: 100%;
}
}
&-btn {
Expand Down
2 changes: 1 addition & 1 deletion src/app/copy/block-copy/block-copy.component.spec.ts
Expand Up @@ -32,7 +32,7 @@ describe('Block Copy component', () => {
componentConfig = {
label: 'Block-level Foobar',
expandToggleAriaLabel: 'Expand Block-level Foobar',
tooltip: 'Block Copy Tooltip',
tooltipText: 'Block Copy Tooltip',
value: 'Token'
};
})
Expand Down
9 changes: 8 additions & 1 deletion src/app/copy/block-copy/block-copy.component.ts
@@ -1,6 +1,7 @@
import {
Component,
Input,
OnInit,
ViewEncapsulation
} from '@angular/core';

Expand Down Expand Up @@ -35,7 +36,7 @@ import { CopyService } from '../copy-service/copy.service';
selector: 'pfng-block-copy',
templateUrl: './block-copy.component.html'
})
export class BlockCopyComponent extends CopyBase {
export class BlockCopyComponent extends CopyBase implements OnInit {
/**
* Label output above the block copy component
*/
Expand Down Expand Up @@ -68,6 +69,12 @@ export class BlockCopyComponent extends CopyBase {
super(copyService);
}

ngOnInit() {
if (!this.buttonAriaLabel && this.buttonLabel) {
this.buttonAriaLabel = this.buttonLabel;
}
}

/**
* Generates a unique ID for the button
*/
Expand Down
Expand Up @@ -3,19 +3,18 @@
<div class="col-sm-8 padding-bottom-15">
<p>This basic example illustrates how you can control various bits of text within the component. Block copy is not intended for use with small strings of text.</p>
<pfng-block-copy
[buttonAriaLabel]="basicEx01.buttonAriaLabel"
[buttonLabel]="basicEx01.buttonLabel"
[buttonAriaLabel]="basicEx01.buttonAriaLabel"
[expandToggleAriaLabel]="basicEx01.expandToggleAriaLabel"
[label]="basicEx01.label"
[tooltip]="basicEx01.tooltip"
[tooltipText]="basicEx01.tooltip"
[value]="basicEx01.value"
(onCopy)="handleCopy($event)"></pfng-block-copy>
</div>
</div>
<div class="row padding-top-10">
<div class="col-sm-12">
<h4 class="actions-label">Actions</h4>
<hr/>
<hr>
</div>
</div>
<div class="row">
Expand Down
Expand Up @@ -3,8 +3,7 @@ import {
OnInit,
ViewEncapsulation
} from '@angular/core';
import {CopyEvent} from '../../copy-event';
import {NotificationType} from '../../../notification/notification-type';
import { CopyEvent } from '../../copy-event';

@Component({
encapsulation: ViewEncapsulation.None,
Expand All @@ -14,7 +13,6 @@ import {NotificationType} from '../../../notification/notification-type';
export class BlockCopyBasicExampleComponent implements OnInit {
actionsText: string = '';
basicEx01 = {
buttonLabel: 'Copy JSON',
buttonAriaLabel: 'Copy Swagger JSON',
expandToggleAriaLabel: 'Toggle Swagger JSON',
label: 'Swagger JSON',
Expand Down
Expand Up @@ -9,13 +9,14 @@
[expanded]="expandedEx01.expanded"
[label]="expandedEx01.label"
[value]="expandedEx01.value"
[width]="expandedEx01.width"
(onCopy)="handleCopy($event)"></pfng-block-copy>
</div>
</div>
<div class="row padding-top-10">
<div class="col-sm-12">
<h4 class="actions-label">Actions</h4>
<hr/>
<hr>
</div>
</div>
<div class="row">
Expand Down
Expand Up @@ -17,7 +17,8 @@ export class BlockCopyExpandedExampleComponent {
expandToggleAriaLabel: 'Toggle GraphQL Query',
expanded: true,
label: 'GraphQL Query',
value: 'query HeroNameAndFriends($episode: Episode) {hero(episode: $episode) {name friends {name}}}'
value: 'query HeroNameAndFriends($episode: Episode) {hero(episode: $episode) {name friends {name}}}',
width: '605px'
};

constructor() {}
Expand Down
Expand Up @@ -8,7 +8,7 @@
[buttonLabel]="cbExConfig.buttonLabel"
[expandToggleAriaLabel]="cbExConfig.expandToggleAriaLabel"
[label]="cbExConfig.label"
[tooltip]="cbExConfig.tooltip"
[tooltipText]="cbExConfig.tooltip"
[value]="cbExConfig.value"
(onCopy)="handleCopy($event, {
name: cbExConfig.buttonAriaLabel,
Expand All @@ -19,7 +19,7 @@
<div class="row padding-top-10">
<div class="col-sm-12">
<h4 class="actions-label">Actions</h4>
<hr/>
<hr>
</div>
</div>
<div class="row">
Expand Down
32 changes: 30 additions & 2 deletions src/app/copy/copy-base.ts
Expand Up @@ -11,6 +11,11 @@ import { CopyService } from './copy-service/copy.service';
* A config containing properties for copy components
*/
export abstract class CopyBase {
protected _copyDefaults = {
copyBtnTooltipText: 'Copy to Clipboard',
tooltipCopiedText: 'Copied'
};

/**
* Copy button aria label (announced to screen readers)
*/
Expand All @@ -19,18 +24,38 @@ export abstract class CopyBase {
/**
* A tooltip that describes the value to be copied
*/
@Input('tooltip') tooltip: string;
@Input('tooltipText') tooltipText: string;

/**
* Placement for the tooltip
*/
@Input('tooltipPlacement') tooltipPlacement: string = 'top';

/**
* A tooltip that describes what the copy button does
*/
@Input('copyBtnTooltipText') copyBtnTooltipText: string = this._copyDefaults.copyBtnTooltipText;

/**
* A tooltip that informs user that copy action recently occurred
*/
@Input('tooltipCopiedText') tooltipCopiedText: string = this._copyDefaults.tooltipCopiedText;

/**
* Placement for the copy button tooltip
*/
@Input('copyBtnTooltipPlacement') copyBtnTooltipPlacement: string = 'top';

/**
* The value to be copied to the clipboard
*/
@Input('value') value: string;

/**
* A width to set on the copy container
*/
@Input('width') width: string;

/**
* Event emitted when values are copied to the clipboard
*/
Expand All @@ -56,14 +81,17 @@ export abstract class CopyBase {
* Copy given value to the clipboard
*/
copy(): void {
let result = this.copyService.copy(this.value);
const result = this.copyService.copy(this.value),
originalCopyBtnTooltipText = this.copyBtnTooltipText;
if (result) {
this.onCopy.emit({
value: this.value
} as CopyEvent);
this._recentlyCopied = true;
this.copyBtnTooltipText = this.tooltipCopiedText || this._copyDefaults.tooltipCopiedText;
setTimeout(() => {
this._recentlyCopied = false;
this.copyBtnTooltipText = originalCopyBtnTooltipText || this._copyDefaults.copyBtnTooltipText;
}, 3000);
}
}
Expand Down
Expand Up @@ -5,7 +5,8 @@
<p>Copy components are accessible via the Form Controls rotor menu in VoiceOver. By default, like in the example below, they are exposed to the rotor menu as "<em>{{'{'}}copyBtnAriaLabel{{'}'}}</em> button". This isn't great from an accessibility standpoint as it doesn't inform the user that it's a <em>copy</em> action that the button performs. Let's fix that.</p>
<pfng-inline-copy
[buttonAriaLabel]="a11yEx01.buttonAriaLabel"
[tooltip]="a11yEx01.tooltip"
[tooltipText]="a11yEx01.tooltip"
[width]="a11yEx01.width"
[value]="a11yEx01.value"
(onCopy)="handleCopy($event, {
name: a11yEx01.buttonAriaLabel,
Expand All @@ -16,7 +17,8 @@
<p>In the example below you'll find the copy button is announced in the format of "Copy <em>{{'{'}}copyBtnAriaLabel{{'}'}}</em> to clipboard button". By providing custom tailored aria label inputs you can ensure the experience you provide to a visually impared user is aligned well with your standard sighted browsing experience.</p>
<pfng-inline-copy
[buttonAriaLabel]="'Copy ' + a11yEx02.buttonAriaLabel + ' to clipboard'"
[tooltip]="a11yEx02.tooltip"
[tooltipText]="a11yEx02.tooltip"
[width]="a11yEx02.width"
[value]="a11yEx02.value"
(onCopy)="handleCopy($event, {
name: a11yEx02.buttonAriaLabel,
Expand Down
Expand Up @@ -22,13 +22,15 @@ export class InlineCopyA11yExampleComponent implements OnInit {
a11yEx01 = {
buttonAriaLabel: 'WAI-ARIA URL',
tooltip: 'ARIA W3C Recommendation',
value: 'https://www.w3.org/TR/wai-aria-1.1/'
value: 'https://www.w3.org/TR/wai-aria-1.1/',
width: '200px'
};

a11yEx02 = {
buttonAriaLabel: 'Example Sparql Query',
tooltip: 'Semantic Triple (SPO)',
value: 'SELECT ?x ?fname WHERE {?x <http://www.w3.org/2001/vcard-rdf/3.0#FN> ?fname}'
value: 'SELECT ?x ?fname WHERE {?x <http://www.w3.org/2001/vcard-rdf/3.0#FN> ?fname}',
width: '420px'
};

constructor(private notificationService: NotificationService) {}
Expand Down
Expand Up @@ -9,8 +9,11 @@
Font size for this component is reduced slightly relative to the surrounding text.
<pfng-inline-copy
[buttonAriaLabel]="basicExConfig.buttonAriaLabel"
[tooltip]="basicExConfig.tooltip"
[tooltipText]="basicExConfig.tooltip"
[value]="basicExConfig.value"
[width]="basicExConfig.width"
[copyBtnTooltipText]="basicExConfig.copyBtnTooltip"
[tooltipCopiedText]="basicExConfig.copiedTxt"
(onCopy)="handleCopy($event)"></pfng-inline-copy>
It is recommended to not repeat the copyValue text for the tooltip as this would be redundant.
Just as with BlockCopy, you have full and independent control over tooltips, aria labels, button labels, and every other piece of text that's displayed as part of this component.
Expand Down
Expand Up @@ -15,7 +15,10 @@ export class InlineCopyBasicExampleComponent implements OnInit {
basicExConfig = {
buttonAriaLabel: 'Copy WAI-ARIA URL',
tooltip: 'ARIA W3C Recommendation',
value: 'https://www.w3.org/TR/wai-aria-1.1/'
value: 'https://www.w3.org/TR/wai-aria-1.1/',
width: '200px',
copyBtnTooltip: 'Copy WAI-ARIA URL',
copiedTxt: 'Copied WAI-ARIA URL to clipboard'
};

constructor() {}
Expand Down
Expand Up @@ -8,6 +8,7 @@
<pfng-inline-copy
[buttonAriaLabel]="wrapExConfig.buttonAriaLabel"
[value]="wrapExConfig.value"
[width]="wrapExConfig.width"
(onCopy)="handleCopy($event)"></pfng-inline-copy>
</div>
</div>
Expand Down
Expand Up @@ -15,7 +15,8 @@ export class InlineCopyWrapExampleComponent implements OnInit {
wrapExConfig = {
buttonAriaLabel: 'Copy JSON+LD Schema Example',
// tslint:disable-next-line:max-line-length
value: '{"@context": "http://json-ld.org/contexts/person.jsonld", "@id": "http://dbpedia.org/resource/John_Lennon", "name": "John Lennon", "born": "1940-10-09", "spouse": "http://dbpedia.org/resource/Cynthia_Lennon"}'
value: '{"@context": "http://json-ld.org/contexts/person.jsonld", "@id": "http://dbpedia.org/resource/John_Lennon", "name": "John Lennon", "born": "1940-10-09", "spouse": "http://dbpedia.org/resource/Cynthia_Lennon"}',
width: '100%'
};

constructor() {}
Expand Down

0 comments on commit b640c9e

Please sign in to comment.