feat(UX): update theme selector in preferences modal

This commit is contained in:
Bijin A B
2025-12-30 03:22:25 +05:30
parent 6d77cacbc4
commit 038fdbb040
4 changed files with 68 additions and 57 deletions

View File

@@ -2,28 +2,30 @@ import styled from 'styled-components';
import { rgba } from 'polished';
const StyledWrapper = styled.div`
.theme-mode-selector {
display: flex;
gap: 16px;
margin-bottom: 24px;
}
padding: 8px 0;
.theme-mode-option {
display: flex;
align-items: center;
gap: 6px;
cursor: pointer;
}
border: 1px solid ${(props) => props.theme.input.border};
border-radius: ${(props) => props.theme.border.radius.md};
box-shadow: none;
padding: 6px 8px;
width: auto;
.theme-variant-section {
margin-top: 20px;
&.selected {
border: 1px solid ${(props) => props.theme.accents.primary};
background: ${(props) => rgba(props.theme.accents.primary, 0.07)};
cursor: default;
}
&:hover {
border: 1px solid ${(props) => props.theme.accents.primary};
}
}
.theme-variant-label {
font-size: ${(props) => props.theme.font.size.sm};
color: ${(props) => props.theme.colors.text.muted};
margin-bottom: 12px;
font-weight: 500;
}
.theme-variants {
@@ -41,7 +43,7 @@ const StyledWrapper = styled.div`
border-radius: ${(props) => props.theme.border.radius.md};
cursor: pointer;
transition: all 0.15s ease;
min-width: 120px;
min-width: 165px;
&:hover {
border-color: ${(props) => props.theme.input.focusBorder};
@@ -50,6 +52,7 @@ const StyledWrapper = styled.div`
&.selected {
border-color: ${(props) => props.theme.accents.primary};
background: ${(props) => rgba(props.theme.accents.primary, 0.07)};
cursor: default;
}
}
@@ -90,7 +93,7 @@ const StyledWrapper = styled.div`
.section-divider {
height: 1px;
background: ${(props) => props.theme.input.border};
margin: 24px 0;
margin: 15px 0;
}
`;

View File

@@ -1,12 +1,16 @@
import React from 'react';
import { rgba } from 'polished';
import { useTheme } from 'providers/Theme';
import { getLightThemes, getDarkThemes } from 'themes/index';
import themes, { getLightThemes, getDarkThemes } from 'themes/index';
import { IconBrightnessUp, IconMoon, IconDeviceDesktop } from '@tabler/icons';
import StyledWrapper from './StyledWrapper';
const ThemePreview = ({ themeId, isDark }) => {
const bgColor = isDark ? '#1e1e1e' : '#ffffff';
const sidebarColor = isDark ? '#252526' : '#f8f8f8';
const lineColor = isDark ? '#3d3d3d' : '#e5e5e5';
const theme = themes[themeId] || themes[isDark ? 'dark' : 'light'];
const bgColor = theme.background.base;
const sidebarColor = theme.sidebar.bg;
const lineColor = rgba(theme.brand, 0.5);
return (
<div className="theme-preview" style={{ background: bgColor, border: `1px solid ${lineColor}` }}>
@@ -44,6 +48,12 @@ const Themes = () => {
const lightThemes = getLightThemes();
const darkThemes = getDarkThemes();
const themeModes = [
{ key: 'light', label: 'Light', icon: IconBrightnessUp },
{ key: 'dark', label: 'Dark', icon: IconMoon },
{ key: 'system', label: 'System', icon: IconDeviceDesktop }
];
const handleModeChange = (mode) => {
setStoredTheme(mode);
};
@@ -69,40 +79,30 @@ const Themes = () => {
<div className="flex flex-col gap-4 w-full">
<div>
<div className="section-header">Appearance</div>
<div className="theme-mode-selector">
<label className="theme-mode-option">
<input
type="radio"
name="theme-mode"
value="light"
checked={storedTheme === 'light'}
onChange={() => handleModeChange('light')}
/>
<span>Light</span>
</label>
<label className="theme-mode-option">
<input
type="radio"
name="theme-mode"
value="dark"
checked={storedTheme === 'dark'}
onChange={() => handleModeChange('dark')}
/>
<span>Dark</span>
</label>
<label className="theme-mode-option">
<input
type="radio"
name="theme-mode"
value="system"
checked={storedTheme === 'system'}
onChange={() => handleModeChange('system')}
/>
<span>System</span>
</label>
</div>
</div>
<div className="flex gap-3 theme-mode-selector justify-start">
{themeModes.map((mode) => {
const Icon = mode.icon;
const isSelected = storedTheme === mode.key;
return (
<button
key={mode.key}
onClick={() => handleModeChange(mode.key)}
className={`theme-mode-option relative ${isSelected ? 'selected' : ''}`}
>
<div className="flex items-center justify-start gap-2">
<Icon size={16} strokeWidth={1.5} />
<span>{mode.label}</span>
</div>
</button>
);
})}
</div>
<div className="section-divider" />
{storedTheme === 'light' && (
<>
{renderThemeVariants(lightThemes, themeVariantLight, setThemeVariantLight, 'Light Theme')}

View File

@@ -1,6 +1,7 @@
import Modal from 'components/Modal/index';
import classnames from 'classnames';
import React, { useState } from 'react';
import { IconSettings, IconPalette, IconBrowser, IconUserCircle, IconKeyboard, IconZoomQuestion, IconSquareLetterB } from '@tabler/icons';
import Support from './Support';
import General from './General';
@@ -59,24 +60,31 @@ const Preferences = ({ onClose }) => {
<div className="flex flex-row gap-2 mx-[-1rem] !my-[-1.5rem] py-2">
<div className="flex flex-col items-center tabs" role="tablist">
<div className={getTabClassname('general')} role="tab" onClick={() => setTab('general')}>
<IconSettings size={16} strokeWidth={1.5} />
General
</div>
<div className={getTabClassname('themes')} role="tab" onClick={() => setTab('themes')}>
<IconPalette size={16} strokeWidth={1.5} />
Themes
</div>
<div className={getTabClassname('display')} role="tab" onClick={() => setTab('display')}>
<IconBrowser size={16} strokeWidth={1.5} />
Display
</div>
<div className={getTabClassname('proxy')} role="tab" onClick={() => setTab('proxy')}>
<IconUserCircle size={16} strokeWidth={1.5} />
Proxy
</div>
<div className={getTabClassname('keybindings')} role="tab" onClick={() => setTab('keybindings')}>
<IconKeyboard size={16} strokeWidth={1.5} />
Keybindings
</div>
<div className={getTabClassname('support')} role="tab" onClick={() => setTab('support')}>
<IconZoomQuestion size={16} strokeWidth={1.5} />
Support
</div>
<div className={getTabClassname('beta')} role="tab" onClick={() => setTab('beta')}>
<IconSquareLetterB size={16} strokeWidth={1.5} />
Beta
</div>
</div>

View File

@@ -32,7 +32,7 @@ const themes = {
export const themeRegistry = {
'light': {
id: 'light',
name: 'Bruno Light',
name: 'Light',
mode: 'light'
},
'light-monochrome': {
@@ -42,7 +42,7 @@ export const themeRegistry = {
},
'light-pastel': {
id: 'light-pastel',
name: 'Bruno Light Pastel',
name: 'Light Pastel',
mode: 'light'
},
'catppuccin-latte': {
@@ -52,17 +52,17 @@ export const themeRegistry = {
},
'dark': {
id: 'dark',
name: 'Bruno Dark',
name: 'Dark',
mode: 'dark'
},
'dark-monochrome': {
id: 'dark-monochrome',
name: 'Bruno Dark Monochrome',
name: 'Dark Monochrome',
mode: 'dark'
},
'dark-pastel': {
id: 'dark-pastel',
name: 'Bruno Dark Pastel',
name: 'Dark Pastel',
mode: 'dark'
},
'catppuccin-frappe': {