Add dynamic sidebar text color with brand color contrast

- Add sidebar text color picker to Branding Settings page
- Implement auto-calculated complementary text colors based on brand color luminance
- Dark themes get light tinted text, light themes get dark tinted text
- Add navigation preview showing text on gradient background
- Support 10 new lighter color palettes (Soft Mint, Lavender, Peach, etc.)
- Add CSS utility classes for brand-text with opacity support
- Update sidebar and navigation components to use dynamic text colors
- Add sidebar_text_color field to Tenant model with migration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-16 22:16:25 -05:00
parent 6a6ad63e7b
commit 725a3c5d84
15 changed files with 365 additions and 54 deletions

View File

@@ -15,12 +15,85 @@
--color-brand-700: #1d4ed8;
--color-brand-800: #1e40af;
--color-brand-900: #1e3a8a;
/* Dynamic brand text color - uses RGB for opacity support */
/* Format: rgb(R G B / alpha) where R G B come from --color-brand-text-rgb */
--color-brand-text: rgb(var(--color-brand-text-rgb) / 1);
}
:root {
font-family: 'Inter', system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
/* Default brand text color (light blue-white for dark backgrounds) */
/* This is dynamically updated by applyBrandColors() based on brand color luminance */
--color-brand-text-rgb: 233 239 255;
}
/* Custom text-brand-text utility classes with opacity support */
.text-brand-text {
color: rgb(var(--color-brand-text-rgb));
}
.text-brand-text\/5 {
color: rgb(var(--color-brand-text-rgb) / 0.05);
}
.text-brand-text\/10 {
color: rgb(var(--color-brand-text-rgb) / 0.1);
}
.text-brand-text\/20 {
color: rgb(var(--color-brand-text-rgb) / 0.2);
}
.text-brand-text\/30 {
color: rgb(var(--color-brand-text-rgb) / 0.3);
}
.text-brand-text\/40 {
color: rgb(var(--color-brand-text-rgb) / 0.4);
}
.text-brand-text\/50 {
color: rgb(var(--color-brand-text-rgb) / 0.5);
}
.text-brand-text\/60 {
color: rgb(var(--color-brand-text-rgb) / 0.6);
}
.text-brand-text\/70 {
color: rgb(var(--color-brand-text-rgb) / 0.7);
}
.text-brand-text\/80 {
color: rgb(var(--color-brand-text-rgb) / 0.8);
}
.text-brand-text\/90 {
color: rgb(var(--color-brand-text-rgb) / 0.9);
}
/* Hover variants */
.hover\:text-brand-text:hover {
color: rgb(var(--color-brand-text-rgb));
}
.hover\:text-brand-text\/60:hover {
color: rgb(var(--color-brand-text-rgb) / 0.6);
}
.hover\:text-brand-text\/80:hover {
color: rgb(var(--color-brand-text-rgb) / 0.8);
}
/* Background variants using brand-text color */
.bg-brand-text\/5 {
background-color: rgb(var(--color-brand-text-rgb) / 0.05);
}
.bg-brand-text\/10 {
background-color: rgb(var(--color-brand-text-rgb) / 0.1);
}
.hover\:bg-brand-text\/5:hover {
background-color: rgb(var(--color-brand-text-rgb) / 0.05);
}
/* Border variants */
.border-brand-text\/10 {
border-color: rgb(var(--color-brand-text-rgb) / 0.1);
}
.border-brand-text\/20 {
border-color: rgb(var(--color-brand-text-rgb) / 0.2);
}
html, body {