You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-07-31 09:24:31 +03:00
frontend: start using CSS modules for components with design tokens
This commit is contained in:
21
frontend/src/components/Block.module.css
Normal file
21
frontend/src/components/Block.module.css
Normal file
@ -0,0 +1,21 @@
|
||||
/* Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
.block {
|
||||
background-color: var(--cpd-color-bg-subtle-secondary);
|
||||
color: var(--cpd-color-text-primary);
|
||||
padding: var(--cpd-space-4x);
|
||||
border-radius: var(--cpd-space-2x);
|
||||
}
|
@ -12,15 +12,18 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import styles from "./Block.module.css";
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
highlight?: boolean;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const Block: React.FC<Props> = ({ children, highlight, className }) => {
|
||||
const Block: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
children,
|
||||
highlight,
|
||||
}) => {
|
||||
return (
|
||||
<div className={className} data-active={highlight}>
|
||||
<div className={styles.block} data-active={highlight}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
21
frontend/src/components/BlockList.module.css
Normal file
21
frontend/src/components/BlockList.module.css
Normal file
@ -0,0 +1,21 @@
|
||||
/* Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
.block-list {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--cpd-space-4x);
|
||||
align-content: flex-start;
|
||||
}
|
@ -12,14 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
import styles from "./BlockList.module.css";
|
||||
|
||||
const BlockList: React.FC<Props> = ({ children }) => {
|
||||
return (
|
||||
<div className="grid grid-cols-1 gap-4 group content-start">{children}</div>
|
||||
);
|
||||
const BlockList: React.FC<React.PropsWithChildren<{}>> = ({ children }) => {
|
||||
return <div className={styles.blockList}>{children}</div>;
|
||||
};
|
||||
|
||||
export default BlockList;
|
||||
|
24
frontend/src/components/BrowserSession.module.css
Normal file
24
frontend/src/components/BrowserSession.module.css
Normal file
@ -0,0 +1,24 @@
|
||||
/* Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
.session-icon {
|
||||
color: var(--cpd-color-icon-secondary);
|
||||
background: var(--cpd-color-bg-subtle-secondary);
|
||||
height: var(--cpd-space-10x);
|
||||
width: var(--cpd-space-10x);
|
||||
padding: var(--cpd-space-2x);
|
||||
border-radius: var(--cpd-space-1x);
|
||||
margin-right: var(--cpd-space-2x);
|
||||
}
|
@ -22,7 +22,7 @@ import { useTransition } from "react";
|
||||
import { currentBrowserSessionIdAtom, currentUserIdAtom } from "../atoms";
|
||||
import { FragmentType, graphql, useFragment } from "../gql";
|
||||
|
||||
import Block from "./Block";
|
||||
import styles from "./BrowserSession.module.css";
|
||||
import DateTime from "./DateTime";
|
||||
|
||||
const FRAGMENT = graphql(/* GraphQL */ `
|
||||
@ -92,8 +92,8 @@ const BrowserSession: React.FC<Props> = ({ session, isCurrent }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Block className="flex items-center">
|
||||
<IconWebBrowser className="mr-4 session-icon" />
|
||||
<div className="flex items-center">
|
||||
<IconWebBrowser className={styles.sessionIcon} />
|
||||
<div className="flex-1">
|
||||
<Body size="md" weight="medium">
|
||||
{isCurrent ? (
|
||||
@ -118,7 +118,7 @@ const BrowserSession: React.FC<Props> = ({ session, isCurrent }) => {
|
||||
>
|
||||
Sign out
|
||||
</Button>
|
||||
</Block>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -82,7 +82,7 @@ const CompatSession: React.FC<{
|
||||
};
|
||||
|
||||
return (
|
||||
<Block className="p-4 bg-grey-25 dark:bg-grey-450 rounded-lg">
|
||||
<Block>
|
||||
<Body>
|
||||
Started: <DateTime datetime={data.createdAt} />
|
||||
</Body>
|
||||
|
31
frontend/src/components/Layout.module.css
Normal file
31
frontend/src/components/Layout.module.css
Normal file
@ -0,0 +1,31 @@
|
||||
/* Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
.container {
|
||||
width: 378px;
|
||||
margin: var(--cpd-space-10x) auto var(--cpd-space-6x) auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.separator {
|
||||
border: 0;
|
||||
height: 1px;
|
||||
background: var(--cpd-color-border-interactive-secondary);
|
||||
margin: var(--cpd-space-4x) 0;
|
||||
}
|
||||
|
@ -12,24 +12,27 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import styles from "./Layout.module.css";
|
||||
import NavBar from "./NavBar";
|
||||
import NavItem from "./NavItem";
|
||||
import NavItem, { ExternalLink } from "./NavItem";
|
||||
|
||||
const Separator: React.FC = () => <hr className={styles.separator} />;
|
||||
|
||||
const Layout: React.FC<{ children?: React.ReactNode }> = ({ children }) => {
|
||||
return (
|
||||
<>
|
||||
<NavBar className="nav-bar container">
|
||||
<div className={styles.container}>
|
||||
<NavBar>
|
||||
<NavItem route={{ type: "home" }}>Sessions</NavItem>
|
||||
<NavItem route={{ type: "account" }}>Emails</NavItem>
|
||||
</NavBar>
|
||||
|
||||
<hr className="my-2" />
|
||||
<Separator />
|
||||
|
||||
<main className="container">{children}</main>
|
||||
<main>{children}</main>
|
||||
|
||||
<hr className="my-2" />
|
||||
<Separator />
|
||||
|
||||
<footer className="text-center">
|
||||
<footer className={styles.footer}>
|
||||
<a href="https://matrix.org" target="_blank" rel="noreferrer noopener">
|
||||
<img
|
||||
className="inline my-2"
|
||||
@ -40,19 +43,19 @@ const Layout: React.FC<{ children?: React.ReactNode }> = ({ children }) => {
|
||||
/>
|
||||
</a>
|
||||
|
||||
<NavBar className="nav-bar container">
|
||||
<NavItem href="https://matrix.org/legal/copyright-notice">
|
||||
<NavBar>
|
||||
<ExternalLink href="https://matrix.org/legal/copyright-notice">
|
||||
Info
|
||||
</NavItem>
|
||||
<NavItem href="https://matrix.org/legal/privacy-notice">
|
||||
</ExternalLink>
|
||||
<ExternalLink href="https://matrix.org/legal/privacy-notice">
|
||||
Privacy
|
||||
</NavItem>
|
||||
<NavItem href="https://matrix.org/legal/terms-and-conditions">
|
||||
</ExternalLink>
|
||||
<ExternalLink href="https://matrix.org/legal/terms-and-conditions">
|
||||
Terms & Conditions
|
||||
</NavItem>
|
||||
</ExternalLink>
|
||||
</NavBar>
|
||||
</footer>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
21
frontend/src/components/NavBar.module.css
Normal file
21
frontend/src/components/NavBar.module.css
Normal file
@ -0,0 +1,21 @@
|
||||
/* Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
.nav-bar-items {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
gap: var(--cpd-space-4x);
|
||||
}
|
@ -12,12 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
const NavBar: React.FC<{
|
||||
className: string;
|
||||
children: React.ReactNode;
|
||||
}> = ({ className, children }) => (
|
||||
<nav className={className}>
|
||||
<ul className="flex flex-row gap-4 justify-center">{children}</ul>
|
||||
import styles from "./NavBar.module.css";
|
||||
|
||||
const NavBar: React.FC<React.PropsWithChildren<{}>> = ({ children }) => (
|
||||
<nav>
|
||||
<ul className={styles.navBarItems}>{children}</ul>
|
||||
</nav>
|
||||
);
|
||||
|
||||
|
30
frontend/src/components/NavItem.module.css
Normal file
30
frontend/src/components/NavItem.module.css
Normal file
@ -0,0 +1,30 @@
|
||||
/* Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
.nav-item {
|
||||
padding: var(--cpd-space-1x) var(--cpd-space-2x);
|
||||
color: var(--cpd-color-text-secondary);
|
||||
line-height: var(--cpd-space-6x);
|
||||
border-radius: var(--cpd-radius-pill-effect);
|
||||
}
|
||||
|
||||
.nav-item:hover {
|
||||
color: var(--cpd-color-text-primary);
|
||||
background-color: var(--cpd-color-bg-subtle-secondary);
|
||||
}
|
||||
|
||||
.nav-item[aria-current="page"] {
|
||||
color: var(--cpd-color-text-primary);
|
||||
}
|
@ -12,41 +12,37 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Link as CpdLink } from "@vector-im/compound-web";
|
||||
import { useAtomValue } from "jotai";
|
||||
|
||||
import { Link, Route, routeAtom } from "../Router";
|
||||
|
||||
type NavItemProps = {
|
||||
children: React.ReactNode;
|
||||
} & ({ route: Route; href?: never } | { route?: never; href: string });
|
||||
import styles from "./NavItem.module.css";
|
||||
|
||||
function isRoute(route: Route | undefined): route is Route {
|
||||
return !!route?.type;
|
||||
}
|
||||
|
||||
function isHref(href: string | undefined): href is string {
|
||||
return typeof href === "string";
|
||||
}
|
||||
|
||||
const NavItem: React.FC<NavItemProps> = ({ route, href, children }) => {
|
||||
const NavItem: React.FC<React.PropsWithChildren<{ route: Route }>> = ({
|
||||
route,
|
||||
children,
|
||||
}) => {
|
||||
const currentRoute = useAtomValue(routeAtom);
|
||||
return (
|
||||
<li className="m-1 mr-0">
|
||||
{isRoute(route) && (
|
||||
<Link
|
||||
route={route}
|
||||
className={currentRoute.type === route.type ? "active" : ""}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
)}
|
||||
{isHref(href) && (
|
||||
<a href={href} target="_blank" rel="noopenner noreferrer">
|
||||
{children}
|
||||
</a>
|
||||
)}
|
||||
<li>
|
||||
<Link
|
||||
className={styles.navItem}
|
||||
route={route}
|
||||
aria-current={currentRoute.type === route.type ? "page" : undefined}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
export const ExternalLink: React.FC<
|
||||
React.PropsWithChildren<{ href: string }>
|
||||
> = ({ href, children }) => (
|
||||
<li>
|
||||
<CpdLink href={href}>{children}</CpdLink>
|
||||
</li>
|
||||
);
|
||||
|
||||
export default NavItem;
|
||||
|
@ -99,13 +99,7 @@ const OAuth2Session: React.FC<Props> = ({ session }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Block
|
||||
className={`p-4 bg-grey-25 dark:bg-grey-450 rounded-lg ${
|
||||
data.finishedAt
|
||||
? "opacity-50 group-hover:opacity-100 transition-opacity"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
<Block>
|
||||
<Typography variant="body" bold>
|
||||
<Link
|
||||
route={{ type: "client", id: data.client.id }}
|
||||
|
@ -25,37 +25,10 @@
|
||||
@tailwind utilities;
|
||||
|
||||
body {
|
||||
/* XXX: I'm unsure why this is not part of the tokens */
|
||||
--cpd-radius-pill-effect: 9999px;
|
||||
|
||||
font: var(--cpd-font-body-md-regular);
|
||||
background: var(--cpd-color-bg-canvas-default);
|
||||
|
||||
width: 378px;
|
||||
margin: var(--cpd-space-10x) auto var(--cpd-space-6x) auto;
|
||||
}
|
||||
|
||||
.nav-bar a {
|
||||
color: var(--cpd-color-text-action-primary);
|
||||
}
|
||||
|
||||
.nav-bar .active {
|
||||
font-weight: var(--cpd-font-weight-semibold);
|
||||
}
|
||||
|
||||
.nav-bar li:not(:first-child) {
|
||||
list-style-type: disc;
|
||||
color: var(--cpd-color-text-secondary);
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
height: 1px;
|
||||
background: var(--cpd-color-gray-400);
|
||||
}
|
||||
|
||||
.session-icon {
|
||||
color: var(--cpd-color-icon-secondary);
|
||||
background: var(--cpd-color-bg-subtle-secondary);
|
||||
height: var(--cpd-space-10x);
|
||||
width: var(--cpd-space-10x);
|
||||
padding: var(--cpd-space-2x);
|
||||
border-radius: var(--cpd-space-1x);
|
||||
color: var(--cpd-color-text-primary);
|
||||
}
|
@ -42,6 +42,11 @@ module.exports = {
|
||||
"black-950": "#21262C",
|
||||
ice: "#F4F9FD",
|
||||
},
|
||||
fontWeight: {
|
||||
semibold: "var(--cpd-font-weight-semibold)",
|
||||
medium: "var(--cpd-font-weight-medium)",
|
||||
regular: "var(--cpd-font-weight-regular)",
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
|
@ -23,6 +23,13 @@ import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig((env) => ({
|
||||
base: "./",
|
||||
|
||||
css: {
|
||||
modules: {
|
||||
localsConvention: "camelCaseOnly",
|
||||
},
|
||||
},
|
||||
|
||||
build: {
|
||||
manifest: true,
|
||||
assetsDir: "",
|
||||
@ -37,6 +44,7 @@ export default defineConfig((env) => ({
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
plugins: [
|
||||
codegen(),
|
||||
|
||||
@ -104,6 +112,7 @@ export default defineConfig((env) => ({
|
||||
ext: ".zz",
|
||||
}),
|
||||
],
|
||||
|
||||
server: {
|
||||
base: "/account/",
|
||||
proxy: {
|
||||
@ -112,6 +121,7 @@ export default defineConfig((env) => ({
|
||||
"http://127.0.0.1:8080",
|
||||
},
|
||||
},
|
||||
|
||||
test: {
|
||||
coverage: {
|
||||
provider: "v8",
|
||||
|
Reference in New Issue
Block a user