| author | |
| committer | |
| log | 0b1ce588246c1e38124598d9fcac4bc5e4063ce3 |
| tree | d96405307fa67508cefae1c3ac43ca4c36a29667 |
| parent | 10da67b9da3e366acf827518423978e4d762a337 |
2 files changed, 111 insertions(+), 10 deletions(-)
apps/web/src/components/settings/SettingsPanels.tsx+14-6| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | import { ArchiveIcon, ArchiveX, LoaderIcon, PlusIcon, RefreshCwIcon } from "lucide-react"; | 1 | import { ArchiveIcon, ArchiveX, LoaderIcon, PlusIcon, RefreshCwIcon } from "lucide-react"; |
| 2 | import { Link } from "@tanstack/react-router"; | 2 | import { Link } from "@tanstack/react-router"; |
| 3 | import type { CSSProperties } from "react"; | ||
| 3 | import { useCallback, useMemo, useRef, useState } from "react"; | 4 | import { useCallback, useMemo, useRef, useState } from "react"; |
| 4 | import { useAtomValue } from "@effect/atom-react"; | 5 | import { useAtomValue } from "@effect/atom-react"; |
| 5 | import { | 6 | import { |
| ... | @@ -499,6 +500,12 @@ export function GeneralSettingsPanel() { | ... | @@ -499,6 +500,12 @@ export function GeneralSettingsPanel() { |
| 499 | const updateSettings = useUpdatePrimarySettings(); | 500 | const updateSettings = useUpdatePrimarySettings(); |
| 500 | const observability = useAtomValue(primaryServerObservabilityAtom); | 501 | const observability = useAtomValue(primaryServerObservabilityAtom); |
| 501 | const serverProviders = useAtomValue(primaryServerProvidersAtom); | 502 | const serverProviders = useAtomValue(primaryServerProvidersAtom); |
| 503 | const glassOpacityRatio = | ||
| 504 | (settings.glassOpacity - MIN_GLASS_OPACITY) / (MAX_GLASS_OPACITY - MIN_GLASS_OPACITY); | ||
| 505 | const glassOpacitySliderStyle = { | ||
| 506 | "--glass-slider-progress": `${glassOpacityRatio * 100}%`, | ||
| 507 | "--glass-slider-fill-offset": `${0.5 - glassOpacityRatio}rem`, | ||
| 508 | } as CSSProperties; | ||
| 502 | const diagnosticsDescription = formatDiagnosticsDescription({ | 509 | const diagnosticsDescription = formatDiagnosticsDescription({ |
| 503 | localTracingEnabled: observability?.localTracingEnabled ?? false, | 510 | localTracingEnabled: observability?.localTracingEnabled ?? false, |
| 504 | otlpTracesEnabled: observability?.otlpTracesEnabled ?? false, | 511 | otlpTracesEnabled: observability?.otlpTracesEnabled ?? false, |
| ... | @@ -581,6 +588,12 @@ export function GeneralSettingsPanel() { | ... | @@ -581,6 +588,12 @@ export function GeneralSettingsPanel() { |
| 581 | } | 588 | } |
| 582 | control={ | 589 | control={ |
| 583 | <div className="flex w-full items-center gap-3 sm:w-52"> | 590 | <div className="flex w-full items-center gap-3 sm:w-52"> |
| 591 | <output | ||
| 592 | className="min-w-12 rounded-md bg-muted px-2 py-1 text-center font-mono text-xs font-medium tabular-nums text-foreground" | ||
| 593 | htmlFor="glass-opacity" | ||
| 594 | > | ||
| 595 | {settings.glassOpacity}% | ||
| 596 | </output> | ||
| 584 | <input | 597 | <input |
| 585 | aria-label="Glass opacity" | 598 | aria-label="Glass opacity" |
| 586 | className="glass-opacity-slider min-w-0 flex-1" | 599 | className="glass-opacity-slider min-w-0 flex-1" |
| ... | @@ -598,15 +611,10 @@ export function GeneralSettingsPanel() { | ... | @@ -598,15 +611,10 @@ export function GeneralSettingsPanel() { |
| 598 | } | 611 | } |
| 599 | }} | 612 | }} |
| 600 | step={5} | 613 | step={5} |
| 614 | style={glassOpacitySliderStyle} | ||
| 601 | type="range" | 615 | type="range" |
| 602 | value={settings.glassOpacity} | 616 | value={settings.glassOpacity} |
| 603 | /> | 617 | /> |
| 604 | <output | ||
| 605 | className="w-10 text-right font-mono text-xs tabular-nums text-muted-foreground" | ||
| 606 | htmlFor="glass-opacity" | ||
| 607 | > | ||
| 608 | {settings.glassOpacity}% | ||
| 609 | </output> | ||
| 610 | </div> | 618 | </div> |
| 611 | } | 619 | } |
| 612 | /> | 620 | /> |
apps/web/src/index.css+97-4| ... | @@ -450,14 +450,107 @@ html[data-mobile-composer-route-transition="true"]::view-transition-old(t3-mobil | ... | @@ -450,14 +450,107 @@ html[data-mobile-composer-route-transition="true"]::view-transition-old(t3-mobil |
| 450 | } | 450 | } |
| 451 | 451 | ||
| 452 | .glass-opacity-slider { | 452 | .glass-opacity-slider { |
| 453 | accent-color: var(--primary); | 453 | --glass-slider-progress: 0%; |
| 454 | --glass-slider-fill-offset: 0.5rem; | ||
| 455 | --glass-slider-fill-position: calc( | ||
| 456 | var(--glass-slider-progress) + var(--glass-slider-fill-offset) | ||
| 457 | ); | ||
| 458 | appearance: none; | ||
| 459 | height: 1.5rem; | ||
| 460 | background: transparent; | ||
| 454 | cursor: pointer; | 461 | cursor: pointer; |
| 455 | } | 462 | } |
| 456 | 463 | ||
| 457 | .glass-opacity-slider:focus-visible { | 464 | .glass-opacity-slider::-webkit-slider-runnable-track { |
| 465 | height: 0.375rem; | ||
| 458 | border-radius: 9999px; | 466 | border-radius: 9999px; |
| 459 | outline: 2px solid var(--ring); | 467 | background: linear-gradient( |
| 460 | outline-offset: 3px; | 468 | to right, |
| 469 | var(--primary) 0 var(--glass-slider-fill-position), | ||
| 470 | color-mix(in srgb, var(--muted-foreground) 22%, transparent) var(--glass-slider-fill-position) | ||
| 471 | 100% | ||
| 472 | ); | ||
| 473 | box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--border) 55%, transparent); | ||
| 474 | } | ||
| 475 | |||
| 476 | .glass-opacity-slider::-moz-range-track { | ||
| 477 | height: 0.375rem; | ||
| 478 | border-radius: 9999px; | ||
| 479 | background: color-mix(in srgb, var(--muted-foreground) 22%, transparent); | ||
| 480 | box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--border) 55%, transparent); | ||
| 481 | } | ||
| 482 | |||
| 483 | .glass-opacity-slider::-moz-range-progress { | ||
| 484 | height: 0.375rem; | ||
| 485 | border-radius: 9999px; | ||
| 486 | background: var(--primary); | ||
| 487 | } | ||
| 488 | |||
| 489 | .glass-opacity-slider::-webkit-slider-thumb { | ||
| 490 | appearance: none; | ||
| 491 | width: 1rem; | ||
| 492 | height: 1rem; | ||
| 493 | margin-top: -0.3125rem; | ||
| 494 | border: 2px solid var(--primary); | ||
| 495 | border-radius: 9999px; | ||
| 496 | background: var(--background); | ||
| 497 | box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 12%, transparent); | ||
| 498 | transition: | ||
| 499 | transform 120ms ease, | ||
| 500 | box-shadow 120ms ease; | ||
| 501 | } | ||
| 502 | |||
| 503 | .glass-opacity-slider::-moz-range-thumb { | ||
| 504 | width: 1rem; | ||
| 505 | height: 1rem; | ||
| 506 | border: 2px solid var(--primary); | ||
| 507 | border-radius: 9999px; | ||
| 508 | background: var(--background); | ||
| 509 | box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 12%, transparent); | ||
| 510 | transition: | ||
| 511 | transform 120ms ease, | ||
| 512 | box-shadow 120ms ease; | ||
| 513 | } | ||
| 514 | |||
| 515 | .glass-opacity-slider:hover::-webkit-slider-thumb { | ||
| 516 | transform: scale(1.08); | ||
| 517 | box-shadow: 0 1px 3px color-mix(in srgb, var(--foreground) 20%, transparent); | ||
| 518 | } | ||
| 519 | |||
| 520 | .glass-opacity-slider:hover::-moz-range-thumb { | ||
| 521 | transform: scale(1.08); | ||
| 522 | box-shadow: 0 1px 3px color-mix(in srgb, var(--foreground) 20%, transparent); | ||
| 523 | } | ||
| 524 | |||
| 525 | .glass-opacity-slider:active::-webkit-slider-thumb { | ||
| 526 | transform: scale(0.94); | ||
| 527 | } | ||
| 528 | |||
| 529 | .glass-opacity-slider:active::-moz-range-thumb { | ||
| 530 | transform: scale(0.94); | ||
| 531 | } | ||
| 532 | |||
| 533 | .glass-opacity-slider:focus-visible { | ||
| 534 | outline: none; | ||
| 535 | } | ||
| 536 | |||
| 537 | .glass-opacity-slider:focus-visible::-webkit-slider-thumb { | ||
| 538 | box-shadow: | ||
| 539 | 0 0 0 3px var(--background), | ||
| 540 | 0 0 0 5px var(--ring); | ||
| 541 | } | ||
| 542 | |||
| 543 | .glass-opacity-slider:focus-visible::-moz-range-thumb { | ||
| 544 | box-shadow: | ||
| 545 | 0 0 0 3px var(--background), | ||
| 546 | 0 0 0 5px var(--ring); | ||
| 547 | } | ||
| 548 | |||
| 549 | @media (forced-colors: active) { | ||
| 550 | .glass-opacity-slider { | ||
| 551 | appearance: auto; | ||
| 552 | accent-color: Highlight; | ||
| 553 | } | ||
| 461 | } | 554 | } |
| 462 | 555 | ||
| 463 | @media (min-width: 40rem) { | 556 | @media (min-width: 40rem) { |