-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add d2l-navigation-button-icon component #151
Changes from all commits
edbb243
e4bc328
95ec27b
950bc60
f6e5dd8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import '@brightspace-ui/core/components/colors/colors.js'; | ||
import '@brightspace-ui/core/components/icons/icon.js'; | ||
import '@brightspace-ui/core/components/tooltip/tooltip.js'; | ||
import { css, html, LitElement, nothing } from 'lit'; | ||
import { FocusMixin } from '@brightspace-ui/core/mixins/focus-mixin.js'; | ||
import { getUniqueId } from '@brightspace-ui/core/helpers/uniqueId.js'; | ||
import { ifDefined } from 'lit/directives/if-defined.js'; | ||
import { highlightBorderStyles } from './d2l-navigation-styles.js'; | ||
|
||
/** | ||
* Navigation button with an icon and text. | ||
*/ | ||
class NavigationButtonIcon extends FocusMixin(LitElement) { | ||
|
||
static get properties() { | ||
return { | ||
/** | ||
* Disables the button | ||
* @type {boolean} | ||
*/ | ||
disabled: { reflect: true, type: Boolean }, | ||
/** | ||
* REQUIRED: Preset icon key (e.g. "tier1:gear") | ||
* @type {string} | ||
*/ | ||
icon: { type: String }, | ||
/** | ||
* REQUIRED: Text for the button | ||
* @type {string} | ||
*/ | ||
text: { type: String }, | ||
/** | ||
* Visually hides the text but still accessible | ||
* @type {boolean} | ||
*/ | ||
textHidden: { attribute: 'text-hidden', type: Boolean } | ||
}; | ||
} | ||
|
||
static get styles() { | ||
return [highlightBorderStyles, css` | ||
:host { | ||
display: inline-block; | ||
height: 100%; | ||
} | ||
:host([hidden]) { | ||
display: none; | ||
} | ||
button { | ||
align-items: center; | ||
background: transparent; | ||
border: none; | ||
color: var(--d2l-color-ferrite); | ||
cursor: pointer; | ||
font-family: inherit; | ||
font-size: inherit; | ||
height: 100%; | ||
margin: 0; | ||
min-height: 40px; | ||
outline: none; | ||
overflow: visible; | ||
padding: 0; | ||
position: relative; | ||
white-space: nowrap; | ||
} | ||
/* Firefox includes a hidden border which messes up button dimensions */ | ||
button::-moz-focus-inner { | ||
border: 0; | ||
} | ||
button:not([disabled]):hover, | ||
button:not([disabled]):focus { | ||
--d2l-icon-fill-color: var(--d2l-color-celestine); | ||
color: var(--d2l-color-celestine); | ||
outline: none; | ||
} | ||
button[disabled] { | ||
cursor: default; | ||
opacity: 0.5; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These styles are ported over from the |
||
`]; | ||
} | ||
|
||
constructor() { | ||
super(); | ||
this.disabled = false; | ||
this.textHidden = false; | ||
this._buttonId = getUniqueId(); | ||
} | ||
|
||
static get focusElementSelector() { | ||
return 'button'; | ||
} | ||
|
||
render() { | ||
const { ariaLabel, id, text, tooltip } = this._getRenderSettings(); | ||
const highlightBorder = !this.disabled ? html`<span class="d2l-navigation-highlight-border"></span>` : nothing; | ||
return html` | ||
<button id="${ifDefined(id)}" ?disabled="${this.disabled}" aria-label="${ifDefined(ariaLabel)}"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm setting |
||
${highlightBorder} | ||
<d2l-icon icon="${this.icon}"></d2l-icon> | ||
${text} | ||
</button> | ||
${tooltip} | ||
`; | ||
} | ||
|
||
_getRenderSettings() { | ||
if (this.textHidden) { | ||
return { | ||
ariaLabel: this.text, | ||
id: this._buttonId, | ||
text: nothing, | ||
tooltip: html`<d2l-tooltip for="${this._buttonId}" for-type="label">${this.text}</d2l-tooltip>` | ||
}; | ||
} | ||
return { | ||
ariaLabel: undefined, | ||
id: undefined, | ||
text: this.text, | ||
tooltip: nothing | ||
}; | ||
} | ||
|
||
} | ||
|
||
customElements.define('d2l-navigation-button-icon', NavigationButtonIcon); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,9 @@ | ||
import '../d2l-navigation-button.js'; | ||
import '../d2l-navigation-button-close.js'; | ||
import '../d2l-navigation-button-icon.js'; | ||
import '../d2l-navigation-button-notification-icon.js'; | ||
import '../d2l-navigation-link.js'; | ||
import '../d2l-navigation-link-back.js'; | ||
import '../d2l-navigation-link-image.js'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I split the link tests out into |
||
import { expect, fixture, html, oneEvent } from '@open-wc/testing'; | ||
import { getComposedActiveElement } from '@brightspace-ui/core/helpers/focus.js'; | ||
import { runConstructor } from '@brightspace-ui/core/tools/constructor-test-helper.js'; | ||
|
||
describe('Buttons', () => { | ||
|
@@ -74,61 +73,46 @@ describe('Buttons', () => { | |
|
||
}); | ||
|
||
describe('d2l-navigation-link', () => { | ||
describe('d2l-navigation-button-icon', () => { | ||
|
||
describe('accessibility', () => { | ||
|
||
it('default', async() => { | ||
const el = await fixture(html`<d2l-navigation-link href="https://www.d2l.com" text="D2L">D2L</d2l-navigation-link>`); | ||
const el = await fixture(html`<d2l-navigation-button-icon icon="tier3:gear" text="test"></d2l-navigation-button-icon>`); | ||
await expect(el).to.be.accessible(); | ||
}); | ||
|
||
it('focused', async() => { | ||
const el = await fixture(html`<d2l-navigation-link href="https://www.d2l.com" text="D2L">D2L</d2l-navigation-link>`); | ||
setTimeout(() => el.shadowRoot.querySelector('a').focus()); | ||
await oneEvent(el, 'focus'); | ||
it('text hidden', async() => { | ||
const el = await fixture(html`<d2l-navigation-button-icon icon="tier3:gear" text="test" text-hidden></d2l-navigation-button-icon>`); | ||
await expect(el).to.be.accessible(); | ||
}); | ||
|
||
}); | ||
|
||
describe('constructor', () => { | ||
it('should construct', () => { | ||
runConstructor('d2l-navigation-link'); | ||
it('disabled', async() => { | ||
const el = await fixture(html`<d2l-navigation-button-icon icon="tier3:gear" text="test" disabled></d2l-navigation-button-icon>`); | ||
await expect(el).to.be.accessible(); | ||
}); | ||
}); | ||
|
||
}); | ||
|
||
describe('d2l-navigation-link-back', () => { | ||
|
||
describe('accessibility', () => { | ||
it('should pass all aXe tests', async() => { | ||
const el = await fixture(html`<d2l-navigation-link-back href="https://www.d2l.com" text="D2L">D2L</d2l-navigation-link-back>`); | ||
it('focused', async() => { | ||
const el = await fixture(html`<d2l-navigation-button-icon icon="tier3:gear" text="test"></d2l-navigation-button-icon>`); | ||
el.focus(); | ||
const activeElem = getComposedActiveElement(); | ||
expect(activeElem).to.equal(el.shadowRoot.querySelector('button')); | ||
await expect(el).to.be.accessible(); | ||
}); | ||
|
||
}); | ||
|
||
describe('constructor', () => { | ||
it('should construct', () => { | ||
runConstructor('d2l-navigation-link-back'); | ||
runConstructor('d2l-navigation-button-icon'); | ||
}); | ||
}); | ||
|
||
}); | ||
|
||
describe('d2l-navigation-link-image', () => { | ||
|
||
describe('accessibility', () => { | ||
it('should pass all aXe tests', async() => { | ||
const el = await fixture(html`<d2l-navigation-link-image src="../demo/logo-image.png" href="https:/www.d2l.com" text="D2L"></d2l-navigation-link-image>`); | ||
await expect(el).to.be.accessible(); | ||
}); | ||
}); | ||
|
||
describe('constructor', () => { | ||
it('should construct', () => { | ||
runConstructor('d2l-navigation-link-image'); | ||
describe('events', () => { | ||
it('should trigger click event', async() => { | ||
const el = await fixture(html`<d2l-navigation-button-icon icon="tier3:gear" text="test"></d2l-navigation-button-icon>`); | ||
setTimeout(() => el.shadowRoot.querySelector('button').click()); | ||
await oneEvent(el, 'click'); | ||
}); | ||
}); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed this last time around.