Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/apollo-vertex/app/_meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export default {
"shadcn-components": "Shadcn Components",
"vertex-components": "Vertex Components",
themes: "Themes",
"haidy-theme-option": "Haidy Theme Option",
localization: "Localization",
};
53 changes: 53 additions & 0 deletions apps/apollo-vertex/app/haidy-theme-option/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { HaidyThemeDashboard } from '@/templates/HaidyThemeDashboard';
import { HaidyThemeDashboardAccessible } from '@/templates/HaidyThemeDashboardAccessible';
import { HaidyThemeLoanQC } from '@/templates/HaidyThemeLoanQC';
import { FullscreenWrapper } from '@/templates/FullscreenWrapper';

# Haidy Theme Option

A frosted glass UI aesthetic applied to the Invoice Processing dashboard. Soft translucent panels, gentle glows, and minimal contrast.

## Original

<div className="not-prose my-8 rounded-lg overflow-hidden" style={{ height: '700px' }}>
<div className="[&_.h-screen]:!h-full h-full">
<FullscreenWrapper>
<HaidyThemeDashboard />
</FullscreenWrapper>
</div>
</div>

## Accessible Version (WCAG AA)

All text meets WCAG 2.1 AA contrast requirements (4.5:1 for normal text, 3:1 for large text and non-text elements). Hierarchy is preserved through font weight and size instead of low-contrast colors.

| Change | Before | After | Contrast |
|---|---|---|---|
| Dates, subtitles | `slate-400` (2.29:1) | `slate-600` | 5.92:1 |
| Labels, headers | `slate-500` (4.26:1) | `slate-600` | 5.92:1 |
| Active nav | `primary` (~2.90:1) | `#0e7490` dark teal | 4.81:1 |
| Failed badge | `rose-600` (4.05:1) | `rose-700` | ~5.4:1 |
| Positive change | `emerald-600/80` (2.64:1) | `emerald-700` | 4.90:1 |
| Negative change | `rose-500/80` (2.74:1) | `rose-600` | 4.76:1 |
| Chart axis | `#94a3b8` (2.29:1) | `#475569` | 5.92:1 |
| Icons | `slate-400` (2.29:1) | `slate-500` | 4.26:1 (3:1 req for non-text) |

<div className="not-prose my-8 rounded-lg overflow-hidden" style={{ height: '700px' }}>
<div className="[&_.h-screen]:!h-full h-full">
<FullscreenWrapper>
<HaidyThemeDashboardAccessible />
</FullscreenWrapper>
</div>
</div>

## Loan Processing QC — Frosted Glass Theme

The same accessible frosted glass aesthetic applied to the Loan Processing QC screen. Three-panel layout with compliance rules sidebar, dual document viewers, and glassmorphism buttons with hover states.

<div className="not-prose my-8 rounded-lg overflow-hidden" style={{ height: '700px' }}>
<div className="[&_.h-screen]:!h-full h-full">
<FullscreenWrapper>
<HaidyThemeLoanQC />
</FullscreenWrapper>
</div>
</div>
2 changes: 1 addition & 1 deletion apps/apollo-vertex/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";
import "./.next/dev/types/routes.d.ts";

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
45 changes: 45 additions & 0 deletions apps/apollo-vertex/templates/FullscreenWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use client";

import { Maximize2, Minimize2 } from "lucide-react";
import { useCallback, useEffect, useRef, useState, type PropsWithChildren } from "react";

export function FullscreenWrapper({ children }: PropsWithChildren) {
const containerRef = useRef<HTMLDivElement>(null);
const [isFullscreen, setIsFullscreen] = useState(false);

const toggleFullscreen = useCallback(() => {
if (!containerRef.current) return;

if (!document.fullscreenElement) {
containerRef.current.requestFullscreen();
} else {
document.exitFullscreen();
}
}, []);

useEffect(() => {
const onChange = () => {
setIsFullscreen(!!document.fullscreenElement);
};
document.addEventListener("fullscreenchange", onChange);
return () => document.removeEventListener("fullscreenchange", onChange);
}, []);

return (
<div ref={containerRef} className="relative h-full">
{children}
<button
type="button"
onClick={toggleFullscreen}
className="absolute bottom-4 right-4 z-50 size-9 flex items-center justify-center rounded-xl bg-white/60 backdrop-blur-[12px] border border-white/30 shadow-[0_0_20px_0_rgba(200,215,235,0.25)] text-slate-500 hover:text-slate-700 hover:bg-white/80 transition-colors cursor-pointer"
title={isFullscreen ? "Exit fullscreen" : "Fullscreen"}
>
{isFullscreen ? (
<Minimize2 className="size-4 stroke-[1.5]" />
) : (
<Maximize2 className="size-4 stroke-[1.5]" />
)}
</button>
</div>
);
}
Loading
Loading