Skip to content

Commit efa99bf

Browse files
authored
feat(UX): Add click-to-focus behavior with high-visibility highlight on Live Preview placeholder (JhaSourav07#2403)
## Description Fixes JhaSourav07#2178 When a user lands on the `/customize`(customization studio) page without a username set, the "Live Preview" panel displays a dotted box with a central upward arrow icon (`↑`). From a user experience perspective, this creates a "false affordance" where clicking it yields zero behavior. This PR introduces an interactive click-to-focus micro-interaction. Clicking anywhere on the central preview placeholder arrow/box wrapper automatically triggers a focus event on the "GitHub Username" input field. Additionally, a direct dynamic visual highlight layout override (emerald green outline ring and a subtle transform scale bump) is applied on focus to cleanly guide the user's focus into the configuration panel. ## Pillar - [ ] 🎨 Pillar 1 — New Theme Design - [ ] 📐 Pillar 2 — Geometric SVG Improvement - [ ] 🕐 Pillar 3 — Timezone Logic Optimization - [x]🛠️ Other (Bug fix, refactoring, docs) ## Visual Preview **Clicking the central live preview container triggers the high-visibility configuration highlight:** <img width="1280" height="832" alt="Screenshot 2026-06-01 at 8 16 10 PM" src="https://github.com/user-attachments/assets/ab005891-f8fc-4609-8e1e-3fe17570938f" /> ## Checklist before requesting a review: - [x] I have read the `CONTRIBUTING.md` file. - [x] I have tested these changes locally (`localhost:3000/api/streak?user=YOUR_USERNAME`). - [x] I have run `npm run format` and `npm run lint` locally and resolved all errors (CI will fail otherwise). - [x] My commits follow the Conventional Commits format (e.g., `feat(themes): ...`, `fix(calculate): ...`). - [x] I have updated `README.md` if I added a new theme or URL parameter. - [x] I have started the repo. - [x] I have made sure that i have only one commit to merge in this PR. - [x] The SVG output matches the CommitPulse "premium quality" aesthetic standard (no raw elements, smooth animations, correct fonts). - [x] (Recommended) I joined the CommitPulse Discord community for contributor discussions, mentorship, and faster PR support.
2 parents 224528c + f78022d commit efa99bf

2 files changed

Lines changed: 25 additions & 7 deletions

File tree

app/customize/components/ControlsPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ export function ControlsPanel({
146146
value={username}
147147
onChange={(e) => onUsernameChange(e.target.value)}
148148
placeholder="jhasourav07"
149-
className="w-full bg-white/60 backdrop-blur-md border border-black/10 dark:bg-black/40 dark:border-white/10 rounded-xl px-4 py-2.5 text-sm font-mono text-black dark:text-emerald-300 placeholder:text-gray-400 dark:placeholder:text-white/60 outline-none focus:border-emerald-500/50 transition-colors"
149+
className="w-full bg-white/60 backdrop-blur-md border border-black/10 dark:bg-black/40 dark:border-white/10 rounded-xl px-4 py-2.5 text-sm font-mono text-black dark:text-emerald-300 placeholder:text-gray-400 dark:placeholder:text-white/60 outline-none focus:border-emerald-500/50 transition-all duration-300"
150150
/>
151151
</ControlRow>
152152

app/customize/page.tsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,6 @@ function CustomizePageInner(): ReactElement {
191191
})
192192
.then((text) => {
193193
if (!text) return;
194-
// Sanitize SVG using DOMPurify with the SVG profile.
195-
// - Forbid risky tags like foreignObject and embedded content
196-
// - Forbid xlink:href to avoid external references
197-
// - Use a conservative URI whitelist to prevent javascript: URIs
198194
const sanitized = DOMPurify.sanitize(text, {
199195
USE_PROFILES: { svg: true },
200196
ADD_TAGS: ['animate', 'style'],
@@ -427,7 +423,29 @@ function CustomizePageInner(): ReactElement {
427423
Live Preview
428424
</p>
429425

430-
<div className="group relative">
426+
{/* ─── MOVING THE INTERACTION LISTENER DIRECTLY TO THE OUTER WRAPPER CONTAINER ROW ─── */}
427+
<div
428+
className="group relative"
429+
onClick={(e) => {
430+
// Only trigger the focus highlight workflow if the placeholder box is actively rendering
431+
if (!hasUsername) {
432+
e.stopPropagation();
433+
const input = document.getElementById('username-input') as HTMLInputElement;
434+
if (input) {
435+
input.focus();
436+
input.style.outline = '4px solid #10b981';
437+
input.style.outlineOffset = '2px';
438+
input.style.transform = 'scale(1.02)';
439+
input.style.transition = 'all 0.3s ease';
440+
441+
setTimeout(() => {
442+
input.style.outline = 'none';
443+
input.style.transform = 'scale(1)';
444+
}, 1000);
445+
}
446+
}
447+
}}
448+
>
431449
{/* Glow ring */}
432450
<div className="absolute -inset-px bg-gradient-to-br from-emerald-500/20 to-purple-500/20 rounded-[1.5rem] opacity-0 group-hover:opacity-100 transition-opacity duration-700 blur-lg pointer-events-none" />
433451

@@ -503,7 +521,7 @@ function CustomizePageInner(): ReactElement {
503521
)}
504522
</div>
505523
) : (
506-
<div className="relative z-10 flex w-full max-w-xl flex-col items-center justify-center rounded-[1.25rem] border border-dashed border-black/10 bg-gray-100/80 backdrop-blur-md dark:border-white/10 dark:bg-white/3 px-6 py-12 text-center">
524+
<div className="relative z-10 flex w-full max-w-xl flex-col items-center justify-center rounded-[1.25rem] border border-dashed border-black/10 bg-gray-100/80 backdrop-blur-md dark:border-white/10 dark:bg-white/3 hover:border-black/30 dark:hover:border-white/30 transition-colors cursor-pointer px-6 py-12 text-center">
507525
<div className="mb-4 flex h-14 w-14 items-center justify-center rounded-2xl border border-black/10 bg-gray-100/80 dark:border-white/10 dark:bg-white/4 text-gray-500 dark:text-emerald-300/70">
508526
<svg
509527
xmlns="http://www.w3.org/2000/svg"

0 commit comments

Comments
 (0)