Fix white filament color swatches invisible in light theme (#726)

Changed filament color circle borders from border-white/20 to
  border-black/20 across all views so white spools are distinguishable
  against light backgrounds.
This commit is contained in:
maziggy
2026-03-17 13:08:04 +01:00
parent 11610a5b48
commit a4006408a2
15 changed files with 27 additions and 26 deletions
+1
View File
@@ -8,6 +8,7 @@ All notable changes to Bambuddy will be documented in this file.
- **Per-User Email Notifications** ([#693](https://github.com/maziggy/bambuddy/pull/693)) — When Advanced Authentication is enabled, individual users can now receive email notifications for their own print jobs. A new "Notifications" page lets each user toggle notifications for print start, complete, failed, and stopped events. Only prints submitted by that user trigger their email — other users' prints are not affected. Requires SMTP to be configured and the "User Notifications" toggle enabled in Settings → Notifications. Administrators and Operators have access by default; Viewers do not. Contributed by @cadtoolbox.
### Fixed
- **White Filament Color Swatches Invisible in Light Theme** ([#726](https://github.com/maziggy/bambuddy/issues/726)) — Filament color circles used a white border that was invisible against light theme backgrounds, making white spools indistinguishable. Changed to a dark border (`border-black/20`) across all views: Inventory, Archives, Assign Spool, Configure AMS Slot, Calendar, Projects, Filament Trends, Local Profiles, Link Spool, and Spoolman Settings. Reported by user.
- **Webhook Notifications Missing Camera Snapshot** ([#679](https://github.com/maziggy/bambuddy/issues/679)) — Webhook notification providers did not include camera snapshots (e.g. from First Layer Complete notifications), even though providers like Telegram, Pushover, ntfy, and Discord already attached them. The webhook payload now includes a base64-encoded `image` field when a snapshot is available (generic format only, not Slack format). Reported by @Arn0uDz.
- **Mobile Sidebar Not Scrollable** — On mobile devices with many navigation items, the sidebar did not scroll, making bottom items unreachable. Added overflow scrolling to the nav section while keeping the logo and footer pinned.
- **User Notification Ruff/Lint Fixes** ([#693](https://github.com/maziggy/bambuddy/pull/693)) — Fixed missing `timezone` import in email timestamp, unused lambda argument, PEP 8 blank line spacing for `mark_printer_stopped_by_user`, and SQLAlchemy forward reference in `UserEmailPreference` model.
+2 -2
View File
@@ -222,7 +222,7 @@ export function AssignSpoolModal({ isOpen, onClose, printerId, amsId, trayId, tr
<div className="flex items-center gap-2">
{trayInfo.color && (
<span
className="w-4 h-4 rounded-full border border-white/20"
className="w-4 h-4 rounded-full border border-black/20"
style={{ backgroundColor: `#${trayInfo.color}` }}
/>
)}
@@ -268,7 +268,7 @@ export function AssignSpoolModal({ isOpen, onClose, printerId, amsId, trayId, tr
<div className="flex items-center gap-1.5 mt-1">
{spool.rgba && (
<span
className="w-3 h-3 rounded-full border border-white/20 flex-shrink-0"
className="w-3 h-3 rounded-full border border-black/20 flex-shrink-0"
style={{ backgroundColor: `#${spool.rgba.substring(0, 6)}` }}
/>
)}
+1 -1
View File
@@ -265,7 +265,7 @@ export function CalendarView({ archives, onArchiveClick, highlightedArchiveId }:
{archive.filament_color.split(',').map((color, i) => (
<div
key={i}
className="w-3 h-3 rounded-full border border-white/20"
className="w-3 h-3 rounded-full border border-black/20"
style={{ backgroundColor: color }}
/>
))}
@@ -841,7 +841,7 @@ export function ConfigureAmsSlotModal({
<span className="text-white/30">|</span>
{slotInfo.trayColor && (
<span
className="w-4 h-4 rounded-full border border-white/20"
className="w-4 h-4 rounded-full border border-black/20"
style={{ backgroundColor: `#${slotInfo.trayColor.slice(0, 6)}` }}
/>
)}
@@ -882,7 +882,7 @@ export function ConfigureAmsSlotModal({
<div className="flex items-center gap-2">
{slotInfo.trayColor && (
<span
className="w-4 h-4 rounded-full border border-white/20"
className="w-4 h-4 rounded-full border border-black/20"
style={{ backgroundColor: `#${slotInfo.trayColor.slice(0, 6)}` }}
/>
)}
@@ -1034,7 +1034,7 @@ export function ConfigureAmsSlotModal({
title={entry.color_name}
>
<span
className="w-4 h-4 rounded-full border border-white/30 flex-shrink-0"
className="w-4 h-4 rounded-full border border-black/20 flex-shrink-0"
style={{ backgroundColor: entry.hex_color }}
/>
<span className="text-xs text-white/80 whitespace-nowrap">{entry.color_name}</span>
@@ -1269,7 +1269,7 @@ export function ConfigureAmsSlotModal({
title={entry.color_name}
>
<span
className="w-4 h-4 rounded-full border border-white/30 flex-shrink-0"
className="w-4 h-4 rounded-full border border-black/20 flex-shrink-0"
style={{ backgroundColor: entry.hex_color }}
/>
<span className="text-xs text-white/80 whitespace-nowrap">{entry.color_name}</span>
+1 -1
View File
@@ -476,7 +476,7 @@ export function FilamentTrends({ archives, currency = '$', dateFrom, dateTo }: F
const percent = colorTotal > 0 ? ((entry.value / colorTotal) * 100).toFixed(0) : 0;
return (
<div key={entry.hex} className="flex items-center gap-1.5 text-xs min-w-0">
<div className="w-2.5 h-2.5 rounded-full flex-shrink-0 border border-white/20"
<div className="w-2.5 h-2.5 rounded-full flex-shrink-0 border border-black/20"
style={{ backgroundColor: entry.hex }} />
<span className="text-bambu-gray truncate">
{percent}%
+1 -1
View File
@@ -123,7 +123,7 @@ export function LinkSpoolModal({ isOpen, onClose, tagUid, trayUuid, printerId, a
className="w-full flex items-center gap-3 p-3 rounded-lg hover:bg-white/5 transition-colors text-left"
>
<span
className="w-6 h-6 rounded-full border border-white/20 flex-shrink-0"
className="w-6 h-6 rounded-full border border-black/20 flex-shrink-0"
style={{ backgroundColor: spool.filament_color_hex ? `#${spool.filament_color_hex}` : '#808080' }}
/>
<div className="flex-1 min-w-0">
@@ -107,7 +107,7 @@ function PresetCard({
{/* 1) Color dot — always shown for filament presets, dimmed if no explicit colour */}
{preset.preset_type === 'filament' && (
<div
className={`w-4 h-4 rounded-full border border-white/20 flex-shrink-0 ${
className={`w-4 h-4 rounded-full border border-black/20 flex-shrink-0 ${
!hasExplicitColour && !colourHex ? 'opacity-25' : !hasExplicitColour ? 'opacity-50' : ''
}`}
style={{ backgroundColor: colourHex ? `#${colourHex}` : '#666' }}
+1 -1
View File
@@ -528,7 +528,7 @@ export function SpoolmanSettings() {
<li key={i} className="flex items-center gap-2">
{s.color && (
<span
className="w-3 h-3 rounded-full border border-white/20"
className="w-3 h-3 rounded-full border border-black/20"
style={{ backgroundColor: `#${s.color}` }}
/>
)}
+3 -3
View File
@@ -1006,7 +1006,7 @@ function ArchiveCard({
{archive.filament_color.split(',').map((color, i) => (
<div
key={i}
className="w-3 h-3 rounded-full border border-white/20"
className="w-3 h-3 rounded-full border border-black/20"
style={{ backgroundColor: color }}
title={color}
/>
@@ -1962,7 +1962,7 @@ function ArchiveListRow({
{archive.filament_color.split(',').map((color, i) => (
<div
key={i}
className="w-2.5 h-2.5 rounded-full border border-white/20"
className="w-2.5 h-2.5 rounded-full border border-black/20"
style={{ backgroundColor: color }}
title={color}
/>
@@ -3508,7 +3508,7 @@ export function ArchivesPage() {
<div className="flex items-center gap-1.5">
{entry.filament_color && (
<span
className="w-3 h-3 rounded-full border border-white/20 flex-shrink-0"
className="w-3 h-3 rounded-full border border-black/20 flex-shrink-0"
style={{ backgroundColor: entry.filament_color.startsWith('#') ? entry.filament_color : undefined }}
/>
)}
+1 -1
View File
@@ -178,7 +178,7 @@ const columnCells: Record<string, (ctx: CellCtx) => ReactNode> = {
rgba: ({ spool }) => (
<div className="flex items-center justify-center">
<span
className="w-5 h-5 rounded-full border border-white/20 flex-shrink-0"
className="w-5 h-5 rounded-full border border-black/20 flex-shrink-0"
style={{ backgroundColor: spool.rgba ? `#${spool.rgba.substring(0, 6)}` : '#808080' }}
title={spool.rgba ? `#${spool.rgba.substring(0, 6)}` : undefined}
/>
+1 -1
View File
@@ -367,7 +367,7 @@ function ProjectCard({ project, onClick, onEdit, onDelete, hasPermission, t }: P
{colors.slice(0, 5).map((col) => (
<div
key={col}
className="w-3 h-3 rounded-full border border-white/20"
className="w-3 h-3 rounded-full border border-black/20"
style={{ backgroundColor: col.startsWith('#') ? col : `#${col}` }}
title={col}
/>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -23,8 +23,8 @@
<!-- Splash screens for iOS -->
<link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
<script type="module" crossorigin src="/assets/index-qEYzdY9E.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Dq3gZWq6.css">
<script type="module" crossorigin src="/assets/index-DfydSnCI.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-hKLgfdEQ.css">
</head>
<body>
<div id="root"></div>