V0.9.21 branding updates

This commit is contained in:
2026-03-15 11:25:00 -04:00
parent d058c9cd5f
commit 8fcadf7f0d
9 changed files with 110 additions and 35 deletions

View File

@@ -2,7 +2,8 @@ import { useState, useEffect, useRef, useCallback } from 'react';
import { api } from '../utils/api.js';
import { useToast } from '../contexts/ToastContext.jsx';
const DEFAULT_TITLE_COLOR = '#1a73e8';
const DEFAULT_TITLE_COLOR = '#1a73e8'; // light mode default
const DEFAULT_TITLE_DARK_COLOR = '#60a5fa'; // dark mode default (lighter blue readable on dark bg)
const DEFAULT_PUBLIC_COLOR = '#1a73e8';
const DEFAULT_DM_COLOR = '#a142f4';
@@ -10,6 +11,45 @@ const COLOUR_SUGGESTIONS = [
'#1a73e8', '#a142f4', '#e53935', '#fa7b17', '#fdd835', '#34a853',
];
// ── Title Colour Row — one row per mode ──────────────────────────────────────
function TitleColourRow({ bgColor, bgLabel, textColor, appName, onChange }) {
const [mode, setMode] = useState('idle'); // 'idle' | 'custom'
return (
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
{/* Preview box */}
<div style={{
background: bgColor, borderRadius: 8, padding: '0 14px',
height: 44, display: 'flex', alignItems: 'center', justifyContent: 'center',
border: '1px solid var(--border)', minWidth: 110, flexShrink: 0,
boxShadow: '0 1px 4px rgba(0,0,0,0.1)',
}}>
<span style={{ color: textColor, fontWeight: 700, fontSize: 16, whiteSpace: 'nowrap' }}>
{appName || 'ATC'}
</span>
</div>
{mode === 'idle' && (
<>
<span style={{ fontSize: 12, color: 'var(--text-tertiary)', fontFamily: 'monospace', minWidth: 64 }}>{textColor}</span>
<button className="btn btn-secondary btn-sm" onClick={() => setMode('custom')}>Custom</button>
</>
)}
{mode === 'custom' && (
<div style={{ flex: 1 }}>
<CustomPicker
initial={textColor}
onSet={(hex) => { onChange(hex); setMode('idle'); }}
onBack={() => setMode('idle')}
/>
</div>
)}
</div>
);
}
// ── Colour math helpers ──────────────────────────────────────────────────────
function hexToHsv(hex) {
@@ -278,7 +318,8 @@ export default function BrandingModal({ onClose }) {
const [resetting, setResetting] = useState(false);
const [showResetConfirm, setShowResetConfirm] = useState(false);
const [colourTitle, setColourTitle] = useState(DEFAULT_TITLE_COLOR);
const [colourTitle, setColourTitle] = useState(DEFAULT_TITLE_COLOR);
const [colourTitleDark, setColourTitleDark] = useState(DEFAULT_TITLE_DARK_COLOR);
const [colourPublic, setColourPublic] = useState(DEFAULT_PUBLIC_COLOR);
const [colourDm, setColourDm] = useState(DEFAULT_DM_COLOR);
const [savingColours, setSavingColours] = useState(false);
@@ -288,6 +329,7 @@ export default function BrandingModal({ onClose }) {
setSettings(settings);
setAppName(settings.app_name || 'jama');
setColourTitle(settings.color_title || DEFAULT_TITLE_COLOR);
setColourTitleDark(settings.color_title_dark || DEFAULT_TITLE_DARK_COLOR);
setColourPublic(settings.color_avatar_public || DEFAULT_PUBLIC_COLOR);
setColourDm(settings.color_avatar_dm || DEFAULT_DM_COLOR);
}).catch(() => {});
@@ -329,12 +371,14 @@ export default function BrandingModal({ onClose }) {
try {
await api.updateColors({
colorTitle: colourTitle,
colorTitleDark: colourTitleDark,
colorAvatarPublic: colourPublic,
colorAvatarDm: colourDm,
});
setSettings(prev => ({
...prev,
color_title: colourTitle,
color_title_dark: colourTitleDark,
color_avatar_public: colourPublic,
color_avatar_dm: colourDm,
}));
@@ -355,6 +399,7 @@ export default function BrandingModal({ onClose }) {
setSettings(fresh);
setAppName(fresh.app_name || 'jama');
setColourTitle(DEFAULT_TITLE_COLOR);
setColourTitleDark(DEFAULT_TITLE_DARK_COLOR);
setColourPublic(DEFAULT_PUBLIC_COLOR);
setColourDm(DEFAULT_DM_COLOR);
toast('Settings reset to defaults', 'success');
@@ -453,11 +498,25 @@ export default function BrandingModal({ onClose }) {
{tab === 'colours' && (
<div className="flex-col gap-3">
<ColourPicker
label="App Title Colour"
value={colourTitle}
onChange={setColourTitle}
/>
<div>
<div className="settings-section-label">App Title Colour</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginTop: 4 }}>
<TitleColourRow
bgColor="#f1f3f4"
bgLabel="Light mode"
textColor={colourTitle}
appName={appName}
onChange={setColourTitle}
/>
<TitleColourRow
bgColor="#13131f"
bgLabel="Dark mode"
textColor={colourTitleDark}
appName={appName}
onChange={setColourTitleDark}
/>
</div>
</div>
<div style={{ borderTop: '1px solid var(--border)', paddingTop: 20 }}>
<ColourPicker