Custom button cleanup & toolbar button styles (#1794)

Closes https://github.com/webrecorder/browsertrix/issues/1791



https://github.com/webrecorder/browsertrix/assets/5727389/54a4d9a2-9e68-4cbd-9cef-8a73a6106043

| Screenshots |
| --- |
| <img width="145" alt="Screenshot 2024-05-08 at 6 13 53 PM"
src="https://github.com/webrecorder/browsertrix/assets/5727389/35efd4b5-2a59-4fd2-8a62-904eedad98f9">
|
This commit is contained in:
Emma Segal-Grossman 2024-05-21 13:28:41 -04:00 committed by GitHub
parent e853b62401
commit 040d1b70d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 80 additions and 49 deletions

View File

@ -1,5 +1,6 @@
/* eslint-disable lit/binding-positions */ /* eslint-disable lit/binding-positions */
/* eslint-disable lit/no-invalid-html */ /* eslint-disable lit/no-invalid-html */
import clsx from "clsx";
import { css } from "lit"; import { css } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
@ -8,6 +9,8 @@ import { html, literal } from "lit/static-html.js";
import { TailwindElement } from "@/classes/TailwindElement"; import { TailwindElement } from "@/classes/TailwindElement";
import { tw } from "@/utils/tailwind"; import { tw } from "@/utils/tailwind";
type Variant = "neutral" | "danger";
/** /**
* Custom styled button * Custom styled button
* *
@ -21,8 +24,18 @@ export class Button extends TailwindElement {
@property({ type: String }) @property({ type: String })
type: "submit" | "button" = "button"; type: "submit" | "button" = "button";
// TODO unify button styling & variants - there are probably a few different
// approaches for difference button use cases, but we'll figure that out in
// the future when we work more on our UI library.
// See also https://github.com/webrecorder/browsertrix/issues/1550
@property({ type: String }) @property({ type: String })
variant: "primary" | "danger" | "neutral" = "neutral"; variant: Variant = "neutral";
@property({ type: Boolean })
filled = false;
@property({ type: String })
size: "small" | "medium" = "medium";
@property({ type: String }) @property({ type: String })
label?: string; label?: string;
@ -39,9 +52,6 @@ export class Button extends TailwindElement {
@property({ type: Boolean }) @property({ type: Boolean })
loading = false; loading = false;
@property({ type: Boolean })
icon = false;
static styles = css` static styles = css`
:host { :host {
display: inline-block; display: inline-block;
@ -57,18 +67,28 @@ export class Button extends TailwindElement {
const tag = this.href ? literal`a` : literal`button`; const tag = this.href ? literal`a` : literal`button`;
return html`<${tag} return html`<${tag}
type=${this.type === "submit" ? "submit" : "button"} type=${this.type === "submit" ? "submit" : "button"}
class=${[ class=${clsx(
tw`flex h-6 cursor-pointer items-center justify-center gap-2 rounded-sm text-center font-medium transition-all disabled:cursor-not-allowed disabled:text-neutral-300`, tw`flex h-6 cursor-pointer items-center justify-center gap-2 text-center font-medium outline-3 outline-offset-1 outline-primary transition focus-visible:outline disabled:cursor-not-allowed disabled:text-neutral-300`,
this.icon ? tw`min-h-8 min-w-8 px-1` : tw`h-6 px-2`, this.size === "medium"
this.raised ? tw`shadow-sm` : "", ? tw`min-h-8 min-w-8 rounded-sm`
{ : tw`min-h-6 min-w-6 rounded-md`,
primary: tw`bg-blue-50 text-blue-600 shadow-blue-800/20 hover:bg-blue-100`, this.raised && tw`border shadow-sm`,
danger: tw`shadow-danger-800/20 bg-danger-50 text-danger-600 hover:bg-danger-100`, this.filled
neutral: tw`text-neutral-600 hover:text-blue-600`, ? [
}[this.variant], tw`text-white`,
] {
.filter(Boolean) neutral: tw`border-primary-800 bg-primary-500 shadow-primary-800/20 hover:bg-primary-600`,
.join(" ")} danger: tw`shadow-danger-800/20 border-danger-800 bg-danger-500 hover:bg-danger-600`,
}[this.variant],
]
: [
this.raised && tw`bg-white`,
{
neutral: tw`border-gray-300 text-gray-600 hover:text-primary-600`,
danger: tw`shadow-danger-800/20 border-danger-300 bg-danger-50 text-danger-600 hover:bg-danger-100`,
}[this.variant],
],
)}
?disabled=${this.disabled} ?disabled=${this.disabled}
href=${ifDefined(this.href)} href=${ifDefined(this.href)}
aria-label=${ifDefined(this.label)} aria-label=${ifDefined(this.label)}

View File

@ -60,12 +60,18 @@ export class CopyButton extends LitElement {
@sl-hide=${this.stopProp} @sl-hide=${this.stopProp}
@sl-after-hide=${this.stopProp} @sl-after-hide=${this.stopProp}
> >
<sl-icon-button <btrix-button
name=${this.isCopied ? "check-lg" : this.name ? this.name : "copy"} size="small"
label=${msg("Copy to clipboard")}
@click=${this.onClick} @click=${this.onClick}
?disabled=${!this.value && !this.getValue} ?disabled=${!this.value && !this.getValue}
></sl-icon-button> class="inline"
raised
>
<sl-icon
name=${this.isCopied ? "check-lg" : this.name ? this.name : "copy"}
label=${msg("Copy to clipboard")}
></sl-icon>
</btrix-button>
</sl-tooltip> </sl-tooltip>
`; `;
} }

View File

@ -1,9 +1,10 @@
import { localized } from "@lit/localize"; import { localized } from "@lit/localize";
import clsx from "clsx";
import { css, html } from "lit"; import { css, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property, queryAssignedNodes } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { TailwindElement } from "@/classes/TailwindElement"; import { TailwindElement } from "@/classes/TailwindElement";
import { tw } from "@/utils/tailwind";
/** /**
* Copy text to clipboard on click * Copy text to clipboard on click
@ -49,26 +50,27 @@ export class CopyField extends TailwindElement {
} }
`; `;
get _slottedChildren() { @queryAssignedNodes({ slot: "label" })
const slot = this.shadowRoot?.querySelector("slot[name=label]"); private readonly slottedChildren: Element[] | undefined;
return (slot as HTMLSlotElement | null | undefined)?.assignedElements();
}
render() { render() {
return html` return html`
<div role="group"> <div
role="group"
class=${clsx(
tw`rounded border`,
this.filled && tw`bg-slate-50`,
this.monostyle && tw`font-monostyle`,
)}
>
<label <label
class="${classMap({ class="${clsx(
hidden: !this.label && !this._slottedChildren, "mb-1.5 inline-block font-sans text-xs leading-[1.4] text-neutral-800",
})} mb-1.5 inline-block font-sans text-xs leading-[1.4] text-neutral-800" !this.label && !this.slottedChildren?.length && tw`hidden`,
)} "
><slot name="label">${this.label}</slot></label ><slot name="label">${this.label}</slot></label
> >
<div <div class="relative inline-flex w-full items-stretch justify-start">
class="${classMap({
"bg-slate-50": this.filled,
"font-monostyle": this.monostyle,
})} relative inline-flex w-full items-stretch justify-start rounded border"
>
<slot name="prefix"></slot> <slot name="prefix"></slot>
<span <span
aria-hidden=${this.hideContentFromScreenReaders} aria-hidden=${this.hideContentFromScreenReaders}
@ -82,6 +84,7 @@ export class CopyField extends TailwindElement {
.content=${this.buttonContent} .content=${this.buttonContent}
.getValue=${this.getValue} .getValue=${this.getValue}
.hoist=${this.hoist} .hoist=${this.hoist}
class="m-1 flex"
></btrix-copy-button> ></btrix-copy-button>
</div> </div>
</div> </div>

View File

@ -147,11 +147,10 @@ export class QueueExclusionForm extends LiteElement {
: ""} : ""}
</sl-input> </sl-input>
</div> </div>
<div class="flex-0 w-10 pt-1 text-center"> <div class="flex-0 w-10 text-center">
<btrix-button <btrix-button
variant="primary" variant="neutral"
raised raised
icon
?disabled=${!this.inputValue || ?disabled=${!this.inputValue ||
this.isRegexInvalid || this.isRegexInvalid ||
this.isSubmitting} this.isSubmitting}

View File

@ -872,11 +872,14 @@ export class ArchivedItemQA extends TailwindElement {
placement="bottom-start" placement="bottom-start"
> >
<btrix-button <btrix-button
icon raised
variant=${!this.splitView ? "primary" : "neutral"} ?filled=${!this.splitView}
size="small"
@click="${() => (this.splitView = !this.splitView)}" @click="${() => (this.splitView = !this.splitView)}"
class="m-0.5"
aria-pressed=${!this.splitView}
> >
<sl-icon name="vr" label=${msg("Split view")}></sl-icon> <sl-icon name="vr"></sl-icon>
</btrix-button> </btrix-button>
</sl-tooltip> </sl-tooltip>
</div> </div>

View File

@ -300,12 +300,14 @@ export class CollectionDetail extends LiteElement {
class="mb-2" class="mb-2"
.value="${publicReplayUrl}" .value="${publicReplayUrl}"
hideContentFromScreenReaders hideContentFromScreenReaders
hoist
> >
<sl-tooltip slot="prefix" content=${msg("Open in New Tab")}> <sl-tooltip slot="prefix" content=${msg("Open in New Tab")} hoist>
<sl-icon-button <sl-icon-button
href=${publicReplayUrl} href=${publicReplayUrl}
name="box-arrow-up-right" name="box-arrow-up-right"
target="_blank" target="_blank"
class="m-px"
> >
</sl-icon-button> </sl-icon-button>
</sl-tooltip> </sl-tooltip>
@ -323,12 +325,11 @@ export class CollectionDetail extends LiteElement {
</p> </p>
<div class="relative mb-5 rounded border bg-slate-50 p-3 pr-9"> <div class="relative mb-5 rounded border bg-slate-50 p-3 pr-9">
<btrix-code value=${embedCode}></btrix-code> <btrix-code value=${embedCode}></btrix-code>
<div <div class="absolute right-1 top-1">
class="absolute right-1.5 top-1.5 rounded border bg-white shadow-sm"
>
<btrix-copy-button <btrix-copy-button
.getValue=${() => embedCode} .getValue=${() => embedCode}
content=${msg("Copy Embed Code")} content=${msg("Copy Embed Code")}
hoist
></btrix-copy-button> ></btrix-copy-button>
</div> </div>
</div> </div>
@ -340,12 +341,11 @@ export class CollectionDetail extends LiteElement {
</p> </p>
<div class="relative mb-5 rounded border bg-slate-50 p-3 pr-9"> <div class="relative mb-5 rounded border bg-slate-50 p-3 pr-9">
<btrix-code language="javascript" value=${importCode}></btrix-code> <btrix-code language="javascript" value=${importCode}></btrix-code>
<div <div class="absolute right-1 top-1">
class="absolute right-1.5 top-1.5 rounded border bg-white shadow-sm"
>
<btrix-copy-button <btrix-copy-button
.getValue=${() => importCode} .getValue=${() => importCode}
content=${msg("Copy JS")} content=${msg("Copy JS")}
hoist
></btrix-copy-button> ></btrix-copy-button>
</div> </div>
</div> </div>