chore: Refactor page headers (#2282)
- Refactors all page headers to use new `pageHeader` - Removes border under org name/title in the org dashboard
This commit is contained in:
parent
b36ed9f730
commit
0c81a2f89e
@ -1,14 +1,11 @@
|
||||
import clsx from "clsx";
|
||||
import { html, nothing, type TemplateResult } from "lit";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
import { html as staticHtml, unsafeStatic } from "lit/static-html.js";
|
||||
|
||||
import { pageNav, pageTitle } from "./pageHeader";
|
||||
import { pageHeader, pageNav } from "./pageHeader";
|
||||
|
||||
import { tw } from "@/utils/tailwind";
|
||||
|
||||
type Content = string | TemplateResult | typeof nothing;
|
||||
|
||||
export function pageHeading({
|
||||
content,
|
||||
level = 2,
|
||||
@ -29,48 +26,6 @@ export function pageHeading({
|
||||
`;
|
||||
}
|
||||
|
||||
// TODO consolidate with pageHeader.ts https://github.com/webrecorder/browsertrix/issues/2197
|
||||
export function pageHeader({
|
||||
title,
|
||||
prefix,
|
||||
suffix,
|
||||
secondary,
|
||||
actions,
|
||||
border = true,
|
||||
classNames,
|
||||
}: {
|
||||
title?: Content;
|
||||
prefix?: Content;
|
||||
suffix?: Content;
|
||||
secondary?: Content;
|
||||
actions?: Content;
|
||||
border?: boolean;
|
||||
classNames?: typeof tw;
|
||||
}) {
|
||||
return html`
|
||||
<header
|
||||
class=${clsx(
|
||||
tw`mt-5 flex flex-col gap-3 lg:flex-row`,
|
||||
border && tw`border-b pb-3`,
|
||||
classNames,
|
||||
)}
|
||||
>
|
||||
<div class="flex flex-1 flex-col gap-2">
|
||||
<div class="flex flex-wrap items-center gap-2.5">
|
||||
${prefix}${pageTitle(title)}${suffix}
|
||||
</div>
|
||||
${secondary}
|
||||
</div>
|
||||
|
||||
${actions
|
||||
? html`<div class="ml-auto flex flex-shrink-0 items-center gap-2">
|
||||
${actions}
|
||||
</div>`
|
||||
: nothing}
|
||||
</header>
|
||||
`;
|
||||
}
|
||||
|
||||
export function page(
|
||||
header: Parameters<typeof pageHeader>[0] & {
|
||||
breadcrumbs?: Parameters<typeof pageNav>[0];
|
||||
|
||||
@ -7,6 +7,8 @@ import { ifDefined } from "lit/directives/if-defined.js";
|
||||
import { NavigateController } from "@/controllers/navigate";
|
||||
import { tw } from "@/utils/tailwind";
|
||||
|
||||
type Content = string | TemplateResult | typeof nothing;
|
||||
|
||||
export type Breadcrumb = {
|
||||
href?: string;
|
||||
content?: string | TemplateResult;
|
||||
@ -101,22 +103,42 @@ export function pageNav(breadcrumbs: Breadcrumb[]) {
|
||||
return pageBreadcrumbs(breadcrumbs);
|
||||
}
|
||||
|
||||
// TODO consolidate with page.ts https://github.com/webrecorder/browsertrix/issues/2197
|
||||
export function pageHeader(
|
||||
title?: string | TemplateResult,
|
||||
suffix?: TemplateResult<1>,
|
||||
classNames?: string,
|
||||
) {
|
||||
export function pageHeader({
|
||||
title,
|
||||
prefix,
|
||||
suffix,
|
||||
secondary,
|
||||
actions,
|
||||
border = true,
|
||||
classNames,
|
||||
}: {
|
||||
title?: Content;
|
||||
prefix?: Content;
|
||||
suffix?: Content;
|
||||
secondary?: Content;
|
||||
actions?: Content;
|
||||
border?: boolean;
|
||||
classNames?: typeof tw | string;
|
||||
}) {
|
||||
return html`
|
||||
<header
|
||||
class=${clsx(
|
||||
"mt-5 flex items-end flex-wrap justify-between gap-2 border-b pb-3",
|
||||
tw`mt-5 flex flex-col gap-3 lg:flex-row`,
|
||||
border && tw`border-b pb-3`,
|
||||
classNames,
|
||||
)}
|
||||
>
|
||||
${pageTitle(title)}
|
||||
${suffix
|
||||
? html`<div class="ml-auto flex items-center gap-2">${suffix}</div>`
|
||||
<div class="flex flex-1 flex-col gap-2">
|
||||
<div class="flex flex-wrap items-center gap-2.5">
|
||||
${prefix}${pageTitle(title)}${suffix}
|
||||
</div>
|
||||
${secondary}
|
||||
</div>
|
||||
|
||||
${actions
|
||||
? html`<div class="ml-auto flex flex-shrink-0 items-center gap-2">
|
||||
${actions}
|
||||
</div>`
|
||||
: nothing}
|
||||
</header>
|
||||
`;
|
||||
|
||||
@ -144,7 +144,10 @@ export class AccountSettings extends BtrixElement {
|
||||
title=${msg("Account Settings")}
|
||||
></btrix-document-title>
|
||||
|
||||
${pageHeader(msg("Account Settings"), undefined, tw`mb-3 lg:mb-5`)}
|
||||
${pageHeader({
|
||||
title: msg("Account Settings"),
|
||||
classNames: tw`mb-3 lg:mb-5`,
|
||||
})}
|
||||
|
||||
<btrix-tab-list activePanel=${this.activeTab} hideIndicator>
|
||||
<header slot="header" class="flex h-7 items-end justify-between">
|
||||
|
||||
@ -264,29 +264,28 @@ export class CrawlsList extends BtrixElement {
|
||||
return html`
|
||||
<main>
|
||||
<div class="contents">
|
||||
${pageHeader(
|
||||
msg("Archived Items"),
|
||||
when(
|
||||
this.isCrawler,
|
||||
() => html`
|
||||
<sl-tooltip
|
||||
content=${msg("Org Storage Full")}
|
||||
?disabled=${!this.org?.storageQuotaReached}
|
||||
>
|
||||
<sl-button
|
||||
size="small"
|
||||
variant="primary"
|
||||
@click=${() => (this.isUploadingArchive = true)}
|
||||
?disabled=${isArchivingDisabled(this.org)}
|
||||
${pageHeader({
|
||||
title: msg("Archived Items"),
|
||||
actions: this.isCrawler
|
||||
? html`
|
||||
<sl-tooltip
|
||||
content=${msg("Org Storage Full")}
|
||||
?disabled=${!this.org?.storageQuotaReached}
|
||||
>
|
||||
<sl-icon slot="prefix" name="upload"></sl-icon>
|
||||
${msg("Upload WACZ")}
|
||||
</sl-button>
|
||||
</sl-tooltip>
|
||||
`,
|
||||
),
|
||||
tw`mb-3`,
|
||||
)}
|
||||
<sl-button
|
||||
size="small"
|
||||
variant="primary"
|
||||
@click=${() => (this.isUploadingArchive = true)}
|
||||
?disabled=${isArchivingDisabled(this.org)}
|
||||
>
|
||||
<sl-icon slot="prefix" name="upload"></sl-icon>
|
||||
${msg("Upload WACZ")}
|
||||
</sl-button>
|
||||
</sl-tooltip>
|
||||
`
|
||||
: nothing,
|
||||
classNames: tw`mb-3`,
|
||||
})}
|
||||
<div class="mb-3 flex gap-2">
|
||||
${listTypes.map(({ label, itemType, icon }) => {
|
||||
const isSelected = itemType === this.itemType;
|
||||
|
||||
@ -93,30 +93,29 @@ export class BrowserProfilesList extends BtrixElement {
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`${pageHeader(
|
||||
msg("Browser Profiles"),
|
||||
when(
|
||||
this.isCrawler,
|
||||
() => html`
|
||||
<sl-button
|
||||
variant="primary"
|
||||
size="small"
|
||||
?disabled=${isArchivingDisabled(this.org)}
|
||||
@click=${() => {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("select-new-dialog", {
|
||||
detail: "browser-profile",
|
||||
}) as SelectNewDialogEvent,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<sl-icon slot="prefix" name="plus-lg"></sl-icon>
|
||||
${msg("New Browser Profile")}
|
||||
</sl-button>
|
||||
`,
|
||||
),
|
||||
tw`mb-3`,
|
||||
)}
|
||||
return html`${pageHeader({
|
||||
title: msg("Browser Profiles"),
|
||||
actions: this.isCrawler
|
||||
? html`
|
||||
<sl-button
|
||||
variant="primary"
|
||||
size="small"
|
||||
?disabled=${isArchivingDisabled(this.org)}
|
||||
@click=${() => {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("select-new-dialog", {
|
||||
detail: "browser-profile",
|
||||
}) as SelectNewDialogEvent,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<sl-icon slot="prefix" name="plus-lg"></sl-icon>
|
||||
${msg("New Browser Profile")}
|
||||
</sl-button>
|
||||
`
|
||||
: undefined,
|
||||
classNames: tw`mb-3`,
|
||||
})}
|
||||
<div class="pb-1">${this.renderTable()}</div>`;
|
||||
}
|
||||
|
||||
|
||||
@ -13,8 +13,7 @@ import type { MarkdownEditor } from "@/components/ui/markdown-editor";
|
||||
import type { PageChangeEvent } from "@/components/ui/pagination";
|
||||
import { SelectCollectionAccess } from "@/features/collections/select-collection-access";
|
||||
import type { ShareCollection } from "@/features/collections/share-collection";
|
||||
import { pageHeader } from "@/layouts/page";
|
||||
import { pageNav, type Breadcrumb } from "@/layouts/pageHeader";
|
||||
import { pageHeader, pageNav, type Breadcrumb } from "@/layouts/pageHeader";
|
||||
import type {
|
||||
APIPaginatedList,
|
||||
APIPaginationQuery,
|
||||
|
||||
@ -132,12 +132,10 @@ export class CollectionsList extends BtrixElement {
|
||||
render() {
|
||||
return html`
|
||||
<div class="contents">
|
||||
${pageHeader(
|
||||
msg("Collections"),
|
||||
when(
|
||||
this.isCrawler,
|
||||
() => html`
|
||||
<sl-button
|
||||
${pageHeader({
|
||||
title: msg("Collections"),
|
||||
actions: this.isCrawler
|
||||
? html` <sl-button
|
||||
variant="primary"
|
||||
size="small"
|
||||
?disabled=${!this.org || this.org.readOnly}
|
||||
@ -145,11 +143,10 @@ export class CollectionsList extends BtrixElement {
|
||||
>
|
||||
<sl-icon slot="prefix" name="plus-lg"></sl-icon>
|
||||
${msg("New Collection")}
|
||||
</sl-button>
|
||||
`,
|
||||
),
|
||||
tw`border-b-transparent`,
|
||||
)}
|
||||
</sl-button>`
|
||||
: nothing,
|
||||
classNames: tw`border-b-transparent`,
|
||||
})}
|
||||
</div>
|
||||
|
||||
<link rel="preload" as="image" href=${noCollectionsImg} />
|
||||
|
||||
@ -15,6 +15,7 @@ import { RouteNamespace } from "@/routes";
|
||||
import type { PublicCollection } from "@/types/collection";
|
||||
import type { PublicOrgCollections } from "@/types/org";
|
||||
import { humanizeExecutionSeconds } from "@/utils/executionTimeFormatter";
|
||||
import { tw } from "@/utils/tailwind";
|
||||
|
||||
type Metrics = {
|
||||
storageUsedBytes: number;
|
||||
@ -84,9 +85,9 @@ export class Dashboard extends BtrixElement {
|
||||
this.metrics.storageUsedBytes >= this.metrics.storageQuotaBytes;
|
||||
|
||||
return html`
|
||||
${pageHeader(
|
||||
this.userOrg?.name,
|
||||
html`
|
||||
${pageHeader({
|
||||
title: this.userOrg?.name,
|
||||
actions: html`
|
||||
${when(
|
||||
this.appState.isAdmin,
|
||||
() =>
|
||||
@ -153,8 +154,8 @@ export class Dashboard extends BtrixElement {
|
||||
</sl-dropdown>`,
|
||||
)}
|
||||
`,
|
||||
"mb-6",
|
||||
)}
|
||||
classNames: tw`border-b-transparent lg:mb-2`,
|
||||
})}
|
||||
<main>
|
||||
<div class="mb-10 flex flex-col gap-6 md:flex-row">
|
||||
${this.renderCard(
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { localized, msg, str } from "@lit/localize";
|
||||
import type { SlInput } from "@shoelace-style/shoelace";
|
||||
import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js";
|
||||
import { html, unsafeCSS, type PropertyValues } from "lit";
|
||||
import { html, nothing, unsafeCSS, type PropertyValues } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import { choose } from "lit/directives/choose.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
@ -136,21 +136,23 @@ export class OrgSettings extends BtrixElement {
|
||||
}
|
||||
|
||||
render() {
|
||||
return html` ${pageHeader(
|
||||
msg("Org Settings"),
|
||||
when(
|
||||
this.userInfo?.orgs && this.userInfo.orgs.length > 1 && this.userOrg,
|
||||
(userOrg) => html`
|
||||
<div class="text-neutral-400">
|
||||
${msg(
|
||||
html`Viewing
|
||||
<strong class="font-medium">${userOrg.name}</strong>`,
|
||||
)}
|
||||
</div>
|
||||
`,
|
||||
),
|
||||
tw`mb-3 lg:mb-5`,
|
||||
)}
|
||||
return html` ${pageHeader({
|
||||
title: msg("Org Settings"),
|
||||
actions:
|
||||
this.userInfo?.orgs && this.userInfo.orgs.length > 1 && this.userOrg
|
||||
? html`
|
||||
<div class="text-neutral-400">
|
||||
${msg(
|
||||
html`Viewing
|
||||
<strong class="font-medium"
|
||||
>${this.userOrg.name}</strong
|
||||
>`,
|
||||
)}
|
||||
</div>
|
||||
`
|
||||
: nothing,
|
||||
classNames: tw`mb-3 lg:mb-5`,
|
||||
})}
|
||||
|
||||
<btrix-tab-list activePanel=${this.activePanel} hideIndicator>
|
||||
<header slot="header" class="flex h-7 items-end justify-between">
|
||||
|
||||
@ -208,9 +208,9 @@ export class WorkflowsList extends BtrixElement {
|
||||
render() {
|
||||
return html`
|
||||
<div class="contents">
|
||||
${pageHeader(
|
||||
msg("Crawl Workflows"),
|
||||
html`
|
||||
${pageHeader({
|
||||
title: msg("Crawl Workflows"),
|
||||
actions: html`
|
||||
${when(
|
||||
this.appState.isAdmin,
|
||||
() =>
|
||||
@ -304,8 +304,8 @@ export class WorkflowsList extends BtrixElement {
|
||||
`,
|
||||
)}
|
||||
`,
|
||||
tw`border-b-transparent`,
|
||||
)}
|
||||
classNames: tw`border-b-transparent`,
|
||||
})}
|
||||
<div class="sticky top-2 z-10 mb-3 rounded-lg border bg-neutral-50 p-4">
|
||||
${this.renderControls()}
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user