-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(SFINT-3167): Add ActionButton Component (#74)
* feat(SFINT-3167): Add ActionButton component. * feat(SFINT-3167): Improve ActionButton hover style. * chore(SFINT-3167): Fix linting * chore(SFINT-3167): Improve styling rules * feat(SFINT-3167): Add component documentation * feat(SFINT-3167): Improve unit tests Add warning when click handler is not set. Validate expectations using DOM elements instead of internal method calls. * feat(SFINT-3167): Improve init of click option * feat(SFINT-3167): Mark click option as required
- Loading branch information
Showing
6 changed files
with
420 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, height=device-height" /> | ||
<title>Development - Action Button</title> | ||
<link rel="stylesheet" href="../css/CoveoFullSearch.css" /> | ||
<link rel="stylesheet" href="../css/CoveoJsSearchExtensions.css" /> | ||
<script src="../js/CoveoJsSearch.Lazy.js"></script> | ||
<script src="../commonjs/CoveoJsSearchExtensions.js"></script> | ||
<script> | ||
let attachedIds = []; | ||
document.addEventListener('DOMContentLoaded', function() { | ||
Coveo.SearchEndpoint.configureSampleEndpointV2(); | ||
Coveo.init(document.body, {}); | ||
}); | ||
</script> | ||
</head> | ||
|
||
<body id="search" class="CoveoSearchInterface" data-enable-history="false" style="padding: 1em;"> | ||
<span class="CoveoAnalytics"></span> | ||
<div class="coveo-tab-section"> | ||
<a class="CoveoTab" data-id="All" data-caption="All Content"></a> | ||
</div> | ||
<div class="coveo-search-section"> | ||
<div class="CoveoSearchbox" data-enable-omnibox="true"></div> | ||
</div> | ||
|
||
<div> | ||
<h2>Button with icon only</h2> | ||
<br /> | ||
<button | ||
class="CoveoActionButton" | ||
data-icon='<svg width=".5em" height=".5em" viewBox="0 0 20 20"><path d="M4 5h7v1H4V5m0 3h7v1H4V8m0 3h7v1H4v-1"></path><path d="M15 1c.009-.525.066-1-1-1H1.002c-.651 0-1 .33-1 1v15c0 .66.351 1 1 1H3v2c.075.546.383 1 1 1h13c.718 0 1-.295 1-1V3c.001-.468-.406-.99-1-1h-2V1M2 15V2h11v13H2m14 3H5v-.995L14 17c.5.005.976-.428 1-1l.021-12H16v14"></path></svg>' | ||
></button> | ||
</div> | ||
|
||
<div> | ||
<h2>Button with icon and text</h2> | ||
<br /> | ||
<button | ||
class="CoveoActionButton" | ||
data-title="The Text" | ||
data-icon='<svg width=".5em" height=".5em" viewBox="0 0 20 20"><path d="M4 5h7v1H4V5m0 3h7v1H4V8m0 3h7v1H4v-1"></path><path d="M15 1c.009-.525.066-1-1-1H1.002c-.651 0-1 .33-1 1v15c0 .66.351 1 1 1H3v2c.075.546.383 1 1 1h13c.718 0 1-.295 1-1V3c.001-.468-.406-.99-1-1h-2V1M2 15V2h11v13H2m14 3H5v-.995L14 17c.5.005.976-.428 1-1l.021-12H16v14"></path></svg>' | ||
></button> | ||
</div> | ||
|
||
<div> | ||
<h2>Button with text only</h2> | ||
<br /> | ||
<button class="CoveoActionButton" data-title="The Text"></button> | ||
</div> | ||
|
||
<div> | ||
<h2>Multiple buttons</h2> | ||
<br /> | ||
|
||
<div style="display: flex;"> | ||
<button class="CoveoActionButton" data-title="First"></button> | ||
<button class="CoveoActionButton" data-title="Second"></button> | ||
<button class="CoveoActionButton" data-title="Third"></button> | ||
</div> | ||
</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
@import '../../sass/Variables.scss'; | ||
|
||
$primary-color-lightest: #ffffff; | ||
$primary-color-lightest-hover: whitesmoke; | ||
$primary-color-light: #e5e5e5; | ||
$primary-color-dark: #4a4a4a; | ||
$accent-color: $calypso; | ||
|
||
$button-size: 36px; | ||
|
||
button.CoveoActionButton.coveo-actionbutton { | ||
height: $button-size; | ||
border: solid 2px $primary-color-light; | ||
border-radius: 3px; | ||
background-color: $primary-color-lightest; | ||
color: $primary-color-dark; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
white-space: nowrap; | ||
} | ||
|
||
.CoveoActionButton { | ||
&:not(.coveo-actionbutton-icononly) { | ||
padding: 0 16px; | ||
} | ||
|
||
&.coveo-actionbutton-icononly { | ||
width: $button-size; | ||
} | ||
|
||
.coveo-actionbutton_icon { | ||
line-height: 0; | ||
font-size: 16px; | ||
|
||
svg { | ||
height: 1em; | ||
width: 1em; | ||
fill: $primary-color-dark; | ||
} | ||
|
||
+ .coveo-actionbutton_title { | ||
margin-left: 8px; | ||
} | ||
} | ||
|
||
+ .coveo-actionbutton { | ||
margin-left: 5px; | ||
} | ||
} | ||
|
||
.CoveoActionButton.coveo-actionbutton:hover, | ||
.CoveoActionButton.coveo-actionbutton:active { | ||
& { | ||
color: $accent-color; | ||
background-color: $primary-color-lightest-hover; | ||
} | ||
|
||
.coveo-actionbutton_icon svg { | ||
fill: $accent-color; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
import { Component, ComponentOptions, IResultsComponentBindings, Initialization } from 'coveo-search-ui'; | ||
|
||
export interface IActionButtonOptions { | ||
title?: string; | ||
tooltip?: string; | ||
icon?: string; | ||
click?: () => void; | ||
} | ||
|
||
/** | ||
* The _ActionButton_ component is a simple button allowing to show an icon, text, and tooltip. | ||
* | ||
* ```html | ||
* <button class='CoveoActionButton'></button> | ||
* ``` | ||
*/ | ||
export class ActionButton extends Component { | ||
static ID = 'ActionButton'; | ||
|
||
/** | ||
* The possible options for _ActionButton_. | ||
* @componentOptions | ||
*/ | ||
static options: IActionButtonOptions = { | ||
/** | ||
* Specifies the button label. The text is displayed on a single line, next to the icon. | ||
* | ||
* Default is the empty string. | ||
* | ||
* ```html | ||
* <button class='CoveoActionButton' data-title='My Button'></button> | ||
* ``` | ||
*/ | ||
title: ComponentOptions.buildStringOption(), | ||
|
||
/** | ||
* Specifies the button tooltip text. | ||
* | ||
* Default is the empty string. | ||
* | ||
* ```html | ||
* <button class='CoveoActionButton' data-tooltip='My button tooltip'></button> | ||
* ``` | ||
*/ | ||
tooltip: ComponentOptions.buildStringOption(), | ||
|
||
/** | ||
* Specifies the button SVG icon. | ||
* Note: The SVG markup has to be HTML encoded when set using the HTML attributes. | ||
* | ||
* Default is the empty string. | ||
* | ||
* For example, with this SVG markup: | ||
* | ||
* ```xml | ||
* <svg width="1em" height="1em">...</svg> | ||
* ``` | ||
* | ||
* The attribute would be set like this: | ||
* | ||
* ```html | ||
* <button class='CoveoActionButton' data-icon='<svg width="1em" height="1em">...</svg>'></button> | ||
* ``` | ||
*/ | ||
icon: ComponentOptions.buildStringOption(), | ||
|
||
/** | ||
* Specifies the handler called when the button is clicked. | ||
* | ||
* Default is `null`. | ||
* | ||
* This option must be set in JavaScript when initializing the component. | ||
*/ | ||
click: ComponentOptions.buildCustomOption(s => null, { required: true }) | ||
}; | ||
|
||
constructor(public element: HTMLElement, public options: IActionButtonOptions, public bindings?: IResultsComponentBindings) { | ||
super(element, ActionButton.ID, bindings); | ||
|
||
this.options = ComponentOptions.initComponentOptions(element, ActionButton, options); | ||
|
||
if (this.options.icon || this.options.title) { | ||
this.render(); | ||
} else { | ||
console.warn('The action button cannot render since no icon nor title is defined.'); | ||
Coveo.$$(this.element).hide(); | ||
} | ||
|
||
if (this.options.click) { | ||
Coveo.$$(element).on('click', () => this.options.click()); | ||
} | ||
} | ||
|
||
protected render(): void { | ||
this.applyButtonStyles(); | ||
|
||
if (this.options.icon) { | ||
this.appendIcon(); | ||
} | ||
if (this.options.title) { | ||
this.appendTitle(); | ||
} | ||
if (this.options.tooltip) { | ||
this.appendTooltip(); | ||
} | ||
} | ||
|
||
protected applyButtonStyles(): void { | ||
this.element.classList.add('coveo-actionbutton'); | ||
|
||
if (this.options.icon && !this.options.title) { | ||
this.element.classList.add('coveo-actionbutton-icononly'); | ||
} | ||
} | ||
|
||
protected createIconElement(): HTMLElement { | ||
const iconElement = document.createElement('span'); | ||
iconElement.classList.add('coveo-icon', 'coveo-actionbutton_icon'); | ||
iconElement.innerHTML = this.options.icon; | ||
return iconElement; | ||
} | ||
|
||
protected createTitleElement(): HTMLElement { | ||
const titleElement = document.createElement('span'); | ||
titleElement.classList.add('coveo-actionbutton_title'); | ||
titleElement.innerText = this.options.title; | ||
return titleElement; | ||
} | ||
|
||
private appendIcon(): void { | ||
this.element.appendChild(this.createIconElement()); | ||
} | ||
|
||
private appendTitle(): void { | ||
this.element.appendChild(this.createTitleElement()); | ||
} | ||
|
||
private appendTooltip(): void { | ||
this.element.title = this.options.tooltip; | ||
} | ||
} | ||
|
||
Initialization.registerAutoCreateComponent(ActionButton); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.