mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
feat(desktop): add search to agent emoji picker (#2630)
## Why The agent avatar picker disables Emoji Mart search, making emojis difficult to find when creating or editing an agent. ## What - Enable sticky search in the shared agent avatar picker - Focus the search field when the Emoji tab opens - Add end-to-end coverage for search, focus, and selection ## Risk Assessment Low — this is limited to the desktop agent avatar picker and does not change avatar persistence or agent configuration. ## References - `pnpm --dir desktop test` — 3,448 passed - `pnpm --dir desktop typecheck` — passed - `pnpm --dir desktop exec playwright test tests/e2e/agents.spec.ts` — 20 passed --- **Update Jul 24, 16:28 EDT:** Completed `CONTRIBUTING.md` validation. ### Manual test 1. Create an agent and open Add avatar → Emoji. 2. Confirm the search field is focused and filters results. 3. Select an emoji and confirm it becomes the avatar. 4. Repeat while editing an existing agent. ### Validation - `just ci` — passed - `just test` — passed ### Follow-up work None. Generated with Codex
This commit is contained in:
@@ -133,6 +133,32 @@ export function AgentCreationPreview({
|
||||
isAvatarMenuOpen && activeTab === "emoji",
|
||||
);
|
||||
|
||||
// Emoji Mart mounts its search input inside a shadow root. Wait for it
|
||||
// before focusing so the surrounding Radix popover cannot win the race.
|
||||
React.useEffect(() => {
|
||||
if (!isAvatarMenuOpen || activeTab !== "emoji") {
|
||||
return;
|
||||
}
|
||||
|
||||
let animationFrame = 0;
|
||||
const focusSearchInput = () => {
|
||||
const searchInput =
|
||||
emojiPickerContainerRef.current
|
||||
?.querySelector("em-emoji-picker")
|
||||
?.shadowRoot?.querySelector<HTMLInputElement>(
|
||||
'input[type="search"]',
|
||||
) ?? null;
|
||||
if (!searchInput) {
|
||||
animationFrame = window.requestAnimationFrame(focusSearchInput);
|
||||
return;
|
||||
}
|
||||
searchInput.focus();
|
||||
};
|
||||
|
||||
animationFrame = window.requestAnimationFrame(focusSearchInput);
|
||||
return () => window.cancelAnimationFrame(animationFrame);
|
||||
}, [activeTab, isAvatarMenuOpen]);
|
||||
|
||||
const customColorDraft = React.useMemo(
|
||||
() => hsvToHex(customHue, customSaturation, customValue),
|
||||
[customHue, customSaturation, customValue],
|
||||
@@ -550,6 +576,7 @@ export function AgentCreationPreview({
|
||||
style={emojiMartThemeVars}
|
||||
>
|
||||
<Picker
|
||||
autoFocus
|
||||
categories={EMOJI_MART_CATEGORIES}
|
||||
data={emojiData}
|
||||
dynamicWidth
|
||||
@@ -577,7 +604,7 @@ export function AgentCreationPreview({
|
||||
applyEmojiAvatar(emoji.native, nextColor);
|
||||
}}
|
||||
previewPosition="none"
|
||||
searchPosition="none"
|
||||
searchPosition="sticky"
|
||||
set="native"
|
||||
skinTonePosition="none"
|
||||
theme="auto"
|
||||
|
||||
@@ -263,6 +263,29 @@ test("built-in persona edits persist", async ({ page }) => {
|
||||
});
|
||||
});
|
||||
|
||||
test("searches agent avatar emoji with focus on open", async ({ page }) => {
|
||||
await gotoApp(page);
|
||||
await page.getByTestId("open-agents-view").click();
|
||||
await page.getByTestId("new-agent-card").click();
|
||||
await page.getByRole("menuitem", { name: "Create from scratch" }).click();
|
||||
|
||||
await expect(page.getByTestId("persona-dialog")).toBeVisible();
|
||||
await page.getByLabel("Add avatar").click();
|
||||
await page.getByRole("tab", { name: "Emoji" }).click();
|
||||
|
||||
const picker = page.locator("em-emoji-picker");
|
||||
const searchInput = picker.locator("input[type='search']");
|
||||
await expect(searchInput).toBeVisible();
|
||||
await expect(searchInput).toBeFocused();
|
||||
|
||||
await searchInput.fill("rocket");
|
||||
await picker.locator("button[aria-label='🚀']").first().click();
|
||||
|
||||
await expect(page.getByRole("img", { name: "Agent name avatar" })).toHaveText(
|
||||
"🚀",
|
||||
);
|
||||
});
|
||||
|
||||
test("agent avatar emoji picker scrolls inside its popover", async ({
|
||||
page,
|
||||
}) => {
|
||||
|
||||
Reference in New Issue
Block a user