diff --git a/apps/web/src/components/settings/SettingsPanels.tsx b/apps/web/src/components/settings/SettingsPanels.tsx index ff4edccec0d2272dd9b208b1215ea7b15eee1102..ebf4aed623486901268f29fc5387045dba0a0e60 100644 --- a/apps/web/src/components/settings/SettingsPanels.tsx +++ b/apps/web/src/components/settings/SettingsPanels.tsx @@ -1,5 +1,6 @@ import { ArchiveIcon, ArchiveX, LoaderIcon, PlusIcon, RefreshCwIcon } from "lucide-react"; import { Link } from "@tanstack/react-router"; +import type { CSSProperties } from "react"; import { useCallback, useMemo, useRef, useState } from "react"; import { useAtomValue } from "@effect/atom-react"; import { @@ -499,6 +500,12 @@ export function GeneralSettingsPanel() { const updateSettings = useUpdatePrimarySettings(); const observability = useAtomValue(primaryServerObservabilityAtom); const serverProviders = useAtomValue(primaryServerProvidersAtom); + const glassOpacityRatio = + (settings.glassOpacity - MIN_GLASS_OPACITY) / (MAX_GLASS_OPACITY - MIN_GLASS_OPACITY); + const glassOpacitySliderStyle = { + "--glass-slider-progress": `${glassOpacityRatio * 100}%`, + "--glass-slider-fill-offset": `${0.5 - glassOpacityRatio}rem`, + } as CSSProperties; const diagnosticsDescription = formatDiagnosticsDescription({ localTracingEnabled: observability?.localTracingEnabled ?? false, otlpTracesEnabled: observability?.otlpTracesEnabled ?? false, @@ -581,6 +588,12 @@ export function GeneralSettingsPanel() { } control={
+ + {settings.glassOpacity}% + - - {settings.glassOpacity}% -
} /> diff --git a/apps/web/src/index.css b/apps/web/src/index.css index 4484634ea1fe66c4b0745ed7865b87e79935848e..70614beb9f46a08f0006860368717a49b081e649 100644 --- a/apps/web/src/index.css +++ b/apps/web/src/index.css @@ -450,14 +450,107 @@ html[data-mobile-composer-route-transition="true"]::view-transition-old(t3-mobil } .glass-opacity-slider { - accent-color: var(--primary); + --glass-slider-progress: 0%; + --glass-slider-fill-offset: 0.5rem; + --glass-slider-fill-position: calc( + var(--glass-slider-progress) + var(--glass-slider-fill-offset) + ); + appearance: none; + height: 1.5rem; + background: transparent; cursor: pointer; } + .glass-opacity-slider::-webkit-slider-runnable-track { + height: 0.375rem; + border-radius: 9999px; + background: linear-gradient( + to right, + var(--primary) 0 var(--glass-slider-fill-position), + color-mix(in srgb, var(--muted-foreground) 22%, transparent) var(--glass-slider-fill-position) + 100% + ); + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--border) 55%, transparent); + } + + .glass-opacity-slider::-moz-range-track { + height: 0.375rem; + border-radius: 9999px; + background: color-mix(in srgb, var(--muted-foreground) 22%, transparent); + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--border) 55%, transparent); + } + + .glass-opacity-slider::-moz-range-progress { + height: 0.375rem; + border-radius: 9999px; + background: var(--primary); + } + + .glass-opacity-slider::-webkit-slider-thumb { + appearance: none; + width: 1rem; + height: 1rem; + margin-top: -0.3125rem; + border: 2px solid var(--primary); + border-radius: 9999px; + background: var(--background); + box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 12%, transparent); + transition: + transform 120ms ease, + box-shadow 120ms ease; + } + + .glass-opacity-slider::-moz-range-thumb { + width: 1rem; + height: 1rem; + border: 2px solid var(--primary); + border-radius: 9999px; + background: var(--background); + box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 12%, transparent); + transition: + transform 120ms ease, + box-shadow 120ms ease; + } + + .glass-opacity-slider:hover::-webkit-slider-thumb { + transform: scale(1.08); + box-shadow: 0 1px 3px color-mix(in srgb, var(--foreground) 20%, transparent); + } + + .glass-opacity-slider:hover::-moz-range-thumb { + transform: scale(1.08); + box-shadow: 0 1px 3px color-mix(in srgb, var(--foreground) 20%, transparent); + } + + .glass-opacity-slider:active::-webkit-slider-thumb { + transform: scale(0.94); + } + + .glass-opacity-slider:active::-moz-range-thumb { + transform: scale(0.94); + } + .glass-opacity-slider:focus-visible { - border-radius: 9999px; - outline: 2px solid var(--ring); - outline-offset: 3px; + outline: none; + } + + .glass-opacity-slider:focus-visible::-webkit-slider-thumb { + box-shadow: + 0 0 0 3px var(--background), + 0 0 0 5px var(--ring); + } + + .glass-opacity-slider:focus-visible::-moz-range-thumb { + box-shadow: + 0 0 0 3px var(--background), + 0 0 0 5px var(--ring); + } + + @media (forced-colors: active) { + .glass-opacity-slider { + appearance: auto; + accent-color: Highlight; + } } @media (min-width: 40rem) {