Add hover style to checkboxes when their corresponding labels are hovered

This commit is contained in:
Keavon Chambers 2026-02-18 17:37:34 -08:00
parent e1357c5c34
commit 6824f55929
4 changed files with 40 additions and 4 deletions

View File

@ -101,7 +101,7 @@ jobs:
comment_id: ${{ github.event.comment.id }}, comment_id: ${{ github.event.comment.id }},
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
body: '!build ([build link](https://github.com/GraphiteEditor/Graphite/actions/runs/' + context.runId + '))' body: '!build ([Run ID ' + context.runId + '](https://github.com/GraphiteEditor/Graphite/actions/runs/' + context.runId + '))'
}); });
- name: 🌐 Build Graphite web code - name: 🌐 Build Graphite web code
@ -111,7 +111,7 @@ jobs:
run: | run: |
cd frontend cd frontend
mold -run npm run ${{ steps.build_command.outputs.command }} mold -run npm run ${{ steps.build_command.outputs.command }}
- name: ❗ Warn on build failure - name: ❗ Warn on build failure
if: ${{ failure() }} if: ${{ failure() }}
uses: actions/github-script@v6 uses: actions/github-script@v6

View File

@ -5,6 +5,7 @@
import { Color, contrastingOutlineFactor, Gradient } from "@graphite/messages"; import { Color, contrastingOutlineFactor, Gradient } from "@graphite/messages";
import type { TooltipState } from "@graphite/state-providers/tooltip"; import type { TooltipState } from "@graphite/state-providers/tooltip";
import { clamp } from "@graphite/utility-functions/math"; import { clamp } from "@graphite/utility-functions/math";
import { isDesktop } from "@graphite/utility-functions/platform";
import FloatingMenu from "@graphite/components/layout/FloatingMenu.svelte"; import FloatingMenu from "@graphite/components/layout/FloatingMenu.svelte";
import { preventEscapeClosingParentFloatingMenu } from "@graphite/components/layout/FloatingMenu.svelte"; import { preventEscapeClosingParentFloatingMenu } from "@graphite/components/layout/FloatingMenu.svelte";
@ -376,6 +377,9 @@
// TODO: Replace this temporary usage of the browser eyedropper API, that only works in Chromium-based browsers, with the custom color sampler system used by the Eyedropper tool // TODO: Replace this temporary usage of the browser eyedropper API, that only works in Chromium-based browsers, with the custom color sampler system used by the Eyedropper tool
function eyedropperSupported(): boolean { function eyedropperSupported(): boolean {
// TODO: Implement support in the desktop app for OS-level color picking
if (isDesktop()) return false;
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
return Boolean((window as any).EyeDropper); return Boolean((window as any).EyeDropper);
} }

View File

@ -99,7 +99,8 @@
} }
// Hovered while unchecked // Hovered while unchecked
&:hover .checkbox-box { &:hover .checkbox-box,
&.label-is-hovered .checkbox-box {
background: var(--color-6-lowergray); background: var(--color-6-lowergray);
} }
@ -120,7 +121,8 @@
} }
// Hovered while checked // Hovered while checked
&:hover .checkbox-box { &:hover .checkbox-box,
&.label-is-hovered .checkbox-box {
background: var(--color-f-white); background: var(--color-f-white);
} }

View File

@ -1,4 +1,6 @@
<script lang="ts"> <script lang="ts">
import { onMount, onDestroy } from "svelte";
import type { ActionShortcut } from "@graphite/messages"; import type { ActionShortcut } from "@graphite/messages";
let className = ""; let className = "";
@ -28,12 +30,39 @@
export let tooltipDescription: string | undefined = undefined; export let tooltipDescription: string | undefined = undefined;
export let tooltipShortcut: ActionShortcut | undefined = undefined; export let tooltipShortcut: ActionShortcut | undefined = undefined;
let self: HTMLLabelElement | undefined;
$: extraClasses = Object.entries(classes) $: extraClasses = Object.entries(classes)
.flatMap(([className, stateName]) => (stateName ? [className] : [])) .flatMap(([className, stateName]) => (stateName ? [className] : []))
.join(" "); .join(" ");
$: extraStyles = Object.entries(styles) $: extraStyles = Object.entries(styles)
.flatMap((styleAndValue) => (styleAndValue[1] !== undefined ? [`${styleAndValue[0]}: ${styleAndValue[1]};`] : [])) .flatMap((styleAndValue) => (styleAndValue[1] !== undefined ? [`${styleAndValue[0]}: ${styleAndValue[1]};`] : []))
.join(" "); .join(" ");
$: watchForCheckbox(forCheckbox);
function watchForCheckbox(forCheckbox: bigint | undefined) {
if (!self) return;
self.removeEventListener("pointerenter", handlePointerEnter);
self.removeEventListener("pointerleave", handlePointerLeave);
if (forCheckbox !== undefined) {
self.addEventListener("pointerenter", handlePointerEnter);
self.addEventListener("pointerleave", handlePointerLeave);
}
}
function handlePointerEnter() {
document.querySelector(`[for="checkbox-input-${forCheckbox}"]`)?.classList.add("label-is-hovered");
}
function handlePointerLeave() {
document.querySelector(`[for="checkbox-input-${forCheckbox}"]`)?.classList.remove("label-is-hovered");
}
onMount(() => watchForCheckbox(forCheckbox));
onDestroy(() => watchForCheckbox(undefined));
</script> </script>
<label <label
@ -52,6 +81,7 @@
data-tooltip-description={tooltipDescription} data-tooltip-description={tooltipDescription}
data-tooltip-shortcut={tooltipShortcut?.shortcut ? JSON.stringify(tooltipShortcut.shortcut) : undefined} data-tooltip-shortcut={tooltipShortcut?.shortcut ? JSON.stringify(tooltipShortcut.shortcut) : undefined}
for={forCheckbox !== undefined ? `checkbox-input-${forCheckbox}` : undefined} for={forCheckbox !== undefined ? `checkbox-input-${forCheckbox}` : undefined}
bind:this={self}
> >
<slot /> <slot />
</label> </label>