Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## 2025-05-23 - [Input Clear Button Pattern]
**Learning:** Users often struggle to clear long inputs like URLs. Adding a conditional "Clear" button (X icon) that appears when text is present significantly improves usability on both desktop and mobile.
**Action:** When creating primary text inputs (search, URL), always implement a clear button that:
1. Only appears when input has value
2. Clears the state
3. Returns focus to the input element

## 2025-05-23 - [Component Cleanup]
**Learning:** Found an unused component `UrlInputWithBranding` that was a near-duplicate of `UrlInput`.
**Action:** Before modifying a component, check for duplicates or "with branding" variants that might be unused. remove them to keep the codebase clean.
145 changes: 0 additions & 145 deletions components/url-input-with-branding.tsx

This file was deleted.

23 changes: 21 additions & 2 deletions components/url-input.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { useState, useEffect } from "react";
import { Loader2, ArrowUp, Link, Sparkles } from "lucide-react";
import { useState, useEffect, useRef } from "react";
import { Loader2, ArrowUp, Link, Sparkles, X } from "lucide-react";
import { extractVideoId } from "@/lib/utils";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
Expand Down Expand Up @@ -31,6 +31,7 @@ export function UrlInput({
const [error, setError] = useState("");
const [isFocused, setIsFocused] = useState(false);
const [isValidUrl, setIsValidUrl] = useState(false);
const inputRef = useRef<HTMLInputElement>(null);
const forceSmartMode = isGrokProviderOnClient();
const showModeSelector =
!forceSmartMode && typeof onModeChange === "function";
Expand Down Expand Up @@ -68,6 +69,13 @@ export function UrlInput({
onSubmit(url);
};

const handleClear = () => {
setUrl("");
setIsValidUrl(false);
setError("");
inputRef.current?.focus();
};

return (
<form onSubmit={handleSubmit} className="w-full max-w-[615px]">
<div className="flex flex-col gap-2">
Expand All @@ -84,6 +92,7 @@ export function UrlInput({
<Link className="h-5 w-5 text-[#989999]" strokeWidth={1.8} />
</div>
<input
ref={inputRef}
type="url"
value={url}
onChange={(e) => setUrl(e.target.value)}
Expand All @@ -96,6 +105,16 @@ export function UrlInput({
className="flex-1 border-0 bg-transparent text-[14px] text-[#989999] placeholder:text-[#989999] focus:outline-none"
disabled={isLoading}
/>
{url && !isLoading && (
<button
type="button"
onClick={handleClear}
aria-label="Clear input"
className="flex h-5 w-5 items-center justify-center rounded-full text-[#989999] hover:bg-[#f0f1f1] hover:text-[#5c5c5c] focus:outline-none focus:ring-2 focus:ring-[#989999] focus:ring-offset-1"
>
<X className="h-3.5 w-3.5" />
</button>
)}
</div>

{/* Bottom row: Mode selector (left) and actions (right) */}
Expand Down