feat: add ColorSync hook to sync color picker and text input

The color picker and text input for accent color weren't syncing properly when the user changed the color picker value. This was because LiveView doesn't update input values that might have user focus, to avoid interfering with user input.

Added a JavaScript LiveView hook (ColorSync) that:
- Listens to 'input' events on both the color picker and text input
- Syncs their values in real-time as the user interacts with either one
- Provides immediate visual feedback when changing colors via the picker

The hook is attached to the accent color form with phx-hook="ColorSync" and syncs the two inputs bidirectionally, ensuring they always display the same value.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Jamey Greenwood 2025-12-31 01:00:22 +00:00
parent 53828c3a2a
commit 0dada968aa
2 changed files with 22 additions and 4 deletions

View File

@ -25,11 +25,29 @@ import {LiveSocket} from "phoenix_live_view"
import {hooks as colocatedHooks} from "phoenix-colocated/simpleshop_theme" import {hooks as colocatedHooks} from "phoenix-colocated/simpleshop_theme"
import topbar from "../vendor/topbar" import topbar from "../vendor/topbar"
// Hook to sync color picker and text input
const ColorSync = {
mounted() {
const picker = this.el.querySelector('input[type="color"]')
const text = this.el.querySelector('input[type="text"]')
if (picker && text) {
picker.addEventListener('input', (e) => {
text.value = e.target.value
})
text.addEventListener('input', (e) => {
picker.value = e.target.value
})
}
}
}
const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
const liveSocket = new LiveSocket("/live", Socket, { const liveSocket = new LiveSocket("/live", Socket, {
longPollFallbackMs: 2500, longPollFallbackMs: 2500,
params: {_csrf_token: csrfToken}, params: {_csrf_token: csrfToken},
hooks: {...colocatedHooks}, hooks: {...colocatedHooks, ColorSync},
}) })
// Show progress bar on live navigation and form submits // Show progress bar on live navigation and form submits

View File

@ -130,22 +130,22 @@
<!-- Colors --> <!-- Colors -->
<div> <div>
<h3 class="font-semibold mb-3">Accent Color</h3> <h3 class="font-semibold mb-3">Accent Color</h3>
<form phx-change="update_color" phx-value-field="accent_color"> <form id="accent-color-form" phx-change="update_color" phx-value-field="accent_color" phx-hook="ColorSync">
<div class="flex gap-2 items-center"> <div class="flex gap-2 items-center">
<input <input
type="color" type="color"
id="accent-color-picker"
name="value" name="value"
value={@theme_settings.accent_color} value={@theme_settings.accent_color}
class="w-12 h-10 rounded cursor-pointer" class="w-12 h-10 rounded cursor-pointer"
phx-debounce="300"
/> />
<input <input
type="text" type="text"
id="accent-color-text"
name="value" name="value"
value={@theme_settings.accent_color} value={@theme_settings.accent_color}
class="input input-bordered input-sm flex-1 font-mono text-xs" class="input input-bordered input-sm flex-1 font-mono text-xs"
placeholder="#000000" placeholder="#000000"
phx-debounce="blur"
/> />
</div> </div>
</form> </form>