+
setLogoInputValue(e.target.value)}
placeholder="Paste your logo link here"
- className="focus:outline-none placeholder:text-[#4D4D4D]"
+ className="focus:outline-none placeholder:text-[#4D4D4D] bg-transparent"
/>
Update
-
-
+
+
Use a logo sized 40 × 152 px for best results.
@@ -300,7 +294,6 @@ export default Style;
updateAppearance('fontFamily', item.value);
}}
startItem={
-
}
/> */
}
diff --git a/src/containers/tabsContainer/index.tsx b/src/containers/tabsContainer/index.tsx
index 3048882..11ec56d 100644
--- a/src/containers/tabsContainer/index.tsx
+++ b/src/containers/tabsContainer/index.tsx
@@ -1,39 +1,44 @@
-import Tabs from "../../components/Tabs";
-
-// inActive assets
-import auth from "/images/tabs/inActive/auth.svg";
-import palette from "/images/tabs/inActive/palette.svg";
-// import puzzle from "/images/tabs/inActive/puzzle.svg";
-
-// active assets
-import activeAuth from "/images/tabs/active/auth.svg";
-// import activePuzzle from "/images/tabs/active/puzzle.svg";
-import activePalette from "/images/tabs/active/palette.svg";
+import Tabs from '../../components/Tabs';
// pages
-import Auth from "./Auth";
+import Auth from './Auth';
+import Style from './Style';
// import Features from "./Features";
-import Style from "./Style";
+import {
+ ActiveAuth,
+ ActivePalette,
+ InActiveAuth,
+ InActivePalette,
+} from '../../assets/TabsIcon';
+import { useConfigContext } from '../../hooks/useConfigContext';
const TabsContainer = () => {
+ const { theme } = useConfigContext();
+
const tabsContent = [
{
- label: "Auth",
- inActiveImg: auth,
- activeImg: activeAuth,
+ label: 'Auth',
+ inActiveImg: (
+
+ ),
+ activeImg:
,
content:
,
},
// {
// label: "Features",
- // inActiveImg: puzzle,
- // activeImg: activePuzzle,
+ // inActiveImg:
,
+ // activeImg:
,
// content:
,
// },
{
- label: "Style",
- inActiveImg: palette,
- activeImg: activePalette,
+ label: 'Style',
+ inActiveImg: (
+
+ ),
+ activeImg: (
+
+ ),
content: ,
},
];
diff --git a/src/context/index.tsx b/src/context/index.tsx
index 64d7ec5..23543c5 100644
--- a/src/context/index.tsx
+++ b/src/context/index.tsx
@@ -4,8 +4,10 @@ import { IAppearance } from '../types';
import { LoginMethodType } from '../constants';
interface IConfigContext {
- theme: 'dark' | 'light' | 'random';
- setTheme: (theme: 'dark' | 'light' | 'random') => void;
+ theme: 'dark' | 'light';
+ setTheme: (theme: 'dark' | 'light') => void;
+ customLogo: string;
+ setCustomLogo: (logo: string) => void;
height: number;
setHeight: (height: number) => void;
appearance: IAppearance;
diff --git a/src/context/provider.tsx b/src/context/provider.tsx
index 368b69f..986fafc 100644
--- a/src/context/provider.tsx
+++ b/src/context/provider.tsx
@@ -1,13 +1,15 @@
-import { useState, ReactNode } from 'react';
+import { useState, ReactNode, useEffect } from 'react';
import { IAppearance } from '../types';
import { ConfigContext } from './index';
import { LoginMethodType } from '../constants';
import { defaultLightTheme } from '../constants/themes';
+import { handleLogoColor } from '../utils/handleLogoColor';
export const ConfigProvider = ({ children }: { children: ReactNode }) => {
- const [theme, setTheme] = useState<'light' | 'dark' | 'random'>('light');
+ const [theme, setTheme] = useState<'light' | 'dark'>('light');
const [height, setHeight] = useState(377);
+ const [customLogo, setCustomLogo] = useState('');
const [appearance, setAppearance] = useState
(defaultLightTheme);
const [loginMethods, setLoginMethods] = useState(['wallet']);
@@ -27,8 +29,18 @@ export const ConfigProvider = ({ children }: { children: ReactNode }) => {
logo: '/images/blux.svg',
});
setTheme('light');
+ setCustomLogo('');
};
+ useEffect(() => {
+ if (!customLogo) {
+ setAppearance((prev) => ({
+ ...prev,
+ logo: handleLogoColor(prev.background),
+ }));
+ }
+ }, [customLogo, appearance.background, setAppearance]);
+
const updateLoginMethods = (methods: LoginMethodType) => {
setLoginMethods(methods);
};
@@ -38,6 +50,8 @@ export const ConfigProvider = ({ children }: { children: ReactNode }) => {
value={{
height,
setHeight,
+ customLogo,
+ setCustomLogo,
theme,
setTheme,
appearance,
diff --git a/src/hooks/useCornerResize.tsx b/src/hooks/useCornerResize.tsx
index e31f158..557a4b1 100644
--- a/src/hooks/useCornerResize.tsx
+++ b/src/hooks/useCornerResize.tsx
@@ -47,11 +47,11 @@ export const useCornerResize = (
};
}, [resizingCorner, startPos, min, max]);
- const handleMouseDown = (corner: string, e: React.MouseEvent) => {
+ const handleResizeRadius = (corner: string, e: React.MouseEvent) => {
e.stopPropagation();
setResizingCorner(corner);
setStartPos({ x: e.clientX, y: e.clientY });
};
- return { radius, handleMouseDown };
+ return { radius, handleResizeRadius };
};
diff --git a/src/hooks/useOutlineResize.tsx b/src/hooks/useOutlineResize.tsx
new file mode 100644
index 0000000..562463d
--- /dev/null
+++ b/src/hooks/useOutlineResize.tsx
@@ -0,0 +1,72 @@
+import { useEffect, useState } from 'react';
+
+export const useOutlineResize = (
+ initialWidth: number = 1,
+ min: number = 0,
+ max: number = 6,
+) => {
+ const [width, setWidth] = useState(initialWidth);
+ const [activeHandle, setActiveHandle] = useState(null);
+ const [startPos, setStartPos] = useState<{ x: number; y: number } | null>(
+ null,
+ );
+
+ useEffect(() => {
+ if (!activeHandle || !startPos) return;
+
+ const handleMove = (e: MouseEvent) => {
+ const dx = e.clientX - startPos.x;
+ const dy = e.clientY - startPos.y;
+ let delta = 0;
+
+ if (activeHandle.includes('center')) {
+ switch (activeHandle) {
+ case 'top-center':
+ delta = -dy / 10;
+ break;
+ case 'bottom-center':
+ delta = dy / 10;
+ break;
+ case 'left-center':
+ delta = -dx / 10;
+ break;
+ case 'right-center':
+ delta = dx / 10;
+ break;
+ }
+ } else {
+ const dist = Math.sqrt(dx * dx + dy * dy);
+ const inward =
+ (activeHandle.includes('top') && dy > 0) ||
+ (activeHandle.includes('bottom') && dy < 0) ||
+ (activeHandle.includes('left') && dx > 0) ||
+ (activeHandle.includes('right') && dx < 0);
+
+ delta = inward ? dist / 8 : -dist / 8;
+ }
+
+ setWidth((prev) => Math.max(min, Math.min(max, prev + delta)));
+ setStartPos({ x: e.clientX, y: e.clientY });
+ };
+
+ const handleUp = () => {
+ setActiveHandle(null);
+ setStartPos(null);
+ };
+
+ window.addEventListener('mousemove', handleMove);
+ window.addEventListener('mouseup', handleUp);
+ return () => {
+ window.removeEventListener('mousemove', handleMove);
+ window.removeEventListener('mouseup', handleUp);
+ };
+ }, [activeHandle, startPos, min, max]);
+
+ const handleResizeOutlineWidth = (pos: string, e: React.MouseEvent) => {
+ e.stopPropagation();
+ setActiveHandle(pos);
+ setStartPos({ x: e.clientX, y: e.clientY });
+ };
+
+ return { width, handleResizeOutlineWidth };
+};
diff --git a/src/style/index.css b/src/style/index.css
index fe54df9..4ffe35b 100644
--- a/src/style/index.css
+++ b/src/style/index.css
@@ -2,6 +2,14 @@
@tailwind components;
@tailwind utilities;
+body {
+ @apply bg-white;
+}
+
+.dark body {
+ @apply bg-darkBg;
+}
+
/* Utility classes */
.center {
display: flex;
diff --git a/src/utils/handleLogoColor.tsx b/src/utils/handleLogoColor.tsx
new file mode 100644
index 0000000..64550d4
--- /dev/null
+++ b/src/utils/handleLogoColor.tsx
@@ -0,0 +1,7 @@
+import { isDarkBackground } from './randomTheme';
+
+export const handleLogoColor = (backgroundColor: string) => {
+ return isDarkBackground(backgroundColor)
+ ? '/images/whiteBluxLogo.svg'
+ : '/images/blux.svg';
+};
diff --git a/src/utils/randomTheme.tsx b/src/utils/randomTheme.tsx
index eea6cf7..50b51a2 100644
--- a/src/utils/randomTheme.tsx
+++ b/src/utils/randomTheme.tsx
@@ -6,10 +6,8 @@ const randomFrom = (arr: T[]) =>
const randomPx = (min: number, max: number) =>
`${Math.floor(Math.random() * (max - min + 1) + min)}px`;
-const randomFont = () => {
- const fonts = ['Manrope', 'JetbrainsMono', 'Playfair', 'ComicNeue'];
- return randomFrom(fonts);
-};
+const randomFont = () =>
+ randomFrom(['Manrope', 'JetbrainsMono', 'Playfair', 'ComicNeue']);
const randomHex = (min: number, max: number) => {
const r = Math.floor(Math.random() * (max - min) + min);
@@ -18,18 +16,23 @@ const randomHex = (min: number, max: number) => {
return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
};
-const getContrastColor = (hex: string) => {
- const c = hex.substring(1);
- const rgb = parseInt(c, 16);
- const r = (rgb >> 16) & 0xff;
- const g = (rgb >> 8) & 0xff;
- const b = rgb & 0xff;
- const brightness = (r * 299 + g * 587 + b * 114) / 1000;
- return brightness > 128 ? '#111111' : '#ffffff';
+export const isDarkBackground = (hex: string): boolean => {
+ const c = hex.replace('#', '');
+ const r = parseInt(c.substring(0, 2), 16);
+ const g = parseInt(c.substring(2, 4), 16);
+ const b = parseInt(c.substring(4, 6), 16);
+ const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
+ return luminance < 0.5;
};
-export const generateRandomTheme = (): IAppearance => {
- const isDark = Math.random() < 0.5;
+const getContrastColor = (hex: string) =>
+ isDarkBackground(hex) ? '#ffffff' : '#111111';
+
+export const generateRandomTheme = (
+ logo: string,
+ baseTheme: 'light' | 'dark' = 'light',
+): IAppearance => {
+ const isDark = baseTheme === 'dark';
const background = isDark ? randomHex(10, 60) : randomHex(220, 255);
const fieldBackground = isDark ? randomHex(20, 70) : randomHex(240, 255);
@@ -40,7 +43,7 @@ export const generateRandomTheme = (): IAppearance => {
const backdropColor = `${borderColor}33`;
return {
- logo: '',
+ logo: logo,
fontFamily: randomFont(),
textColor,
accentColor,
diff --git a/tailwind.config.js b/tailwind.config.js
index d79d765..cde7526 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,5 +1,6 @@
/** @type {import('tailwindcss').Config} */
export default {
+ darkMode: 'class', // <--- add this line
content: ['./src/**/*.{js,jsx,ts,tsx,css}'],
theme: {
extend: {
@@ -11,10 +12,17 @@ export default {
jetbrainsMono: ['JetBrainsMono', 'monospace'],
},
colors: {
+ white: '#ffffff',
primary: '#0D1292',
primaryDark: '#04062F',
lightPurple: '#CDCEEE',
lightGray: '#F8F9FA',
+ // Add dark theme variants
+ darkBg: '#000',
+ darkGray: '#0F0F0F',
+ darkBorder: '#333333',
+ darkField: '#1A1A1A',
+ darkFieldGray: '#121212',
},
screens: {
short: { raw: '(min-width: 1024px) and (max-height: 820px)' },