Refactor collections and browser profile data-tables (#1505)

- Updates browser profile list styles to match other data table styles
- Makes entire collection item clickable
- Refactors row click area to fix text overflow
This commit is contained in:
sua yoo 2024-01-30 19:46:42 -08:00 committed by GitHub
parent 15e410daa1
commit 79645b64fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 204 additions and 196 deletions

View File

@ -1,7 +1,12 @@
import { LitElement, html, css } from "lit"; import { LitElement, html, css } from "lit";
import { customElement, state, queryAssignedElements } from "lit/decorators.js"; import {
customElement,
state,
queryAssignedElements,
query,
} from "lit/decorators.js";
import { msg, localized } from "@lit/localize"; import { msg, localized } from "@lit/localize";
import type { SlMenu } from "@shoelace-style/shoelace"; import type { SlDropdown, SlMenu } from "@shoelace-style/shoelace";
/** /**
* Dropdown for additional actions. * Dropdown for additional actions.
@ -34,12 +39,15 @@ export class OverflowDropdown extends LitElement {
@state() @state()
private hasMenuItems?: boolean; private hasMenuItems?: boolean;
@query("sl-dropdown")
private dropdown?: SlDropdown;
@queryAssignedElements({ selector: "sl-menu", flatten: true }) @queryAssignedElements({ selector: "sl-menu", flatten: true })
private menu!: Array<SlMenu>; private menu!: Array<SlMenu>;
render() { render() {
return html` return html`
<sl-dropdown ?disabled=${!this.hasMenuItems}> <sl-dropdown ?disabled=${!this.hasMenuItems} hoist>
<sl-icon-button <sl-icon-button
slot="trigger" slot="trigger"
class="trigger" class="trigger"
@ -54,4 +62,8 @@ export class OverflowDropdown extends LitElement {
</sl-dropdown> </sl-dropdown>
`; `;
} }
hide() {
this.dropdown?.hide();
}
} }

View File

@ -40,23 +40,22 @@ export class TableCell extends LitElement {
role = "cell"; role = "cell";
@property({ type: String }) @property({ type: String })
rowClickTarget?: (typeof ALLOWED_ROW_CLICK_TARGET_TAG)[number] | "" = ""; rowClickTarget?: (typeof ALLOWED_ROW_CLICK_TARGET_TAG)[number];
render() { render() {
return html`${this.rowClickTarget && return html`<slot @slotchange=${this.handleSlotChange}></slot>`;
ALLOWED_ROW_CLICK_TARGET_TAG.includes(this.rowClickTarget)
? html`<style>
:host {
display: grid;
grid-template-columns: subgrid;
} }
::slotted(${unsafeCSS(this.rowClickTarget)}) { private handleSlotChange(e: Event) {
position: absolute; if (!this.rowClickTarget) return;
inset: 0; const elems = (e.target as HTMLSlotElement).assignedElements();
grid-column: clickable-start / clickable-end; const rowClickTarget = elems.find(
} (el) => el.tagName.toLowerCase() === this.rowClickTarget
</style>` );
: nothing} <slot></slot>`;
if (!rowClickTarget) return;
// Styled in table.css
rowClickTarget.classList.add("rowClickTarget");
} }
} }

View File

@ -11,6 +11,7 @@ export class TableRow extends LitElement {
grid-column: var(--btrix-table-grid-column); grid-column: var(--btrix-table-grid-column);
display: grid; display: grid;
grid-template-columns: subgrid; grid-template-columns: subgrid;
position: relative;
} }
`; `;

View File

@ -0,0 +1,24 @@
btrix-table-cell[rowClickTarget] {
display: grid;
grid-template-columns: subgrid;
white-space: nowrap;
overflow: hidden;
}
.rowClickTarget {
max-width: 100%;
}
.rowClickTarget::after {
content: "";
display: block;
position: absolute;
inset: 0;
grid-column: clickable-start / clickable-end;
}
.rowClickTarget:focus-visible {
outline: var(--sl-focus-ring);
outline-offset: -0.25rem;
border-radius: 0.5rem;
}

View File

@ -6,9 +6,18 @@ import {
queryAssignedElements, queryAssignedElements,
} from "lit/decorators.js"; } from "lit/decorators.js";
import { TailwindElement } from "@/classes/TailwindElement"; import { theme } from "@/theme";
import tableCSS from "./table.stylesheet.css";
import { type TableHead } from "./table-head"; import { type TableHead } from "./table-head";
// Add table CSS to theme CSS to make it available throughout the app,
// to both shadow and light dom components.
// TODO Remove once all `LiteElement`s are migrated over to `TailwindElement`
tableCSS.split("}").forEach((rule: string) => {
if (!rule.trim()) return;
theme.insertRule(`${rule}}`);
});
/** /**
* Low-level component for displaying content as a table. * Low-level component for displaying content as a table.
* To style tables, use TailwindCSS utility classes. * To style tables, use TailwindCSS utility classes.
@ -46,7 +55,7 @@ import { type TableHead } from "./table-head";
* @cssproperty --btrix-cell-padding-bottom * @cssproperty --btrix-cell-padding-bottom
*/ */
@customElement("btrix-table") @customElement("btrix-table")
export class Table extends TailwindElement { export class Table extends LitElement {
static styles = css` static styles = css`
:host { :host {
--btrix-cell-gap: 0; --btrix-cell-gap: 0;

View File

@ -6,15 +6,14 @@ import {
queryAssignedElements, queryAssignedElements,
query, query,
} from "lit/decorators.js"; } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { msg, localized, str } from "@lit/localize"; import { msg, localized, str } from "@lit/localize";
import { type SlCheckbox } from "@shoelace-style/shoelace";
import { TailwindElement } from "@/classes/TailwindElement"; import { TailwindElement } from "@/classes/TailwindElement";
import type { ArchivedItem } from "@/types/crawler"; import type { ArchivedItem } from "@/types/crawler";
import { renderName } from "@/utils/crawler"; import { renderName } from "@/utils/crawler";
import { NavigateController } from "@/controllers/navigate"; import { NavigateController } from "@/controllers/navigate";
import { type SlCheckbox } from "@shoelace-style/shoelace";
const NAME_WIDTH_CSS = css`26rem`;
export type CheckboxChangeEventDetail = { export type CheckboxChangeEventDetail = {
checked: boolean; checked: boolean;
@ -38,29 +37,8 @@ export class ArchivedItemListItem extends TailwindElement {
border-radius: var(--btrix-border-radius-top, 0) border-radius: var(--btrix-border-radius-top, 0)
var(--btrix-border-radius-to, 0) var(--btrix-border-radius-bottom, 0) var(--btrix-border-radius-to, 0) var(--btrix-border-radius-bottom, 0)
var(--btrix-border-radius-bottom, 0); var(--btrix-border-radius-bottom, 0);
position: relative;
height: 2.5rem; height: 2.5rem;
} }
/*
* TODO consolidate data-table variations
* https://github.com/webrecorder/browsertrix-cloud/issues/1504
*/
btrix-table-cell {
overflow: hidden;
white-space: nowrap;
}
.clickLabel {
width: ${NAME_WIDTH_CSS};
display: flex;
gap: var(--btrix-cell-gap, 0);
align-items: center;
height: 100%;
box-sizing: border-box;
padding: var(--btrix-cell-padding-top) var(--btrix-cell-padding-right)
var(--btrix-cell-padding-bottom) var(--btrix-cell-padding-left);
}
`; `;
@property({ type: Object }) @property({ type: Object })
@ -87,7 +65,7 @@ export class ArchivedItemListItem extends TailwindElement {
if (!this.item) return; if (!this.item) return;
const checkboxId = `${this.item.id}-checkbox`; const checkboxId = `${this.item.id}-checkbox`;
const rowName = html` const rowName = html`
<div class="clickLabel"> <div class="flex items-center gap-3">
<slot name="namePrefix"></slot> <slot name="namePrefix"></slot>
${renderName(this.item)} ${renderName(this.item)}
</div> </div>
@ -122,7 +100,9 @@ export class ArchivedItemListItem extends TailwindElement {
` `
: nothing} : nothing}
<btrix-table-cell <btrix-table-cell
rowClickTarget=${this.href ? "a" : this.checkbox ? "label" : ""} rowClickTarget=${ifDefined(
this.href ? "a" : this.checkbox ? "label" : undefined
)}
> >
${this.href ${this.href
? html`<a href=${this.href} @click=${this.navigate.link}> ? html`<a href=${this.href} @click=${this.navigate.link}>
@ -225,7 +205,7 @@ export class ArchivedItemList extends TailwindElement {
btrix-table { btrix-table {
grid-template-columns: ${`${ grid-template-columns: ${`${
this.hasCheckboxCell ? "min-content" : "" this.hasCheckboxCell ? "min-content" : ""
} [clickable-start] ${NAME_WIDTH_CSS} 12rem 1fr 1fr 1fr [clickable-end] ${ } [clickable-start] 60ch 12rem 1fr 1fr 30ch [clickable-end] ${
this.hasActionCell ? "min-content" : "" this.hasActionCell ? "min-content" : ""
}`.trim()}; }`.trim()};
} }

View File

@ -19,6 +19,7 @@ import {
query, query,
queryAssignedElements, queryAssignedElements,
} from "lit/decorators.js"; } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { msg, localized, str } from "@lit/localize"; import { msg, localized, str } from "@lit/localize";
import { RelativeDuration } from "@/components/ui/relative-duration"; import { RelativeDuration } from "@/components/ui/relative-duration";
@ -28,8 +29,6 @@ import { renderName } from "@/utils/crawler";
import { TailwindElement } from "@/classes/TailwindElement"; import { TailwindElement } from "@/classes/TailwindElement";
import { NavigateController } from "@/controllers/navigate"; import { NavigateController } from "@/controllers/navigate";
const NAME_WIDTH_CSS = css`16rem`;
/** /**
* @slot menu * @slot menu
*/ */
@ -46,28 +45,6 @@ export class CrawlListItem extends TailwindElement {
border-radius: var(--btrix-border-radius-top, 0) border-radius: var(--btrix-border-radius-top, 0)
var(--btrix-border-radius-to, 0) var(--btrix-border-radius-bottom, 0) var(--btrix-border-radius-to, 0) var(--btrix-border-radius-bottom, 0)
var(--btrix-border-radius-bottom, 0); var(--btrix-border-radius-bottom, 0);
position: relative;
}
/*
* TODO consolidate data-table variations
* https://github.com/webrecorder/browsertrix-cloud/issues/1504
*/
btrix-table-cell {
overflow: hidden;
white-space: nowrap;
}
.clickLabel {
width: ${NAME_WIDTH_CSS};
overflow: hidden;
display: flex;
gap: var(--btrix-cell-gap, 0);
align-items: center;
height: 100%;
box-sizing: border-box;
padding: var(--btrix-cell-padding-top) var(--btrix-cell-padding-right)
var(--btrix-cell-padding-bottom) var(--btrix-cell-padding-left);
} }
`; `;
@ -102,7 +79,7 @@ export class CrawlListItem extends TailwindElement {
if (this.workflowId) { if (this.workflowId) {
const label = html` const label = html`
<div class="clickLabel"> <div>
${this.safeRender( ${this.safeRender(
(crawl) => html` (crawl) => html`
<sl-format-date <sl-format-date
@ -118,7 +95,9 @@ export class CrawlListItem extends TailwindElement {
</div> </div>
`; `;
idCell = html` idCell = html`
<btrix-table-cell rowClickTarget=${this.href ? "a" : ""}> <btrix-table-cell
rowClickTarget=${ifDefined(this.href ? "a" : undefined)}
>
${this.href ${this.href
? html`<a href=${this.href} @click=${this.navigate.link}> ? html`<a href=${this.href} @click=${this.navigate.link}>
${label} ${label}
@ -320,7 +299,7 @@ export class CrawlList extends TailwindElement {
btrix-table { btrix-table {
grid-template-columns: grid-template-columns:
min-content [clickable-start] min-content [clickable-start]
${this.workflowId ? "" : `${NAME_WIDTH_CSS} `}${NAME_WIDTH_CSS} auto ${this.workflowId ? "" : `auto `}auto auto
auto auto auto auto [clickable-end] min-content; auto auto auto auto [clickable-end] min-content;
} }
</style> </style>

View File

@ -8,6 +8,7 @@ import type { Profile } from "./types";
import type { APIPaginatedList } from "@/types/api"; import type { APIPaginatedList } from "@/types/api";
import type { SelectNewDialogEvent } from "./index"; import type { SelectNewDialogEvent } from "./index";
import type { Browser } from "@/types/browser"; import type { Browser } from "@/types/browser";
import { nothing } from "lit";
/** /**
* Usage: * Usage:
@ -54,133 +55,129 @@ export class BrowserProfilesList extends LiteElement {
</sl-button> </sl-button>
</div> </div>
</header> </header>
<div class="overflow-auto pb-1 px-2">${this.renderTable()}</div>`;
${this.renderTable()}`;
} }
private renderTable() { private renderTable() {
return html` return html`
<div role="table"> <btrix-table
<div class="mb-2 px-1" role="rowgroup"> style="grid-template-columns: min-content [clickable-start] 60ch repeat(2, auto) [clickable-end] min-content; --btrix-cell-padding-left: var(--sl-spacing-x-small); --btrix-cell-padding-right: var(--sl-spacing-x-small);"
<div
class="hidden md:grid grid-cols-8 gap-3 md:gap-5 text-sm text-neutral-500"
role="row"
> >
<div class="col-span-3 px-2" role="columnheader" aria-sort="none"> <btrix-table-head class="mb-2">
${msg("Description")} <btrix-table-header-cell>
</div> <span class="sr-only">${msg("Backed up status")}</span>
<div class="col-span-1 px-2" role="columnheader" aria-sort="none"> </btrix-table-header-cell>
${msg("Created")} <btrix-table-header-cell class="pl-0">
</div> ${msg("Name")}
<div class="col-span-2 px-2" role="columnheader" aria-sort="none"> </btrix-table-header-cell>
<btrix-table-header-cell>
${msg("Date Created")}
</btrix-table-header-cell>
<btrix-table-header-cell>
${msg("Visited URLs")} ${msg("Visited URLs")}
</div> </btrix-table-header-cell>
</div> <btrix-table-header-cell>
</div> <span class="sr-only">${msg("Row Actions")}</span>
${this.browserProfiles </btrix-table-header-cell>
? this.browserProfiles.length </btrix-table-head>
? html`<div class="border rounded" role="rowgroup"> ${this.browserProfiles?.length
${this.browserProfiles.map(this.renderItem.bind(this))} ? html`
</div>` <btrix-table-body
style="--btrix-row-gap: var(--sl-spacing-x-small); --btrix-cell-padding-top: var(--sl-spacing-2x-small); --btrix-cell-padding-bottom: var(--sl-spacing-2x-small);"
>
${this.browserProfiles.map(this.renderItem)}
</btrix-table-body>
`
: nothing}
</btrix-table>
${this.browserProfiles?.length
? nothing
: html` : html`
<div class="border-t border-b py-5"> <div class="border-t border-b py-5">
<p class="text-center text-0-500"> <p class="text-center text-0-500">
${msg("No browser profiles yet.")} ${msg("No browser profiles yet.")}
</p> </p>
</div> </div>
` `}
: ""}
</div>
`; `;
} }
private renderItem(data: Profile) { private renderItem = (data: Profile) => {
const isBackedUp = data.resource && data.resource.replicas.length > 0;
return html` return html`
<btrix-table-row
class="border rounded cursor-pointer select-none transition-all shadow hover:shadow-none hover:bg-neutral-50 focus-within:bg-neutral-50"
>
<btrix-table-cell class="p-3">
<sl-tooltip
content=${isBackedUp ? msg("Backed up") : msg("Not backed up")}
>
<sl-icon
name=${isBackedUp ? "clouds" : "cloud-slash"}
class="${isBackedUp ? "text-success" : "text-neutral-500"}"
></sl-icon>
</sl-tooltip>
</btrix-table-cell>
<btrix-table-cell
class="flex-col items-start justify-center pl-0"
rowClickTarget="a"
>
<a <a
class="block p-1 leading-none hover:bg-zinc-50 hover:text-primary border-t first:border-t-0 transition-colors" class="flex items-center gap-3"
href=${`${this.orgBasePath}/browser-profiles/profile/${data.id}`} href=${`${this.orgBasePath}/browser-profiles/profile/${data.id}`}
@click=${this.navLink} @click=${this.navLink}
title=${data.name}
> >
<div class="grid grid-cols-8 gap-3 md:gap-5" role="row"> ${data.name}
<div class="col-span-8 md:col-span-3 p-2" role="cell"> </a>
<div class="font-medium text-sm"> <div class="text-xs text-neutral-500 w-full">
<span>${data.name}</span> <div class="truncate">
${when( ${data.description} ${data.description} ${data.description}
data.resource && data.resource.replicas.length > 0, ${data.description} ${data.description} ${data.description}
() => html` <sl-tooltip content=${msg("Backed up")}>
<sl-icon
name="clouds"
class="w-4 h-4 ml-2 align-text-bottom text-success"
></sl-icon>
</sl-tooltip>`
)}
</div>
<div class="text-sm truncate" title=${data.description}>
${data.description} ${data.description}
</div> </div>
</div> </div>
<div class="col-span-8 md:col-span-1 p-2 text-sm" role="cell"> </btrix-table-cell>
${new Date(data.created).toLocaleDateString()} <btrix-table-cell class="whitespace-nowrap">
</div> <sl-format-date
<div class="col-span-7 md:col-span-3 p-2 text-sm" role="cell"> date=${`${data.created}Z`}
${data.origins.join(", ")} month="2-digit"
</div> day="2-digit"
<div class="col-span-1 md:col-span-1 flex items-center justify-end"> year="2-digit"
${this.renderMenu(data)} hour="2-digit"
</div> minute="2-digit"
</div> ></sl-format-date>
</a> </btrix-table-cell>
`; <btrix-table-cell>${data.origins.join(", ")}</btrix-table-cell>
} <btrix-table-cell class="px-1"
>${this.renderActions(data)}</btrix-table-cell
private renderMenu(data: Profile) {
return html`
<sl-dropdown hoist @click=${(e: Event) => e.preventDefault()}>
<sl-icon-button
slot="trigger"
name="three-dots"
label=${msg("Actions")}
style="font-size: 1rem"
></sl-icon-button>
<ul
class="text-sm text-neutral-800 bg-white whitespace-nowrap"
role="menu"
> >
<li </btrix-table-row>
class="p-2 hover:bg-zinc-100 cursor-pointer" `;
role="menuitem" };
private renderActions(data: Profile) {
return html`
<btrix-overflow-dropdown @click=${(e: Event) => e.preventDefault()}>
<sl-menu>
<sl-menu-item
@click=${(e: any) => { @click=${(e: any) => {
this.duplicateProfile(data); this.duplicateProfile(data);
e.target.closest("sl-dropdown").hide();
}} }}
> >
<sl-icon <sl-icon slot="prefix" name="files"></sl-icon>
class="inline-block align-middle px-1" ${msg("Duplicate profile")}
name="files" </sl-menu-item>
></sl-icon> <sl-menu-item
<span class="inline-block align-middle pr-2" style="--sl-color-neutral-700: var(--danger)"
>${msg("Duplicate profile")}</span
>
</li>
<li
class="p-2 text-danger hover:bg-danger hover:text-white cursor-pointer"
role="menuitem"
@click=${(e: any) => { @click=${(e: any) => {
// Close dropdown before deleting template
e.target.closest("sl-dropdown").hide();
this.deleteProfile(data); this.deleteProfile(data);
}} }}
> >
<sl-icon <sl-icon slot="prefix" name="trash3"></sl-icon>
class="inline-block align-middle px-1" ${msg("Delete")}
name="trash3" </sl-menu-item>
></sl-icon> </sl-menu>
<span class="inline-block align-middle pr-2">${msg("Delete")}</span> </btrix-overflow-dropdown>
</li>
</ul>
</sl-dropdown>
`; `;
} }

View File

@ -15,6 +15,7 @@ import type { Collection, CollectionSearchValues } from "@/types/collection";
import type { CollectionSavedEvent } from "@/features/collections/collection-metadata-dialog"; import type { CollectionSavedEvent } from "@/features/collections/collection-metadata-dialog";
import noCollectionsImg from "~assets/images/no-collections-found.webp"; import noCollectionsImg from "~assets/images/no-collections-found.webp";
import type { SelectNewDialogEvent } from "./index"; import type { SelectNewDialogEvent } from "./index";
import type { OverflowDropdown } from "@/components/ui/overflow-dropdown";
type Collections = APIPaginatedList<Collection>; type Collections = APIPaginatedList<Collection>;
type SearchFields = "name"; type SearchFields = "name";
@ -151,7 +152,9 @@ export class CollectionsList extends LiteElement {
> >
${this.renderControls()} ${this.renderControls()}
</div> </div>
<div class="overflow-auto pb-1 px-2">
${guard([this.collections], this.renderList)} ${guard([this.collections], this.renderList)}
</div>
` `
: this.renderLoading() : this.renderLoading()
)} )}
@ -391,7 +394,7 @@ export class CollectionsList extends LiteElement {
if (this.collections?.items.length) { if (this.collections?.items.length) {
return html` return html`
<btrix-table <btrix-table
style="grid-template-columns: min-content 24rem repeat(3, 1fr) 12rem min-content" style="grid-template-columns: min-content [clickable-start] 60ch repeat(3, 1fr) 12rem [clickable-end] min-content"
> >
<btrix-table-head class="mb-2"> <btrix-table-head class="mb-2">
<btrix-table-header-cell> <btrix-table-header-cell>
@ -485,7 +488,9 @@ export class CollectionsList extends LiteElement {
private renderItem = (col: Collection) => private renderItem = (col: Collection) =>
html` html`
<btrix-table-row class="border rounded"> <btrix-table-row
class="border rounded cursor-pointer select-none transition-all shadow hover:shadow-none hover:bg-neutral-50 focus-within:bg-neutral-50"
>
<btrix-table-cell class="p-3"> <btrix-table-cell class="p-3">
${col?.isPublic ${col?.isPublic
? html` ? html`
@ -507,10 +512,10 @@ export class CollectionsList extends LiteElement {
</sl-tooltip> </sl-tooltip>
`} `}
</btrix-table-cell> </btrix-table-cell>
<btrix-table-cell> <btrix-table-cell rowClickTarget="a">
<a <a
class="block py-2 truncate"
href=${`${this.orgBasePath}/collections/view/${col.id}`} href=${`${this.orgBasePath}/collections/view/${col.id}`}
class="block text-primary hover:text-indigo-500"
@click=${this.navLink} @click=${this.navLink}
> >
${col.name} ${col.name}
@ -542,7 +547,7 @@ export class CollectionsList extends LiteElement {
minute="2-digit" minute="2-digit"
></sl-format-date> ></sl-format-date>
</btrix-table-cell> </btrix-table-cell>
<btrix-table-cell> <btrix-table-cell class="px-1">
${this.isCrawler ? this.renderActions(col) : ""} ${this.isCrawler ? this.renderActions(col) : ""}
</btrix-table-cell> </btrix-table-cell>
</btrix-table-row> </btrix-table-row>
@ -552,10 +557,7 @@ export class CollectionsList extends LiteElement {
const authToken = this.authState!.headers.Authorization.split(" ")[1]; const authToken = this.authState!.headers.Authorization.split(" ")[1];
return html` return html`
<sl-dropdown distance="4"> <btrix-overflow-dropdown>
<btrix-button class="p-2" slot="trigger" label=${msg("Actions")} icon>
<sl-icon class="font-base" name="three-dots-vertical"></sl-icon>
</btrix-button>
<sl-menu> <sl-menu>
<sl-menu-item <sl-menu-item
@click=${() => this.manageCollection(col, "editMetadata")} @click=${() => this.manageCollection(col, "editMetadata")}
@ -602,7 +604,11 @@ export class CollectionsList extends LiteElement {
class="px-6 py-[0.6rem] flex gap-2 items-center whitespace-nowrap hover:bg-neutral-100" class="px-6 py-[0.6rem] flex gap-2 items-center whitespace-nowrap hover:bg-neutral-100"
download download
@click=${(e: MouseEvent) => { @click=${(e: MouseEvent) => {
(e.target as HTMLAnchorElement).closest("sl-dropdown")?.hide(); (
(e.target as HTMLAnchorElement).closest(
"btrix-overflow-dropdown"
) as OverflowDropdown
)?.hide();
}} }}
> >
<sl-icon name="cloud-download" slot="prefix"></sl-icon> <sl-icon name="cloud-download" slot="prefix"></sl-icon>
@ -617,7 +623,7 @@ export class CollectionsList extends LiteElement {
${msg("Delete Collection")} ${msg("Delete Collection")}
</sl-menu-item> </sl-menu-item>
</sl-menu> </sl-menu>
</sl-dropdown> </btrix-overflow-dropdown>
`; `;
}; };

View File

@ -1,4 +1,4 @@
import themeCSS from "./theme.css"; import themeCSS from "./theme.stylesheet.css";
// Create a new style sheet from the compiled theme CSS // Create a new style sheet from the compiled theme CSS
export const theme = new CSSStyleSheet(); export const theme = new CSSStyleSheet();

View File

@ -104,13 +104,14 @@ const main = {
exclude: /node_modules/, exclude: /node_modules/,
}, },
{ {
// Non-theme styles and assets like fonts and Shoelace // Global styles and assets, like fonts and Shoelace,
// that get added to document styles
test: /\.css$/, test: /\.css$/,
include: [ include: [
path.resolve(__dirname, "src"), path.resolve(__dirname, "src"),
path.resolve(__dirname, "node_modules/@shoelace-style/shoelace"), path.resolve(__dirname, "node_modules/@shoelace-style/shoelace"),
], ],
exclude: [path.resolve(__dirname, "src/theme.css")], exclude: /\.stylesheet\.css$/,
use: [ use: [
"style-loader", "style-loader",
{ loader: "css-loader", options: { importLoaders: 1 } }, { loader: "css-loader", options: { importLoaders: 1 } },
@ -118,8 +119,8 @@ const main = {
], ],
}, },
{ {
// Theme CSS loaded as raw string and used as a CSSStyleSheet // CSS loaded as raw string and used as a CSSStyleSheet
test: /theme\.css$/, test: /\.stylesheet\.css$/,
type: "asset/source", type: "asset/source",
include: [path.resolve(__dirname, "src")], include: [path.resolve(__dirname, "src")],
use: ["postcss-loader"], use: ["postcss-loader"],