diff --git a/public/brands/polinetwork-mono.svg b/public/brands/polinetwork-mono.svg new file mode 100644 index 0000000..db83a97 --- /dev/null +++ b/public/brands/polinetwork-mono.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/src/components/dev-login.tsx b/src/components/dev-login.tsx index e100a31..0a0cfd6 100644 --- a/src/components/dev-login.tsx +++ b/src/components/dev-login.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useId, useState } from "react"; import { FlaskConical, TriangleAlert } from "lucide-react"; import { cn } from "cn"; import { buttonVariants } from "@/components/ui/button"; @@ -20,6 +20,8 @@ import { export function DevLoginPanel({ redirect }: { redirect: string }) { const [personas, setPersonas] = useState([]); const [oauthQuery, setOauthQuery] = useState(); + const [open, setOpen] = useState(false); + const listId = useId(); useEffect(() => { // Read from the address bar as Better Auth's client does, so the signature still matches. @@ -40,41 +42,67 @@ export function DevLoginPanel({ redirect }: { redirect: string }) { return (
-
-

-

-

- Local development only. Signs you in as a test person, no account needed. -

+

+ +

+ -
); } diff --git a/src/components/login-page.tsx b/src/components/login-page.tsx index 7352bdf..09b4661 100644 --- a/src/components/login-page.tsx +++ b/src/components/login-page.tsx @@ -20,7 +20,7 @@ const providers = [ export function LoginLayout({ children, wide = false }: { children: ReactNode; wide?: boolean }) { return ( -
+
@@ -37,7 +37,6 @@ export function LoginLayout({ children, wide = false }: { children: ReactNode; w {children} -

PoliNetwork APS

@@ -225,10 +224,18 @@ export function LoginPage({ callbackURL = "/" }: { callbackURL?: string }) {

)} +

- {oauthFlow - ? "After signing in you'll review what the application can access before anything is shared." - : "New here? Continue with an account to get started. You can add a passkey once you're signed in."} + By continuing, you acknowledge that you have read and understood our{" "} + + Privacy Policy. +

diff --git a/src/components/rbac/catalog-search.tsx b/src/components/rbac/catalog-search.tsx index 80fe17b..a5f67a6 100644 --- a/src/components/rbac/catalog-search.tsx +++ b/src/components/rbac/catalog-search.tsx @@ -1,9 +1,62 @@ import { useRef, type ReactNode } from "react"; import { Search, X } from "lucide-react"; +import { cn } from "cn"; import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; +/** The search box on its own, for pages that lay out the rest of the toolbar themselves. */ +export function SearchField({ + kind, + query, + onQueryChange, + className, + inputClassName, +}: { + kind: "roles" | "permissions"; + query: string; + onQueryChange: (query: string) => void; + className?: string; + inputClassName?: string; +}) { + const input = useRef(null); + + return ( +
+
+ ); +} + export function CatalogSearch({ kind, query, @@ -19,40 +72,15 @@ export function CatalogSearch({ total: number; children?: ReactNode; }) { - const input = useRef(null); - return (
-
-
+

{query.trim() ? `${count} of ${total}` : total} {kind}

diff --git a/src/components/rbac/icons.tsx b/src/components/rbac/icons.tsx new file mode 100644 index 0000000..01ee946 --- /dev/null +++ b/src/components/rbac/icons.tsx @@ -0,0 +1,48 @@ +import { CircleQuestionMark, Crown, KeyRound, type LucideProps, Plus, Users } from "lucide-react"; +import { cn } from "cn"; + +/* + * The eRBACo designs draw lucide's glyphs with their own line widths, given in pixels at the size + * each icon renders. `absoluteStrokeWidth` keeps them at those pixels, which is why every icon + * here takes a fixed `size` rather than a size class. + */ + +type IconProps = Omit; + +export function PermissionsIcon({ className, ...props }: IconProps) { + // The design's key hole is a heavier dot than the outline around it. + return ( +