From 363d0a76545e0dd55ec889f33dddb2ea07051d87 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 15 May 2025 17:03:02 +0100 Subject: [PATCH] Stash --- modules/banner/element-web/src/Banner.tsx | 28 +++---- modules/banner/element-web/src/Logo.tsx | 11 ++- modules/banner/element-web/src/Menu.tsx | 65 +++++++++------- .../src/Univention/SilentLogin.tsx | 3 +- modules/banner/element-web/src/index.tsx | 4 +- modules/banner/element-web/src/theme.ts | 78 +++++-------------- .../banner/element-web/tests/banner.spec.ts | 3 +- 7 files changed, 81 insertions(+), 111 deletions(-) diff --git a/modules/banner/element-web/src/Banner.tsx b/modules/banner/element-web/src/Banner.tsx index 2d957f9b6e..310f584312 100644 --- a/modules/banner/element-web/src/Banner.tsx +++ b/modules/banner/element-web/src/Banner.tsx @@ -8,26 +8,25 @@ Please see LICENSE files in the repository root for full details. import { type FC } from "react"; import styled, { ThemeProvider } from "styled-components"; import { type Api } from "@element-hq/element-web-module-api"; +import { Heading } from "@vector-im/compound-web"; import { type ModuleConfig } from "./config"; import UniventionMenu from "./Univention/Menu"; import Menu from "./Menu"; -import { theme } from "./theme"; import Logo from "./Logo.tsx"; +import { theme } from "./theme.ts"; const Root = styled.nav` - background-color: ${({ theme }): string => theme.compound.color.bgCanvasDefault}; - border-bottom: ${({ theme }): string => theme.navbar.border}; - height: ${({ theme }): string => theme.navbar.height}; - display: grid; - grid-template-columns: ${({ theme }): string => `${theme.navbar.triggerWidth} auto`}; - gap: 24px; + height: ${({ theme }): string => theme.bannerHeight}; + background-color: ${({ theme }): string => theme.bannerBackgroundColor}; + border-bottom: "1px solid var(--cpd-color-bg-subtle-primary)"; + display: flex; + gap: var(--cpd-space-3x); `; -const Main = styled.div` +const LogoContainer = styled.div` display: flex; - align-items: center; - grid-column: 2; + padding: var(--cpd-space-3x) 0; `; interface Props { @@ -54,9 +53,12 @@ const Banner: FC = ({ api, logoUrl, href, menu }) => { {menuJsx} -
- -
+ + + + + {api.config.get("brand")} +
); diff --git a/modules/banner/element-web/src/Logo.tsx b/modules/banner/element-web/src/Logo.tsx index d515cfdb4e..485f5afbbf 100644 --- a/modules/banner/element-web/src/Logo.tsx +++ b/modules/banner/element-web/src/Logo.tsx @@ -13,19 +13,22 @@ const Anchor = styled.a` display: flex; `; -const Image = styled.img` - height: ${({ theme }): string => theme.navbar.logoHeight}; +const Image = styled.img<{ + height?: string; +}>` align-self: center; + height: ${({ height }): string => height ?? "32px"}; `; interface Props { api: Api; src: string; + height?: string; href?: string; } -const Logo: FC = ({ api, src, href }) => { - const img = {api.i18n.translate("logo_alt")}; +const Logo: FC = ({ api, src, href, height }) => { + const img = {api.i18n.translate("logo_alt")}; if (!href) return img; diff --git a/modules/banner/element-web/src/Menu.tsx b/modules/banner/element-web/src/Menu.tsx index 7b32d53c56..e77dfaf67b 100644 --- a/modules/banner/element-web/src/Menu.tsx +++ b/modules/banner/element-web/src/Menu.tsx @@ -8,47 +8,47 @@ Please see LICENSE files in the repository root for full details. import { type FC, type JSX, useState } from "react"; import { AnimatePresence, motion } from "framer-motion"; import * as Dialog from "@radix-ui/react-dialog"; -import styled from "styled-components"; +import styled, { useTheme } from "styled-components"; import { InlineSpinner } from "@vector-im/compound-web"; import { StaticConfig } from "./config"; -import { theme } from "./theme"; import type { Api } from "@element-hq/element-web-module-api"; import Logo from "./Logo.tsx"; const Sidebar = styled(motion.div)` - padding: 16px 12px 0; - box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3); + padding: 0 var(--cpd-space-3x) var(--cpd-space-4x); + box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.1); overflow: auto; position: fixed; left: 0; top: 0; height: 100%; - width: ${({ theme }): string => theme.menu.width}; - background: white; - border-top-right-radius: 16px; - border-bottom-right-radius: 16px; + width: ${({ theme }): string => theme.menuWidth}; + background: ${({ theme }): string => theme.menuBackgroundColor}; + border-radius: 0 16px 16px 0; `; const SidebarHeading = styled.div` display: flex; justify-content: space-between; align-items: center; - margin-bottom: 20px; + margin-bottom: 20px; // TODO check `; -const Launcher = styled.button` +const Trigger = styled.button` align-items: center; border: none; - color: ${({ theme }): string => theme.compound.color.textPrimary}; cursor: pointer; display: flex; + background-color: ${({ theme }): string => theme.triggerBackgroundColor}; + color: ${({ theme }): string => theme.triggerColor}; + width: ${({ theme }): string => theme.triggerWidth}; &:hover, &:focus, &[data-expanded="true"] { - background-color: ${({ theme }): string => theme.color.accent}; - color: #ffffff; + background-color: ${({ theme }): string => theme.triggerBackgroundColorHover}; + color: ${({ theme }): string => theme.triggerColorHover}; } svg { @@ -71,39 +71,43 @@ const CloseButton = styled.button` &:hover, &:focus { - background-color: rgba(238, 239, 242, 1); + background-color: ${({ theme }): string => theme.menuButtonBackgroundColorHover}; } `; const CategoryHeading = styled.h2` font-weight: 700; font-size: 12px; - color: #203257; + color: #203257; // TODO font margin-top: 16px; margin-bottom: 8px; `; const LinkButton = styled.a` - font-size: 14px; - color: #000000; + font-size: 14px; // TODO font + color: var(--cpd-color-text-action-primary); font-weight: 500; display: flex; border-radius: 8px; padding: 8px; align-items: center; + &:link { + color: var(--cpd-color-text-action-primary); // TODO + } + &:hover { - background-color: #eeeff2; + background-color: #eeeff2; // TODO } `; const LinkLogo = styled.img` height: 24px; width: 24px; - border-radius: 3px; - border: 1px solid #eeeff2; + border-radius: 3px; // TODO + border: 1px solid #eeeff2; // TODO margin-right: 8px; - background-color: #ffffff; + background-color: ${({ theme }): string => theme.menuBackgroundColor}; `; const CentredContainer = styled.div` @@ -134,8 +138,6 @@ interface Props { fallbackLogoUrl: string; } -const WIDTH = parseInt(theme.menu.width.slice(0, -2), 10); - const Category: FC<{ data: StaticConfig["categories"][number]; }> = ({ data }) => { @@ -152,6 +154,8 @@ const Category: FC<{ }; const Menu: FC = ({ api, config, fallbackLogoUrl }) => { + const theme = useTheme(); + const width = parseInt(theme.menuWidth.slice(0, -2), 10); const [open, setOpen] = useState(false); let content: JSX.Element; @@ -180,11 +184,14 @@ const Menu: FC = ({ api, config, fallbackLogoUrl }) => { return ( - - - + + + - + @@ -201,9 +208,9 @@ const Menu: FC = ({ api, config, fallbackLogoUrl }) => { diff --git a/modules/banner/element-web/src/Univention/SilentLogin.tsx b/modules/banner/element-web/src/Univention/SilentLogin.tsx index 06814333c2..46e0f39eb0 100644 --- a/modules/banner/element-web/src/Univention/SilentLogin.tsx +++ b/modules/banner/element-web/src/Univention/SilentLogin.tsx @@ -34,8 +34,7 @@ const SilentLogin: FC = ({ onLoggedIn, icsUrl }) => { }; }, [onLoggedIn, url.origin]); - // TODO title? - return ; + return ; }; export default SilentLogin; diff --git a/modules/banner/element-web/src/index.tsx b/modules/banner/element-web/src/index.tsx index cc1e1e5123..54dc3a0392 100644 --- a/modules/banner/element-web/src/index.tsx +++ b/modules/banner/element-web/src/index.tsx @@ -11,7 +11,7 @@ import { ModuleConfig, CONFIG_KEY } from "./config"; import Banner from "./Banner"; import { name as ModuleName } from "../package.json"; -class TopBarModule implements Module { +class BannerModule implements Module { public static readonly moduleApiVersion = "^1.0.0"; private config?: ModuleConfig; @@ -43,4 +43,4 @@ class TopBarModule implements Module { } } -export default TopBarModule satisfies ModuleFactory; +export default BannerModule satisfies ModuleFactory; diff --git a/modules/banner/element-web/src/theme.ts b/modules/banner/element-web/src/theme.ts index 300cf1924a..f6a6c43f30 100644 --- a/modules/banner/element-web/src/theme.ts +++ b/modules/banner/element-web/src/theme.ts @@ -5,68 +5,26 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE files in the repository root for full details. */ -import { DefaultTheme } from "styled-components"; +const theme = { + textColor: "var(--cpd-color-text-primary)", + bannerBackgroundColor: "var(--cpd-color-bg-canvas-default)", + bannerHeight: "60px", + triggerWidth: "68px", + triggerBackgroundColor: "var(--cpd-color-bg-subtle-primary)", + // triggerBackgroundColorHover: "var(--cpd-color-bg-accent-hovered)", + triggerBackgroundColorHover: "var(--cpd-color-text-action-accent)", + triggerColor: "var(--cpd-color-text-primary)", + triggerColorHover: "var(--cpd-color-bg-canvas-default)", + menuWidth: "320px", + menuBackgroundColor: "var(--cpd-color-bg-canvas-default)", + menuButtonBackgroundColorHover: "var(--cpd-color-bg-subtle-primary)", +}; -const bgCanvasDefault = "var(--cpd-color-bg-canvas-default)"; -const textActionAccent = "var(--cpd-color-text-action-accent)"; -const textPrimary = "var(--cpd-color-text-primary)"; -const iconOnSolidPrimary = "var(--cpd-color-icon-on-solid-primary)"; +type Theme = typeof theme; -const bodyMdSemibold = "var(--cpd-font-body-md-semibold)"; +export { theme }; declare module "styled-components" { - export interface DefaultTheme { - compound: { - color: { - bgCanvasDefault: string; - textActionAccent: string; - textPrimary: string; - iconOnSolidPrimary: string; - }; - font: { - bodyMdSemibold: string; - }; - }; - color: { - accent: string; - }; - navbar: { - border: string; - boxShadow: string; - height: string; - triggerWidth: string; - logoHeight: string; - }; - menu: { - width: string; - }; - } + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + export interface DefaultTheme extends Theme {} } - -export const theme: DefaultTheme = { - compound: { - color: { - bgCanvasDefault, - textActionAccent, - textPrimary, - iconOnSolidPrimary, - }, - font: { - bodyMdSemibold, - }, - }, - color: { - accent: "#571EFA", // primary/700 TODO - }, - navbar: { - border: "1px solid #D3D7DE", // TODO - boxShadow: "4px 4px 12px 0 rgba(118, 131, 156, 0.6)", - height: "60px", - triggerWidth: "68px", - logoHeight: "34px", - }, - menu: { - // TODO - width: "235px", - }, -}; diff --git a/modules/banner/element-web/tests/banner.spec.ts b/modules/banner/element-web/tests/banner.spec.ts index 4857e31865..ae9566ec5d 100644 --- a/modules/banner/element-web/tests/banner.spec.ts +++ b/modules/banner/element-web/tests/banner.spec.ts @@ -136,8 +136,9 @@ test.describe("Banner", () => { if (type === "univention") { await expect(sidebar).toMatchScreenshot(`${type}_menu_loading.png`); - await navigationJsonResolver.resolve(); + navigationJsonResolver.resolve(); } + await page.pause(); const emailApp = page.getByText("E-Mail"); await expect(emailApp).toHaveAttribute("href", "https://example.com/email");