Skip to content

Commit b0ef7e1

Browse files
authored
Merge pull request #151 from Ehonrie/branding/theme
feat: Branding/theme
2 parents 48f39c2 + 9fcb410 commit b0ef7e1

7 files changed

Lines changed: 191 additions & 27 deletions

File tree

BRANDING.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# NiffyInsur Brand Guidelines
2+
3+
This document outlines the visual identity and styling standards for NiffyInsur.
4+
5+
## Color Palette
6+
7+
### Primary (Azure Blue)
8+
- **HSL**: `217 91% 60%`
9+
- **Hex**: `#3b82f6`
10+
- **Usage**: Buttons, links, primary brand elements.
11+
12+
### Secondary (Slate)
13+
- **HSL**: `222 47% 11%` (Foreground) / `0 0% 100%` (Background)
14+
- **Usage**: Typography, borders, subtle UI elements.
15+
16+
### Status Colors
17+
- **Success**: `142 71% 45%` (Green)
18+
- **Warning**: `48 96% 53%` (Yellow)
19+
- **Destructive**: `0 84% 60%` (Red)
20+
21+
## Typography
22+
23+
### Headings & Body
24+
- **Font**: [Inter](https://rsms.me/inter/)
25+
- **Weight**: 400 (Regular), 500 (Medium), 600 (Semi-Bold), 700 (Bold)
26+
27+
### Technical & Data
28+
- **Font**: [IBM Plex Mono](https://github.com/IBM/plex)
29+
- **Usage**: Addresses, transaction hashes, smart contract code, numbers.
30+
31+
## UI Principles
32+
33+
1. **Glassmorphism**: Use the `.glass` utility for cards and overlays to create depth.
34+
- Example: `<div className="glass rounded-lg p-6">...</div>`
35+
2. **Interactive States**:
36+
- **Hover**: Subtle scaling or opacity shift.
37+
- **Focus**: Clear Azure Blue ring (`focus-ring` utility).
38+
3. **Dark Mode**: Automatically respects system preferences, manual override available via `ThemeToggle`.
39+
40+
## Assets
41+
- **Logo Mark**: [icon.svg](/frontend/public/icon.svg)
42+
- **Manifest**: [site.webmanifest](/frontend/public/site.webmanifest)

frontend/public/icon.svg

Lines changed: 5 additions & 0 deletions
Loading

frontend/public/site.webmanifest

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "NiffyInsur",
3+
"short_name": "NiffyInsur",
4+
"icons": [
5+
{
6+
"src": "/android-chrome-192x192.png",
7+
"sizes": "192x192",
8+
"type": "image/png"
9+
},
10+
{
11+
"src": "/android-chrome-512x512.png",
12+
"sizes": "512x512",
13+
"type": "image/png"
14+
}
15+
],
16+
"theme_color": "#0062FF",
17+
"background_color": "#ffffff",
18+
"display": "standalone",
19+
"start_url": "/"
20+
}

frontend/src/app/globals.css

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,58 +5,58 @@
55
@layer base {
66
:root {
77
--background: 0 0% 100%;
8-
--foreground: 222.2 84% 4.9%;
8+
--foreground: 222 47% 11%;
99
--card: 0 0% 100%;
10-
--card-foreground: 222.2 84% 4.9%;
10+
--card-foreground: 222 47% 11%;
1111
--popover: 0 0% 100%;
12-
--popover-foreground: 222.2 84% 4.9%;
13-
--primary: 221.2 83.2% 53.3%;
12+
--popover-foreground: 222 47% 11%;
13+
--primary: 217 91% 60%; /* Stellar Azure Blue */
1414
--primary-foreground: 210 40% 98%;
15-
--secondary: 210 40% 96%;
16-
--secondary-foreground: 222.2 84% 4.9%;
17-
--muted: 210 40% 96%;
15+
--secondary: 210 40% 96.1%;
16+
--secondary-foreground: 222.2 47.4% 11.2%;
17+
--muted: 210 40% 96.1%;
1818
--muted-foreground: 215.4 16.3% 46.9%;
19-
--accent: 210 40% 96%;
20-
--accent-foreground: 222.2 84% 4.9%;
19+
--accent: 210 40% 96.1%;
20+
--accent-foreground: 222.2 47.4% 11.2%;
2121
--destructive: 0 84.2% 60.2%;
2222
--destructive-foreground: 210 40% 98%;
2323
--border: 214.3 31.8% 91.4%;
2424
--input: 214.3 31.8% 91.4%;
25-
--ring: 221.2 83.2% 53.3%;
26-
--radius: 0.5rem;
25+
--ring: 217 91% 60%;
26+
--radius: 0.75rem;
2727
--font-inter: 'Inter', system-ui, sans-serif;
2828
--font-ibm-mono: 'IBM Plex Mono', monospace;
2929
}
3030

3131
.dark {
32-
--background: 222.2 84% 4.9%;
32+
--background: 222 47% 4%;
3333
--foreground: 210 40% 98%;
34-
--card: 222.2 84% 4.9%;
34+
--card: 222 47% 6%;
3535
--card-foreground: 210 40% 98%;
36-
--popover: 222.2 84% 4.9%;
36+
--popover: 222 47% 6%;
3737
--popover-foreground: 210 40% 98%;
38-
--primary: 217.2 91.2% 59.8%;
39-
--primary-foreground: 222.2 84% 4.9%;
40-
--secondary: 217.2 32.6% 17.5%;
38+
--primary: 217 91% 60%;
39+
--primary-foreground: 222.2 47.4% 11.2%;
40+
--secondary: 217.2 32.6% 12%;
4141
--secondary-foreground: 210 40% 98%;
42-
--muted: 217.2 32.6% 17.5%;
42+
--muted: 217.2 32.6% 12%;
4343
--muted-foreground: 215 20.2% 65.1%;
44-
--accent: 217.2 32.6% 17.5%;
44+
--accent: 217.2 32.6% 12%;
4545
--accent-foreground: 210 40% 98%;
4646
--destructive: 0 62.8% 30.6%;
4747
--destructive-foreground: 210 40% 98%;
48-
--border: 217.2 32.6% 17.5%;
49-
--input: 217.2 32.6% 17.5%;
50-
--ring: 224.3 76.3% 94.1%;
48+
--border: 217.2 32.6% 12%;
49+
--input: 217.2 32.6% 12%;
50+
--ring: 217 91% 60%;
5151
}
5252
}
5353

5454
@layer base {
5555
* {
56-
@apply border-border;
56+
@apply border-border outline-ring/30;
5757
}
5858
body {
59-
@apply bg-background text-foreground;
59+
@apply bg-background text-foreground antialiased;
6060
}
6161
}
6262

frontend/src/app/layout.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,11 @@ export default async function RootLayout({ children }: { children: React.ReactNo
7070
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
7171
<link rel="manifest" href="/site.webmanifest" />
7272
</head>
73-
<body className="font-sans">
74-
{children}
75-
<Toaster />
73+
<body className="font-sans antialiased">
74+
<ThemeProvider defaultTheme="system" storageKey="niffyinsur-theme">
75+
{children}
76+
<Toaster />
77+
</ThemeProvider>
7678
</body>
7779
</html>
7880
);
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
'use client';
2+
3+
import * as React from 'react';
4+
5+
type Theme = 'dark' | 'light' | 'system';
6+
7+
interface ThemeProviderProps {
8+
children: React.ReactNode;
9+
defaultTheme?: Theme;
10+
storageKey?: string;
11+
}
12+
13+
interface ThemeProviderState {
14+
theme: Theme;
15+
setTheme: (theme: Theme) => void;
16+
}
17+
18+
const ThemeProviderContext = React.createContext<ThemeProviderState | undefined>(undefined);
19+
20+
export function ThemeProvider({
21+
children,
22+
defaultTheme = 'system',
23+
storageKey = 'niffyinsur-theme',
24+
...props
25+
}: ThemeProviderProps) {
26+
const [theme, setTheme] = React.useState<Theme>(
27+
() => (typeof window !== 'undefined' ? (localStorage.getItem(storageKey) as Theme) : defaultTheme) || defaultTheme
28+
);
29+
30+
React.useEffect(() => {
31+
const root = window.document.documentElement;
32+
33+
root.classList.remove('light', 'dark');
34+
35+
if (theme === 'system') {
36+
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
37+
? 'dark'
38+
: 'light';
39+
40+
root.classList.add(systemTheme);
41+
return;
42+
}
43+
44+
root.classList.add(theme);
45+
}, [theme]);
46+
47+
const value = React.useMemo(
48+
() => ({
49+
theme,
50+
setTheme: (theme: Theme) => {
51+
localStorage.setItem(storageKey, theme);
52+
setTheme(theme);
53+
},
54+
}),
55+
[theme, storageKey]
56+
);
57+
58+
return (
59+
<ThemeProviderContext.Provider {...props} value={value}>
60+
{children}
61+
</ThemeProviderContext.Provider>
62+
);
63+
}
64+
65+
export const useTheme = () => {
66+
const context = React.useContext(ThemeProviderContext);
67+
68+
if (context === undefined)
69+
throw new Error('useTheme must be used within a ThemeProvider');
70+
71+
return context;
72+
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use client';
2+
3+
import * as React from 'react';
4+
import { Moon, Sun } from 'lucide-react';
5+
import { Button } from '@/components/ui/button';
6+
import { useTheme } from '@/components/theme-provider';
7+
8+
export function ThemeToggle() {
9+
const { theme, setTheme } = useTheme();
10+
11+
return (
12+
<Button
13+
variant="ghost"
14+
size="icon"
15+
onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
16+
title="Toggle theme"
17+
>
18+
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
19+
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
20+
<span className="sr-only">Toggle theme</span>
21+
</Button>
22+
);
23+
}

0 commit comments

Comments
 (0)