mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 14:55:43 +00:00
fix(themes): restyle the animated-theme indicator (#1035)
Replace the raw hazard-triangle icon with a small amber motion chip (shared AnimatedThemeBadge): an Activity glyph on a tinted rounded surface. In the Theme Store it stays inline after the name; on installed theme cards it moves from bottom-right to top-centre, clear of the active indicator (top-right) and the uninstall control (top-left). Tooltip and aria-label are unchanged.
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
import { Activity } from 'lucide-react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
type Variant = 'inline' | 'overlay';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small amber "animated theme" chip, shown only on animation-risk setups
|
||||||
|
* (Nvidia/Linux or compositing off). A motion glyph rather than a hazard
|
||||||
|
* triangle — the CPU-usage caveat lives in the tooltip.
|
||||||
|
*
|
||||||
|
* - `inline` — sits after a theme name (Theme Store rows).
|
||||||
|
* - `overlay` — pinned top-centre on an installed theme's preview swatch
|
||||||
|
* (top-right is the active indicator, top-left the uninstall X).
|
||||||
|
*/
|
||||||
|
export function AnimatedThemeBadge({ variant }: { variant: Variant }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const overlay = variant === 'overlay';
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
role="img"
|
||||||
|
aria-label={t('settings.themeAnimationWarning')}
|
||||||
|
data-tooltip={t('settings.themeAnimationWarning')}
|
||||||
|
data-tooltip-pos="top"
|
||||||
|
style={{
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
width: overlay ? 18 : undefined,
|
||||||
|
height: overlay ? 18 : undefined,
|
||||||
|
padding: overlay ? 0 : '1px 5px',
|
||||||
|
borderRadius: 999,
|
||||||
|
background: 'color-mix(in srgb, var(--warning) 20%, var(--bg-elevated, var(--bg-card)))',
|
||||||
|
border: '1px solid color-mix(in srgb, var(--warning) 45%, transparent)',
|
||||||
|
color: 'var(--warning)',
|
||||||
|
...(overlay
|
||||||
|
? { position: 'absolute', top: 3, left: '50%', transform: 'translateX(-50%)' }
|
||||||
|
: { verticalAlign: 'middle' }),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Activity size={overlay ? 11 : 12} strokeWidth={2.5} />
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import { AlertTriangle, Check, X } from 'lucide-react';
|
import { Check, X } from 'lucide-react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useThemeStore } from '../../store/themeStore';
|
import { useThemeStore } from '../../store/themeStore';
|
||||||
import { useInstalledThemesStore } from '../../store/installedThemesStore';
|
import { useInstalledThemesStore } from '../../store/installedThemesStore';
|
||||||
import { uninstallTheme } from '../../utils/themes/uninstallTheme';
|
import { uninstallTheme } from '../../utils/themes/uninstallTheme';
|
||||||
import { useThemeAnimationRisk } from '../../hooks/useThemeAnimationRisk';
|
import { useThemeAnimationRisk } from '../../hooks/useThemeAnimationRisk';
|
||||||
|
import { AnimatedThemeBadge } from './AnimatedThemeBadge';
|
||||||
import { FIXED_THEMES } from './fixedThemes';
|
import { FIXED_THEMES } from './fixedThemes';
|
||||||
|
|
||||||
/** Pull a 3-band swatch (bg / card / accent) out of an installed theme's CSS. */
|
/** Pull a 3-band swatch (bg / card / accent) out of an installed theme's CSS. */
|
||||||
@@ -80,30 +81,7 @@ export function InstalledThemes() {
|
|||||||
<Check size={8} strokeWidth={3} color="white" />
|
<Check size={8} strokeWidth={3} color="white" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{animRisk && c.animated && (
|
{animRisk && c.animated && <AnimatedThemeBadge variant="overlay" />}
|
||||||
<span
|
|
||||||
role="img"
|
|
||||||
aria-label={t('settings.themeAnimationWarning')}
|
|
||||||
data-tooltip={t('settings.themeAnimationWarning')}
|
|
||||||
data-tooltip-pos="top"
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: '3px',
|
|
||||||
right: '3px',
|
|
||||||
width: '16px',
|
|
||||||
height: '16px',
|
|
||||||
borderRadius: '50%',
|
|
||||||
background: 'var(--bg-elevated)',
|
|
||||||
color: 'var(--warning)',
|
|
||||||
border: '1px solid var(--warning)',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AlertTriangle size={10} />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<span className={`theme-card-label${isActive ? ' is-active' : ''}`}>
|
<span className={`theme-card-label${isActive ? ' is-active' : ''}`}>
|
||||||
{c.label}
|
{c.label}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { AlertTriangle, Check, ChevronLeft, ChevronRight, Download, RefreshCw, Trash2, WifiOff } from 'lucide-react';
|
import { Check, ChevronLeft, ChevronRight, Download, RefreshCw, Trash2, WifiOff } from 'lucide-react';
|
||||||
import { open as openUrl } from '@tauri-apps/plugin-shell';
|
import { open as openUrl } from '@tauri-apps/plugin-shell';
|
||||||
import CoverLightbox from '../CoverLightbox';
|
import CoverLightbox from '../CoverLightbox';
|
||||||
import { useThemeAnimationRisk } from '../../hooks/useThemeAnimationRisk';
|
import { useThemeAnimationRisk } from '../../hooks/useThemeAnimationRisk';
|
||||||
|
import { AnimatedThemeBadge } from './AnimatedThemeBadge';
|
||||||
import { useThemeStore } from '../../store/themeStore';
|
import { useThemeStore } from '../../store/themeStore';
|
||||||
import { useInstalledThemesStore, type InstalledTheme } from '../../store/installedThemesStore';
|
import { useInstalledThemesStore, type InstalledTheme } from '../../store/installedThemesStore';
|
||||||
import {
|
import {
|
||||||
@@ -295,17 +296,7 @@ export function ThemeStoreSection() {
|
|||||||
<Check size={12} /> {t('settings.themeStoreActive')}
|
<Check size={12} /> {t('settings.themeStoreActive')}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{animRisk && th.animated && (
|
{animRisk && th.animated && <AnimatedThemeBadge variant="inline" />}
|
||||||
<span
|
|
||||||
role="img"
|
|
||||||
aria-label={t('settings.themeAnimationWarning')}
|
|
||||||
data-tooltip={t('settings.themeAnimationWarning')}
|
|
||||||
data-tooltip-pos="top"
|
|
||||||
style={{ display: 'inline-flex', color: 'var(--warning)' }}
|
|
||||||
>
|
|
||||||
<AlertTriangle size={14} />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: 12, color: 'var(--text-muted)' }}>
|
<div style={{ fontSize: 12, color: 'var(--text-muted)' }}>
|
||||||
{t('settings.themeStoreByAuthor', { author: th.author })}
|
{t('settings.themeStoreByAuthor', { author: th.author })}
|
||||||
|
|||||||
Reference in New Issue
Block a user