diff --git a/src/elements/ia-button/ia-button-story.ts b/src/elements/ia-button/ia-button-story.ts index 35da5e2..e5f8c10 100644 --- a/src/elements/ia-button/ia-button-story.ts +++ b/src/elements/ia-button/ia-button-story.ts @@ -53,6 +53,19 @@ const propInputSettings: PropInputSettings[] = [ inputType: 'radio', radioOptions: ['button', 'submit', 'reset'], }, + { + label: 'Link to attach to button', + propertyName: 'href', + defaultValue: '', + inputType: 'text', + }, + { + label: 'Open link in new tab', + propertyName: 'openLinksNewTab', + defaultValue: false, + inputType: 'radio', + radioOptions: [true, false], + }, ]; const styleInputSettings: StyleInputSettings[] = [ diff --git a/src/elements/ia-button/ia-button.test.ts b/src/elements/ia-button/ia-button.test.ts index 46fb5e9..1d25867 100644 --- a/src/elements/ia-button/ia-button.test.ts +++ b/src/elements/ia-button/ia-button.test.ts @@ -6,7 +6,7 @@ import { IAButton } from './ia-button'; import './ia-button'; describe('IA button', () => { - test('renders a basic button', async () => { + test('renders a basic button by default', async () => { const el = await fixture(html`Submit`); const button = el.shadowRoot?.querySelector('button'); @@ -14,6 +14,38 @@ describe('IA button', () => { expect(button?.disabled).to.equal(false); }); + test('renders a link around the button if href provided', async () => { + const el = await fixture( + html`Go`, + ); + + const link = el.shadowRoot?.querySelector('a'); + expect(link).to.exist; + expect(link?.href).to.equal('https://archive.org/foo'); + }); + + test('includes a target="_blank" if requested', async () => { + const el = await fixture( + html` + Go + `, + ); + + const link = el.shadowRoot?.querySelector('a'); + expect(link).to.exist; + expect(link?.target).to.equal('_blank'); + }); + + test('uses target="_self" for links by default', async () => { + const el = await fixture( + html`Go`, + ); + + const link = el.shadowRoot?.querySelector('a'); + expect(link).to.exist; + expect(link?.target).to.equal('_self'); + }); + test('displays slotted text within button', async () => { const el = await fixture( html`Submit`, diff --git a/src/elements/ia-button/ia-button.ts b/src/elements/ia-button/ia-button.ts index 80d8f67..c450e16 100644 --- a/src/elements/ia-button/ia-button.ts +++ b/src/elements/ia-button/ia-button.ts @@ -52,15 +52,21 @@ export class IAButton extends LitElement { | 'submit' | 'reset' = 'button'; + /* An optional href to wrap around the button */ + @property({ type: String }) href?: string; + + /* Whether to add a target="_blank" to any wrapping link */ + @property({ type: Boolean }) openLinksNewTab: boolean = false; + render(): TemplateResult { return html` - + ${this.href + ? html`${this.buttonTemplate}` + : this.buttonTemplate} `; } @@ -71,6 +77,24 @@ export class IAButton extends LitElement { } } + /* The native button to render */ + private get buttonTemplate(): TemplateResult { + return html` + + `; + } + + /* The text to render within the button */ + private get buttonTextTemplate(): TemplateResult { + return this.loading ? this.loadingStateTemplate : html``; + } + /* Content to render while button is loading */ private get loadingStateTemplate(): TemplateResult { return html` @@ -264,6 +288,10 @@ export class IAButton extends LitElement { -o-user-select: none; } + a { + text-decoration: none; + } + button:disabled, button.disabled { cursor: not-allowed;