mirror of
https://github.com/hanzoai/sign.git
synced 2026-10-21 01:21:51 +00:00
Set the app in Zen on hanzo.ai's palette, with pill buttons
The theme takes @hanzo/ui DESIGN.md's values: a true-black page, #0a0a0a surfaces, #171717 raised, #ededf1 ink and white-alpha hairlines in dark; white, #0a0a0a ink and black-alpha hairlines in light. Each is an opaque triplet, so Tailwind's alpha modifiers still apply. Type is Zen and Zen Mono from @hanzo/font, at Zen's own weights. Buttons are pills, the primary in the ink colour; the option cards built from a Button keep a card's corners, and the folder actions wrap on a phone rather than breaking a pill over two lines.
This commit is contained in:
+7
-19
@@ -1,23 +1,7 @@
|
||||
/* Zen and Zen Mono, the Hanzo family: @hanzo/font carries the faces and the @font-face. */
|
||||
@import '@hanzo/font/css';
|
||||
@import '@hanzo/esign-ui/styles/theme.css';
|
||||
|
||||
/* Inter Variable Fonts */
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
src: url('/fonts/inter-variablefont_opsz,wght.ttf') format('truetype-variations');
|
||||
font-weight: 100 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/* Inter Italic Variable Fonts */
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
src: url('/fonts/inter-italic-variablefont_opsz,wght.ttf') format('truetype-variations');
|
||||
font-weight: 100 900;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/* Caveat Variable Font */
|
||||
@font-face {
|
||||
font-family: 'Caveat';
|
||||
@@ -64,7 +48,11 @@
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--font-sans: 'Inter';
|
||||
--font-sans:
|
||||
Zen, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
|
||||
sans-serif;
|
||||
--font-mono:
|
||||
Zen Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;
|
||||
--font-signature: 'Caveat';
|
||||
--font-noto: 'Noto Sans', 'Noto Sans Korean', 'Noto Sans Japanese', 'Noto Sans Chinese';
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
||||
import type { TRecipientAccessAuth } from '@hanzo/esign-lib/types/document-auth';
|
||||
import { useZapMutation } from '@hanzo/esign-trpc/zap/react';
|
||||
import type {
|
||||
TAccessAuthRequest2FAEmailRequest,
|
||||
TAccessAuthRequest2FAEmailResponse,
|
||||
} from '@hanzo/esign-trpc/server/document-router/access-auth-request-2fa-email.types';
|
||||
import { useZapMutation } from '@hanzo/esign-trpc/zap/react';
|
||||
import { cn } from '@hanzo/esign-ui/lib/utils';
|
||||
import { Alert } from '@hanzo/esign-ui/primitives/alert';
|
||||
import { Button } from '@hanzo/esign-ui/primitives/button';
|
||||
@@ -157,7 +157,7 @@ export const AccessAuth2FAForm = ({ onSubmit, token, error }: AccessAuth2FAFormP
|
||||
<h3 className="text-lg font-semibold">
|
||||
<Trans>Choose verification method</Trans>
|
||||
</h3>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
<Trans>Please select how you'd like to receive your verification code.</Trans>
|
||||
</p>
|
||||
</div>
|
||||
@@ -172,7 +172,7 @@ export const AccessAuth2FAForm = ({ onSubmit, token, error }: AccessAuth2FAFormP
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="flex h-auto w-full justify-start gap-3 p-4"
|
||||
className="flex h-auto w-full justify-start gap-3 rounded-2xl p-4"
|
||||
onClick={async () => onMethodSelect('email')}
|
||||
disabled={isRequesting2FAEmail}
|
||||
>
|
||||
@@ -181,7 +181,7 @@ export const AccessAuth2FAForm = ({ onSubmit, token, error }: AccessAuth2FAFormP
|
||||
<div className="font-medium">
|
||||
<Trans>Email verification</Trans>
|
||||
</div>
|
||||
<div className="text-muted-foreground text-sm">
|
||||
<div className="text-sm text-muted-foreground">
|
||||
<Trans>We'll send a 6-digit code to your email</Trans>
|
||||
</div>
|
||||
</div>
|
||||
@@ -191,7 +191,7 @@ export const AccessAuth2FAForm = ({ onSubmit, token, error }: AccessAuth2FAFormP
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="flex h-auto w-full justify-start gap-3 p-4"
|
||||
className="flex h-auto w-full justify-start gap-3 rounded-2xl p-4"
|
||||
onClick={async () => onMethodSelect('authenticator')}
|
||||
disabled={isRequesting2FAEmail}
|
||||
>
|
||||
@@ -200,7 +200,7 @@ export const AccessAuth2FAForm = ({ onSubmit, token, error }: AccessAuth2FAFormP
|
||||
<div className="font-medium">
|
||||
<Trans>Authenticator app</Trans>
|
||||
</div>
|
||||
<div className="text-muted-foreground text-sm">
|
||||
<div className="text-sm text-muted-foreground">
|
||||
<Trans>Use your authenticator app to generate a code</Trans>
|
||||
</div>
|
||||
</div>
|
||||
@@ -222,7 +222,7 @@ export const AccessAuth2FAForm = ({ onSubmit, token, error }: AccessAuth2FAFormP
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div className="text-muted-foreground text-sm">
|
||||
<div className="text-sm text-muted-foreground">
|
||||
{selectedMethod === 'email' ? (
|
||||
<Trans>
|
||||
We've sent a 6-digit verification code to your email. Please enter it below to
|
||||
@@ -268,7 +268,7 @@ export const AccessAuth2FAForm = ({ onSubmit, token, error }: AccessAuth2FAFormP
|
||||
|
||||
{expiresAt && millisecondsRemaining !== null && (
|
||||
<div
|
||||
className={cn('text-muted-foreground mt-2 text-center text-sm', {
|
||||
className={cn('mt-2 text-center text-sm text-muted-foreground', {
|
||||
'text-destructive': millisecondsRemaining <= 0,
|
||||
})}
|
||||
>
|
||||
|
||||
@@ -123,7 +123,7 @@ export const DocumentSigningAuthDialog = ({
|
||||
{/* Show chooser if no auth type is selected and there are multiple options */}
|
||||
{!selectedAuthType && validAuthTypes.length > 1 && (
|
||||
<div className="space-y-4">
|
||||
<p className="text-muted-foreground text-sm">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
<Trans>Choose your preferred authentication method:</Trans>
|
||||
</p>
|
||||
<div className="grid gap-2">
|
||||
@@ -132,7 +132,7 @@ export const DocumentSigningAuthDialog = ({
|
||||
key={authType}
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="h-auto justify-start p-4"
|
||||
className="h-auto justify-start rounded-2xl p-4"
|
||||
onClick={() => setSelectedAuthType(authType)}
|
||||
>
|
||||
<div className="text-left">
|
||||
@@ -145,7 +145,7 @@ export const DocumentSigningAuthDialog = ({
|
||||
.exhaustive()}
|
||||
</div>
|
||||
|
||||
<div className="text-muted-foreground text-sm">
|
||||
<div className="text-sm text-muted-foreground">
|
||||
{match(authType)
|
||||
.with(DocumentAuth.ACCOUNT, () => <Trans>Sign in to your account</Trans>)
|
||||
.with(DocumentAuth.PASSKEY, () => (
|
||||
|
||||
@@ -100,7 +100,7 @@ export const FolderGrid = ({ type, parentId }: FolderGridProps) => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4 sm:flex-row sm:justify-end">
|
||||
<div className="flex flex-wrap gap-4 sm:flex-row sm:justify-end">
|
||||
<EnvelopeUploadButton type={type} folderId={parentId || undefined} />
|
||||
|
||||
<EnvelopeImportMenu type={type} folderId={parentId || undefined} />
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
"@hanzo/esign-tailwind-config": "*",
|
||||
"@hanzo/esign-trpc": "*",
|
||||
"@hanzo/esign-ui": "*",
|
||||
"@hanzo/font": "1.9.3",
|
||||
"@zap-proto/zap": "^1.6.0",
|
||||
"@zap-proto/web": "^1.0.0",
|
||||
"ws": "^8.21.3",
|
||||
|
||||
Generated
+10
@@ -123,6 +123,7 @@
|
||||
"@hanzo/esign-tailwind-config": "*",
|
||||
"@hanzo/esign-trpc": "*",
|
||||
"@hanzo/esign-ui": "*",
|
||||
"@hanzo/font": "1.9.3",
|
||||
"@hanzo/insights": "1.358.2",
|
||||
"@hanzo/insights-node": "5.26.2",
|
||||
"@hono/node-server": "^2.1.1",
|
||||
@@ -3552,6 +3553,15 @@
|
||||
"resolved": "packages/ui",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@hanzo/font": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@hanzo/font/-/font-1.9.3.tgz",
|
||||
"integrity": "sha512-PVCyIFMp/wBVfLsWczVWC3VVxbUzlTDwc/LBRgyT6Fizk09aACq8ByRmbJp0FGKVd1BbUDeekvfv0g1eoj4OvQ==",
|
||||
"license": "SIL OPEN FONT LICENSE",
|
||||
"peerDependencies": {
|
||||
"next": ">=13.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@hanzo/insights": {
|
||||
"version": "1.358.2",
|
||||
"resolved": "https://registry.npmjs.org/@hanzo/insights/-/insights-1.358.2.tgz",
|
||||
|
||||
@@ -10,9 +10,17 @@ module.exports = {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ['var(--font-sans)', ...fontFamily.sans],
|
||||
mono: ['var(--font-mono)', ...fontFamily.mono],
|
||||
signature: ['var(--font-signature)'],
|
||||
noto: ['var(--font-noto)'],
|
||||
},
|
||||
// Zen is variable; these are where it reads on a screen (@hanzo/ui DESIGN.md §1).
|
||||
fontWeight: {
|
||||
normal: '497',
|
||||
medium: '606',
|
||||
semibold: '680',
|
||||
bold: '760',
|
||||
},
|
||||
zIndex: {
|
||||
9999: '9999',
|
||||
},
|
||||
|
||||
@@ -7,8 +7,9 @@ import { Loader } from 'lucide-react';
|
||||
|
||||
import { cn } from '../lib/utils';
|
||||
|
||||
// Pills, as on hanzo.ai: the primary is the ink colour (white on black, black on white).
|
||||
const buttonVariants = cva(
|
||||
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
|
||||
'inline-flex items-center justify-center rounded-full text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
@@ -23,8 +24,8 @@ const buttonVariants = cva(
|
||||
},
|
||||
size: {
|
||||
default: 'h-10 py-2 px-4',
|
||||
sm: 'h-9 px-3 rounded-md',
|
||||
lg: 'h-11 px-8 rounded-md',
|
||||
sm: 'h-9 px-3',
|
||||
lg: 'h-11 px-8',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
@@ -48,8 +49,7 @@ const loaderVariants = cva('mr-2 animate-spin', {
|
||||
});
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean;
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,45 +3,48 @@
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
/* Light: hanzo.ai's light palette (@hanzo/tokens `light`). A white page, #0a0a0a ink, and
|
||||
hairlines that are DESIGN.md's black-alpha rungs composited on white: border 10%, a
|
||||
control's edge 15%, hover 5%. Every value is opaque so Tailwind's `/alpha` modifiers apply. */
|
||||
:root,
|
||||
.dark-mode-disabled {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 0 0% 11%;
|
||||
--foreground: 0 0% 4%;
|
||||
|
||||
--muted: 0 0% 96%;
|
||||
--muted-foreground: 0 0% 45%;
|
||||
--muted: 0 0% 95%;
|
||||
--muted-foreground: 0 0% 32%;
|
||||
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 0 0% 11%;
|
||||
--popover-foreground: 0 0% 4%;
|
||||
|
||||
--card: 0 0% 100%;
|
||||
--card-border: 0 0% 91%;
|
||||
--card-border: 0 0% 90%;
|
||||
--card-border-tint: 115 115 115;
|
||||
--card-foreground: 0 0% 11%;
|
||||
--card-foreground: 0 0% 4%;
|
||||
|
||||
--field-card: 0 0% 96%;
|
||||
--field-card-border: 0 0% 85%;
|
||||
--field-card-foreground: 0 0% 11%;
|
||||
--field-card-foreground: 0 0% 4%;
|
||||
|
||||
--widget: 0 0% 97%;
|
||||
--widget-foreground: 0 0% 95%;
|
||||
|
||||
--border: 0 0% 91%;
|
||||
--input: 0 0% 91%;
|
||||
--border: 0 0% 90%;
|
||||
--input: 0 0% 85%;
|
||||
|
||||
--primary: 0 0% 0%;
|
||||
--primary-foreground: 0 0% 100%;
|
||||
--primary: 0 0% 4%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
|
||||
--secondary: 0 0% 96%;
|
||||
--secondary-foreground: 0 0% 11%;
|
||||
--secondary: 0 0% 95%;
|
||||
--secondary-foreground: 0 0% 4%;
|
||||
|
||||
--accent: 0 0% 96%;
|
||||
--accent-foreground: 0 0% 11%;
|
||||
--accent: 0 0% 95%;
|
||||
--accent-foreground: 0 0% 4%;
|
||||
|
||||
--destructive: 0 72% 51%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
|
||||
--ring: 0 0% 45%;
|
||||
--ring: 0 0% 50%;
|
||||
|
||||
--radius: 0.5rem;
|
||||
|
||||
@@ -58,43 +61,45 @@
|
||||
--envelope-editor-background: 0 0% 98%;
|
||||
}
|
||||
|
||||
/* Black page. Depth is the ramp above it: surface 6-7%, hover 16%, edge 18%. No hue at any step. */
|
||||
/* Dark, the house theme: @hanzo/ui DESIGN.md §4. A true-black page, #0a0a0a
|
||||
surfaces, #171717 for hover and anything raised, and white-alpha hairlines composited
|
||||
on black (border 10%, a control's edge 15%). Ink is #ededf1, never pure white on black. */
|
||||
.dark:not(.dark-mode-disabled) {
|
||||
--background: 0 0% 0%;
|
||||
--foreground: 0 0% 97%;
|
||||
--foreground: 240 11% 94%;
|
||||
|
||||
--muted: 0 0% 10%;
|
||||
--muted-foreground: 0 0% 65%;
|
||||
--muted: 0 0% 9%;
|
||||
--muted-foreground: 240 5% 65%;
|
||||
|
||||
--popover: 0 0% 7%;
|
||||
--popover-foreground: 0 0% 90%;
|
||||
--popover: 0 0% 4%;
|
||||
--popover-foreground: 240 11% 94%;
|
||||
|
||||
--card: 0 0% 6%;
|
||||
--card-border: 0 0% 18%;
|
||||
--card: 0 0% 4%;
|
||||
--card-border: 0 0% 10%;
|
||||
--card-border-tint: 115 115 115;
|
||||
--card-foreground: 0 0% 95%;
|
||||
--card-foreground: 240 11% 94%;
|
||||
|
||||
--widget: 0 0% 6%;
|
||||
--widget-foreground: 0 0% 18%;
|
||||
--widget: 0 0% 4%;
|
||||
--widget-foreground: 0 0% 10%;
|
||||
|
||||
--border: 0 0% 18%;
|
||||
--input: 0 0% 18%;
|
||||
--border: 0 0% 10%;
|
||||
--input: 0 0% 15%;
|
||||
|
||||
--field-border: 0 0% 91%;
|
||||
|
||||
--primary: 0 0% 100%;
|
||||
--primary: 0 0% 98%;
|
||||
--primary-foreground: 0 0% 0%;
|
||||
|
||||
--secondary: 0 0% 12%;
|
||||
--secondary: 0 0% 9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
|
||||
--accent: 0 0% 16%;
|
||||
--accent: 0 0% 9%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
|
||||
--destructive: 0 87% 62%;
|
||||
--destructive-foreground: 0 87% 19%;
|
||||
|
||||
--ring: 0 0% 45%;
|
||||
--ring: 0 0% 40%;
|
||||
|
||||
--radius: 0.5rem;
|
||||
|
||||
@@ -109,8 +114,9 @@
|
||||
@apply border-border;
|
||||
}
|
||||
|
||||
/* Zen's book weight is 497, not the generic 400 (@hanzo/ui DESIGN.md §1). */
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
@apply bg-background font-normal text-foreground;
|
||||
font-feature-settings:
|
||||
'rlig' 1,
|
||||
'calt' 1;
|
||||
|
||||
Reference in New Issue
Block a user