Finish theming
This commit is contained in:
@@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { type FC } from "react";
|
import { type FC } from "react";
|
||||||
import styled, { ThemeProvider } from "styled-components";
|
import styled from "styled-components";
|
||||||
import { type Api } from "@element-hq/element-web-module-api";
|
import { type Api } from "@element-hq/element-web-module-api";
|
||||||
import { Heading } from "@vector-im/compound-web";
|
import { Heading } from "@vector-im/compound-web";
|
||||||
|
|
||||||
@@ -14,7 +14,6 @@ import { type ModuleConfig } from "./config";
|
|||||||
import UniventionMenu from "./Univention/Menu";
|
import UniventionMenu from "./Univention/Menu";
|
||||||
import Menu from "./Menu";
|
import Menu from "./Menu";
|
||||||
import Logo from "./Logo.tsx";
|
import Logo from "./Logo.tsx";
|
||||||
import { theme } from "./theme.ts";
|
|
||||||
|
|
||||||
const Root = styled.nav`
|
const Root = styled.nav`
|
||||||
height: ${({ theme }): string => theme.bannerHeight};
|
height: ${({ theme }): string => theme.bannerHeight};
|
||||||
@@ -50,17 +49,15 @@ const Banner: FC<Props> = ({ api, logoUrl, href, menu }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<Root>
|
||||||
<Root>
|
{menuJsx}
|
||||||
{menuJsx}
|
<LogoContainer>
|
||||||
<LogoContainer>
|
<Logo api={api} src={logoUrl} href={href} height="100%" />
|
||||||
<Logo api={api} src={logoUrl} href={href} height="100%" />
|
</LogoContainer>
|
||||||
</LogoContainer>
|
<Heading size="sm" weight="medium" as="h1">
|
||||||
<Heading size="sm" weight="medium" as="h1">
|
{api.config.get("brand")}
|
||||||
{api.config.get("brand")}
|
</Heading>
|
||||||
</Heading>
|
</Root>
|
||||||
</Root>
|
|
||||||
</ThemeProvider>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { z } from "zod";
|
import { z, ZodSchema, ZodTypeDef } from "zod";
|
||||||
|
|
||||||
|
import { Theme } from "./theme.ts";
|
||||||
|
|
||||||
const StaticConfig = z.object({
|
const StaticConfig = z.object({
|
||||||
type: z.literal("static"),
|
type: z.literal("static"),
|
||||||
@@ -85,15 +87,25 @@ export const ModuleConfig = z.object({
|
|||||||
*/
|
*/
|
||||||
logo_link_url: z.string().url(),
|
logo_link_url: z.string().url(),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for the menu.
|
||||||
|
*/
|
||||||
menu: z.discriminatedUnion("type", [StaticConfig, UniventionConfig]),
|
menu: z.discriminatedUnion("type", [StaticConfig, UniventionConfig]),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Theme variable overrides, optional.
|
||||||
|
*/
|
||||||
|
theme: Theme.default({}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type ModuleConfig = z.infer<typeof ModuleConfig>;
|
export type ModuleConfig = z.infer<typeof ModuleConfig>;
|
||||||
|
|
||||||
|
export type ConfigSchema = ZodSchema<z.output<typeof ModuleConfig>, ZodTypeDef, z.input<typeof ModuleConfig>>;
|
||||||
|
|
||||||
export const CONFIG_KEY = "io.element.element-web-modules.banner";
|
export const CONFIG_KEY = "io.element.element-web-modules.banner";
|
||||||
|
|
||||||
declare module "@element-hq/element-web-module-api" {
|
declare module "@element-hq/element-web-module-api" {
|
||||||
export interface Config {
|
export interface Config {
|
||||||
[CONFIG_KEY]: ModuleConfig;
|
[CONFIG_KEY]: ConfigSchema["_input"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { ThemeProvider } from "styled-components";
|
||||||
|
|
||||||
import type { Module, Api, ModuleFactory } from "@element-hq/element-web-module-api";
|
import type { Module, Api, ModuleFactory } from "@element-hq/element-web-module-api";
|
||||||
import Translations from "./translations.json";
|
import Translations from "./translations.json";
|
||||||
import { ModuleConfig, CONFIG_KEY } from "./config";
|
import { ModuleConfig, CONFIG_KEY } from "./config";
|
||||||
@@ -33,12 +35,14 @@ class BannerModule implements Module {
|
|||||||
|
|
||||||
const root = this.api.createRoot(div);
|
const root = this.api.createRoot(div);
|
||||||
root.render(
|
root.render(
|
||||||
<Banner
|
<ThemeProvider theme={this.config.theme}>
|
||||||
api={this.api}
|
<Banner
|
||||||
logoUrl={this.config.logo_url}
|
api={this.api}
|
||||||
href={this.config.logo_link_url}
|
logoUrl={this.config.logo_url}
|
||||||
menu={this.config.menu}
|
href={this.config.logo_link_url}
|
||||||
/>,
|
menu={this.config.menu}
|
||||||
|
/>
|
||||||
|
</ThemeProvider>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,26 +5,26 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const theme = {
|
import { z } from "zod";
|
||||||
textColor: "var(--cpd-color-text-primary)",
|
|
||||||
subheadingColor: "var(--cpd-color-text-secondary)",
|
|
||||||
bannerBackgroundColor: "var(--cpd-color-bg-canvas-default)",
|
|
||||||
bannerHeight: "60px",
|
|
||||||
triggerWidth: "68px",
|
|
||||||
triggerBackgroundColor: "var(--cpd-color-bg-subtle-secondary)",
|
|
||||||
triggerBackgroundColorHover: "var(--cpd-color-bg-accent-hovered)",
|
|
||||||
triggerBackgroundColorPressed: "var(--cpd-color-bg-accent-pressed)",
|
|
||||||
triggerColor: "var(--cpd-color-icon-primary)",
|
|
||||||
triggerColorContrast: "var(--cpd-color-icon-on-solid-primary)",
|
|
||||||
menuWidth: "320px",
|
|
||||||
menuBackgroundColor: "var(--cpd-color-bg-canvas-default)",
|
|
||||||
menuButtonBackgroundColorHover: "var(--cpd-color-bg-action-secondary-hovered)",
|
|
||||||
menuButtonBackgroundColorPressed: "var(--cpd-color-bg-action-secondary-pressed)",
|
|
||||||
};
|
|
||||||
|
|
||||||
type Theme = typeof theme;
|
export const Theme = z.object({
|
||||||
|
textColor: z.string().default("var(--cpd-color-text-primary)"),
|
||||||
|
subheadingColor: z.string().default("var(--cpd-color-text-secondary)"),
|
||||||
|
bannerBackgroundColor: z.string().default("var(--cpd-color-bg-canvas-default)"),
|
||||||
|
bannerHeight: z.string().default("60px"),
|
||||||
|
triggerWidth: z.string().default("68px"),
|
||||||
|
triggerBackgroundColor: z.string().default("var(--cpd-color-bg-subtle-secondary)"),
|
||||||
|
triggerBackgroundColorHover: z.string().default("var(--cpd-color-bg-accent-hovered)"),
|
||||||
|
triggerBackgroundColorPressed: z.string().default("var(--cpd-color-bg-accent-pressed)"),
|
||||||
|
triggerColor: z.string().default("var(--cpd-color-icon-primary)"),
|
||||||
|
triggerColorContrast: z.string().default("var(--cpd-color-icon-on-solid-primary)"),
|
||||||
|
menuWidth: z.string().default("320px"),
|
||||||
|
menuBackgroundColor: z.string().default("var(--cpd-color-bg-canvas-default)"),
|
||||||
|
menuButtonBackgroundColorHover: z.string().default("var(--cpd-color-bg-action-secondary-hovered)"),
|
||||||
|
menuButtonBackgroundColorPressed: z.string().default("var(--cpd-color-bg-action-secondary-pressed)"),
|
||||||
|
});
|
||||||
|
|
||||||
export { theme };
|
export type Theme = z.infer<typeof Theme>;
|
||||||
|
|
||||||
declare module "styled-components" {
|
declare module "styled-components" {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { test as base, expect } from "../../../../playwright/element-web-test.ts";
|
import { test as base, expect } from "../../../../playwright/element-web-test.ts";
|
||||||
import { ModuleConfig } from "../src/config.ts";
|
import { type ConfigSchema } from "../src/config.ts";
|
||||||
|
|
||||||
const test = base.extend<{
|
const test = base.extend<{
|
||||||
// Resolver for when to respond to the navigation.json request
|
// Resolver for when to respond to the navigation.json request
|
||||||
@@ -39,7 +39,7 @@ test.describe("Banner", () => {
|
|||||||
// We don't take a screenshot as we don't want to assert Element's styling, only our own
|
// We don't take a screenshot as we don't want to assert Element's styling, only our own
|
||||||
});
|
});
|
||||||
|
|
||||||
const configs: ModuleConfig[] = [
|
const configs: ConfigSchema["_input"][] = [
|
||||||
{
|
{
|
||||||
logo_url: "http://localhost:8080/logo.svg",
|
logo_url: "http://localhost:8080/logo.svg",
|
||||||
logo_link_url: "https://example.com/portal",
|
logo_link_url: "https://example.com/portal",
|
||||||
@@ -84,6 +84,10 @@ test.describe("Banner", () => {
|
|||||||
logo_url: "http://localhost:8080/opendesk/logofull.svg",
|
logo_url: "http://localhost:8080/opendesk/logofull.svg",
|
||||||
ics_url: "http://localhost:8080/ics/",
|
ics_url: "http://localhost:8080/ics/",
|
||||||
},
|
},
|
||||||
|
theme: {
|
||||||
|
triggerBackgroundColorHover: "#571EFA",
|
||||||
|
triggerBackgroundColorPressed: "#4519C2",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.6 KiB |
Reference in New Issue
Block a user