fix: replace text-white with theme-aware color tokens (#7908)

## Summary
- Replace hardcoded `text-white` class with theme-aware alternatives to
fix invisible text on light themes
- Update Load3D control backgrounds to use semantic tokens
- Update dropdown menus to use `bg-interface-menu-surface`
- Update overlay backgrounds to use `bg-backdrop` with opacity

## Changes
| Component | Old | New |
|-----------|-----|-----|
| Text on primary bg | `text-white` | `text-base-foreground` |
| Dropdown menus | `bg-black/50` | `bg-interface-menu-surface` |
| Control panels | `bg-smoke-700/30` | `bg-backdrop/30` |
| Loading overlays | `bg-black bg-opacity-50` | `bg-backdrop/50` |
| Selected states | `bg-smoke-600` | `bg-button-active-surface` |

## Files Modified (14)
- `src/components/TopMenuSection.vue`
- `src/components/input/MultiSelect.vue`
- `src/components/load3d/*.vue` (12 files)
- `src/renderer/extensions/vueNodes/VideoPreview.vue`

## Test plan
- [ ] Verify text visibility in light theme
- [ ] Verify text visibility in dark theme
- [ ] Test Load3D viewer controls functionality
- [ ] Test MultiSelect dropdown checkbox visibility

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7908-fix-replace-text-white-with-theme-aware-color-tokens-2e26d73d36508107bb01d1d6e3b74f6a)
by [Unito](https://www.unito.io)
This commit is contained in:
Johnpaul Chiwetelu
2026-01-09 02:40:15 +01:00
committed by GitHub
parent a2e0c3d596
commit 9e434a1002
14 changed files with 50 additions and 42 deletions

View File

@@ -54,7 +54,7 @@
<i class="icon-[lucide--history] size-4" />
<span
v-if="queuedCount > 0"
class="absolute -top-1 -right-1 min-w-[16px] rounded-full bg-primary-background py-0.25 text-[10px] font-medium leading-[14px] text-white"
class="absolute -top-1 -right-1 min-w-[16px] rounded-full bg-primary-background py-0.25 text-[10px] font-medium leading-[14px] text-base-foreground"
>
{{ queuedCount }}
</span>

View File

@@ -160,7 +160,7 @@
>
<i
v-if="slotProps.selected"
class="text-bold icon-[lucide--check] text-xs text-white"
class="text-bold icon-[lucide--check] text-xs text-base-foreground"
/>
</div>
<span>

View File

@@ -1,6 +1,6 @@
<template>
<div
class="pointer-events-auto absolute top-12 left-2 z-20 flex flex-col rounded-lg bg-smoke-700/30"
class="pointer-events-auto absolute top-12 left-2 z-20 flex flex-col rounded-lg bg-backdrop/30"
@pointerdown.stop
@pointermove.stop
@pointerup.stop
@@ -14,12 +14,12 @@
class="rounded-full"
@click="toggleMenu"
>
<i class="pi pi-bars text-lg text-white" />
<i class="pi pi-bars text-lg text-base-foreground" />
</Button>
<div
v-show="isMenuOpen"
class="absolute top-0 left-12 rounded-lg bg-black/50 shadow-lg"
class="absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg"
>
<div class="flex flex-col">
<Button
@@ -29,13 +29,13 @@
:class="
cn(
'flex w-full items-center justify-start',
activeCategory === category && 'bg-smoke-600'
activeCategory === category && 'bg-button-active-surface'
)
"
@click="selectCategory(category)"
>
<i :class="getCategoryIcon(category)" />
<span class="whitespace-nowrap text-white">{{
<span class="whitespace-nowrap text-base-foreground">{{
$t(categoryLabels[category])
}}</span>
</Button>
@@ -169,7 +169,7 @@ const getCategoryIcon = (category: string) => {
export: 'pi pi-download'
}
// @ts-expect-error fixme ts strict error
return `${icons[category]} text-white text-lg`
return `${icons[category]} text-base-foreground text-lg`
}
const emit = defineEmits<{

View File

@@ -2,11 +2,11 @@
<Transition name="fade">
<div
v-if="loading"
class="bg-opacity-50 absolute inset-0 z-50 flex items-center justify-center bg-black"
class="absolute inset-0 z-50 flex items-center justify-center bg-backdrop/50"
>
<div class="flex flex-col items-center">
<div class="spinner" />
<div class="mt-4 text-lg text-white">
<div class="mt-4 text-lg text-base-foreground">
{{ loadingMessage }}
</div>
</div>

View File

@@ -15,7 +15,7 @@
:class="[
'pi',
playing ? 'pi-pause' : 'pi-play',
'text-lg text-white'
'text-lg text-base-foreground'
]"
/>
</Button>
@@ -46,7 +46,7 @@
class="flex-1"
@update:model-value="handleSliderChange"
/>
<span class="min-w-16 text-xs text-white">
<span class="min-w-16 text-xs text-base-foreground">
{{ formatTime(currentTime) }} / {{ formatTime(animationDuration) }}
</span>
</div>

View File

@@ -11,7 +11,7 @@
:aria-label="$t('load3d.switchCamera')"
@click="switchCamera"
>
<i :class="['pi', 'pi-camera', 'text-lg text-white']" />
<i :class="['pi', 'pi-camera', 'text-lg text-base-foreground']" />
</Button>
<PopupSlider
v-if="showFOVButton"

View File

@@ -12,18 +12,18 @@
:aria-label="$t('load3d.exportModel')"
@click="toggleExportFormats"
>
<i class="pi pi-download text-lg text-white" />
<i class="pi pi-download text-lg text-base-foreground" />
</Button>
<div
v-show="showExportFormats"
class="absolute top-0 left-12 rounded-lg bg-black/50 shadow-lg"
class="absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg"
>
<div class="flex flex-col">
<Button
v-for="format in exportFormats"
:key="format.value"
variant="textonly"
class="text-white"
class="text-base-foreground"
@click="exportModel(format.value)"
>
{{ format.label }}

View File

@@ -12,7 +12,7 @@
:aria-label="$t('load3d.lightIntensity')"
@click="toggleLightIntensity"
>
<i class="pi pi-sun text-lg text-white" />
<i class="pi pi-sun text-lg text-base-foreground" />
</Button>
<div
v-show="showLightIntensity"

View File

@@ -12,11 +12,11 @@
:aria-label="t('load3d.upDirection')"
@click="toggleUpDirection"
>
<i class="pi pi-arrow-up text-lg text-white" />
<i class="pi pi-arrow-up text-lg text-base-foreground" />
</Button>
<div
v-show="showUpDirection"
class="absolute top-0 left-12 rounded-lg bg-black/50 shadow-lg"
class="absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg"
>
<div class="flex flex-col">
<Button
@@ -24,7 +24,10 @@
:key="direction"
variant="textonly"
:class="
cn('text-white', upDirection === direction && 'bg-blue-500')
cn(
'text-base-foreground',
upDirection === direction && 'bg-blue-500'
)
"
@click="selectUpDirection(direction)"
>
@@ -46,11 +49,11 @@
:aria-label="t('load3d.materialMode')"
@click="toggleMaterialMode"
>
<i class="pi pi-box text-lg text-white" />
<i class="pi pi-box text-lg text-base-foreground" />
</Button>
<div
v-show="showMaterialMode"
class="absolute top-0 left-12 rounded-lg bg-black/50 shadow-lg"
class="absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg"
>
<div class="flex flex-col">
<Button
@@ -59,7 +62,7 @@
variant="textonly"
:class="
cn(
'whitespace-nowrap text-white',
'whitespace-nowrap text-base-foreground',
materialMode === mode && 'bg-blue-500'
)
"
@@ -83,7 +86,7 @@
:aria-label="t('load3d.showSkeleton')"
@click="showSkeleton = !showSkeleton"
>
<i class="pi pi-sitemap text-lg text-white" />
<i class="pi pi-sitemap text-lg text-base-foreground" />
</Button>
</div>
</div>

View File

@@ -8,11 +8,11 @@
:aria-label="tooltipText"
@click="toggleSlider"
>
<i :class="['pi', icon, 'text-lg text-white']" />
<i :class="['pi', icon, 'text-lg text-base-foreground']" />
</Button>
<div
v-show="showSlider"
class="absolute top-0 left-12 rounded-lg bg-black/50 p-4 shadow-lg w-[150px]"
class="absolute top-0 left-12 rounded-lg bg-interface-menu-surface p-4 shadow-lg w-[150px]"
>
<Slider
v-model="value"

View File

@@ -1,5 +1,5 @@
<template>
<div class="relative rounded-lg bg-smoke-700/30">
<div class="relative rounded-lg bg-backdrop/30">
<div class="flex flex-col gap-2">
<Button
v-tooltip.right="{
@@ -25,7 +25,7 @@
:class="[
'pi',
isRecording ? 'pi-circle-fill' : 'pi-video',
'text-lg text-white'
'text-lg text-base-foreground'
]"
/>
</Button>
@@ -42,7 +42,7 @@
:aria-label="$t('load3d.exportRecording')"
@click="handleExportRecording"
>
<i class="pi pi-download text-lg text-white" />
<i class="pi pi-download text-lg text-base-foreground" />
</Button>
<Button
@@ -57,12 +57,12 @@
:aria-label="$t('load3d.clearRecording')"
@click="handleClearRecording"
>
<i class="pi pi-trash text-lg text-white" />
<i class="pi pi-trash text-lg text-base-foreground" />
</Button>
<div
v-if="recordingDuration && recordingDuration > 0 && !isRecording"
class="mt-1 text-center text-xs text-white"
class="mt-1 text-center text-xs text-base-foreground"
>
{{ formatDuration(recordingDuration) }}
</div>

View File

@@ -8,7 +8,7 @@
:aria-label="$t('load3d.showGrid')"
@click="toggleGrid"
>
<i class="pi pi-table text-lg text-white" />
<i class="pi pi-table text-lg text-base-foreground" />
</Button>
<div v-if="!hasBackgroundImage">
@@ -23,7 +23,7 @@
:aria-label="$t('load3d.backgroundColor')"
@click="openColorPicker"
>
<i class="pi pi-palette text-lg text-white" />
<i class="pi pi-palette text-lg text-base-foreground" />
<input
ref="colorPickerRef"
type="color"
@@ -48,7 +48,7 @@
:aria-label="$t('load3d.uploadBackgroundImage')"
@click="openImagePicker"
>
<i class="pi pi-image text-lg text-white" />
<i class="pi pi-image text-lg text-base-foreground" />
<input
ref="imagePickerRef"
type="file"
@@ -76,7 +76,7 @@
:aria-label="$t('load3d.panoramaMode')"
@click="toggleBackgroundRenderMode"
>
<i class="pi pi-globe text-lg text-white" />
<i class="pi pi-globe text-lg text-base-foreground" />
</Button>
</div>
@@ -98,7 +98,7 @@
:aria-label="$t('load3d.removeBackgroundImage')"
@click="removeBackgroundImage"
>
<i class="pi pi-times text-lg text-white" />
<i class="pi pi-times text-lg text-base-foreground" />
</Button>
</div>
</div>

View File

@@ -1,5 +1,5 @@
<template>
<div class="relative rounded-lg bg-smoke-700/30">
<div class="relative rounded-lg bg-backdrop/30">
<div class="flex flex-col gap-2">
<Button
v-tooltip.right="{
@@ -12,7 +12,7 @@
:aria-label="t('load3d.openIn3DViewer')"
@click="openIn3DViewer"
>
<i class="pi pi-expand text-lg text-white" />
<i class="pi pi-expand text-lg text-base-foreground" />
</Button>
</div>
</div>

View File

@@ -20,11 +20,16 @@
<!-- Error State -->
<div
v-if="videoError"
class="flex size-full flex-col items-center justify-center bg-smoke-800/50 text-center text-white py-8"
role="alert"
class="flex size-full flex-col items-center justify-center bg-muted-background text-center text-base-foreground py-8"
>
<i class="mb-2 icon-[lucide--video-off] h-12 w-12 text-smoke-400" />
<p class="text-sm text-smoke-300">{{ $t('g.videoFailedToLoad') }}</p>
<p class="mt-1 text-xs text-smoke-400">
<i
class="mb-2 icon-[lucide--video-off] h-12 w-12 text-base-foreground"
/>
<p class="text-sm text-base-foreground">
{{ $t('g.videoFailedToLoad') }}
</p>
<p class="mt-1 text-xs text-base-foreground">
{{ getVideoFilename(currentVideoUrl) }}
</p>
</div>