Skip to content

Commit 265f425

Browse files
committed
feat: new homepages
1 parent d1059b6 commit 265f425

File tree

6 files changed

+885
-394
lines changed

6 files changed

+885
-394
lines changed

src/components/LuxeArt.jsx

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import React, { useMemo } from 'react';
2+
3+
const LuxeArt = ({ seed = 'luxe', className }) => {
4+
// LCG Random Generator
5+
const rng = useMemo(() => {
6+
let h = 0xdeadbeef;
7+
for (let i = 0; i < seed.length; i++) {
8+
h = Math.imul(h ^ seed.charCodeAt(i), 2654435761);
9+
}
10+
return () => {
11+
h = Math.imul(h ^ (h >>> 16), 2246822507);
12+
h = Math.imul(h ^ (h >>> 13), 3266489909);
13+
return ((h ^= h >>> 16) >>> 0) / 4294967296;
14+
};
15+
}, [seed]);
16+
17+
const shapes = useMemo(() => {
18+
const r = rng; // concise alias
19+
const items = [];
20+
21+
// Palette Generation
22+
const baseHue = Math.floor(r() * 360);
23+
// const saturation = 20 + r() * 20; // Low saturation for Luxe feel
24+
// const lightness = 80 + r() * 10; // High lightness
25+
26+
// Generate organic curves (Silk/Marble effect)
27+
const curveCount = 8 + Math.floor(r() * 5);
28+
29+
for (let i = 0; i < curveCount; i++) {
30+
const points = [];
31+
const segments = 4;
32+
const startY = r() * 100;
33+
34+
points.push({ x: 0, y: startY });
35+
36+
for (let j = 1; j <= segments; j++) {
37+
points.push({
38+
x: (j / segments) * 100,
39+
y: startY + (r() - 0.5) * 50 // Variation
40+
});
41+
}
42+
43+
// Create smooth bezier path
44+
let d = `M ${points[0].x} ${points[0].y}`;
45+
for (let j = 0; j < points.length - 1; j++) {
46+
const p0 = points[j];
47+
const p1 = points[j + 1];
48+
// Simple catmull-rom or quadratic approx?
49+
// Let's use simple cubic bezier for smoothness
50+
const cp1x = p0.x + (p1.x - p0.x) / 2;
51+
const cp1y = p0.y;
52+
const cp2x = p0.x + (p1.x - p0.x) / 2;
53+
const cp2y = p1.y;
54+
d += ` C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${p1.x} ${p1.y}`;
55+
}
56+
57+
// Close the shape to bottom/corners to form a fillable area
58+
d += ` L 100 100 L 0 100 Z`;
59+
60+
const opacity = 0.05 + r() * 0.15;
61+
// const color = `hsla(${baseHue + (r() - 0.5) * 40}, ${saturation}%, ${lightness - i * 5}%, ${opacity})`;
62+
// Force grayscale/gold/bronze tones for "Luxe"
63+
const isGold = r() > 0.8;
64+
const hue = isGold ? 45 : baseHue; // 45 is roughly gold
65+
const sat = isGold ? 60 : 0; // Grayscale or Gold
66+
const lit = isGold ? 60 : 90 - i * 5;
67+
68+
items.push({
69+
d,
70+
fill: `hsla(${hue}, ${sat}%, ${lit}%, ${opacity})`,
71+
stroke: `hsla(${hue}, ${sat}%, ${lit - 20}%, ${opacity * 2})`
72+
});
73+
}
74+
75+
// Add some noise texture specks
76+
const specks = [];
77+
for(let k=0; k<50; k++) {
78+
specks.push({
79+
cx: r() * 100,
80+
cy: r() * 100,
81+
r: r() * 0.3,
82+
fill: 'rgba(0,0,0,0.1)'
83+
});
84+
}
85+
86+
return { curves: items, specks };
87+
}, [rng]);
88+
89+
return (
90+
<div className={`w-full h-full bg-[#EBEBEB] overflow-hidden relative ${className}`}>
91+
<svg
92+
viewBox="0 0 100 100"
93+
preserveAspectRatio="none"
94+
className="w-full h-full"
95+
>
96+
{shapes.curves.map((shape, i) => (
97+
<path
98+
key={`curve-${i}`}
99+
d={shape.d}
100+
fill={shape.fill}
101+
stroke={shape.stroke}
102+
strokeWidth="0.1"
103+
style={{ mixBlendMode: 'multiply' }}
104+
/>
105+
))}
106+
{shapes.specks.map((s, i) => (
107+
<circle key={`speck-${i}`} cx={s.cx} cy={s.cy} r={s.r} fill={s.fill} />
108+
))}
109+
</svg>
110+
</div>
111+
);
112+
};
113+
114+
export default LuxeArt;

src/context/VisualSettingsContext.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export const VisualSettingsProvider = ({ children }) => {
5555
const [sidebarColor, setSidebarColor] = usePersistentState('sidebar-color','default');
5656
const [isSplashTextEnabled, setIsSplashTextEnabled] = usePersistentState('is-splash-text-enabled',true);
5757
const [isAppFullscreen, setIsAppFullscreen] = usePersistentState('is-app-fullscreen', false);
58+
const [fezcodexTheme, setFezcodexTheme] = usePersistentState('fezcodex-theme', 'brutalist'); // 'brutalist' or 'luxe'
5859

5960
const [isSidebarOpen, setIsSidebarOpen] = React.useState(window.innerWidth > 768);
6061
useEffect(() => {
@@ -337,6 +338,8 @@ export const VisualSettingsProvider = ({ children }) => {
337338
toggleSplashText,
338339
isAppFullscreen,
339340
toggleAppFullscreen,
341+
fezcodexTheme,
342+
setFezcodexTheme,
340343
isSidebarOpen,
341344
setIsSidebarOpen,
342345
toggleSidebar,

0 commit comments

Comments
 (0)