From 23ec5cfcbf2be6dd956d48d8cc45c7b7afc70d0d Mon Sep 17 00:00:00 2001 From: Collin Fingar Date: Tue, 18 Mar 2025 11:56:32 -0400 Subject: [PATCH] ColorPickerInput: Fixed color picker disappearing on input blur (#102241) * ColorPickerInput: Fixed color picker disappearing on input blur * Updates per feedback around targeting method * Updated per feedback - testid vs id --- .../ColorPicker/ColorPickerInput.test.tsx | 18 ++++++++++++++++++ .../ColorPicker/ColorPickerInput.tsx | 12 ++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.test.tsx b/packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.test.tsx index 8b81be33bf0..9f13e67918b 100644 --- a/packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.test.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.test.tsx @@ -12,6 +12,24 @@ describe('ColorPickerInput', () => { expect(screen.getByTestId('color-popover')).toBeInTheDocument(); }); + it('should hide color popover on blur', async () => { + render(); + expect(screen.queryByTestId('color-popover')).not.toBeInTheDocument(); + await userEvent.click(screen.getByRole('textbox')); + expect(screen.getByTestId('color-popover')).toBeInTheDocument(); + await userEvent.click(document.body); + expect(screen.queryByTestId('color-popover')).not.toBeInTheDocument(); + }); + + it('should not hide color popover on blur if clicked inside the color picker', async () => { + render(); + expect(screen.queryByTestId('color-popover')).not.toBeInTheDocument(); + await userEvent.click(screen.getByRole('textbox')); + expect(screen.getByTestId('color-popover')).toBeInTheDocument(); + await userEvent.click(screen.getAllByRole('slider')[0]); + expect(screen.queryByTestId('color-popover')).toBeInTheDocument(); + }); + it('should pass correct color to onChange callback', async () => { const mockOnChange = jest.fn(); render(); diff --git a/packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.tsx b/packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.tsx index add799af11c..381ad0403b2 100644 --- a/packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.tsx @@ -1,5 +1,5 @@ import { css, cx } from '@emotion/css'; -import { useState, forwardRef } from 'react'; +import { useState, forwardRef, FocusEvent } from 'react'; import { RgbaStringColorPicker } from 'react-colorful'; import { useThrottleFn } from 'react-use'; @@ -48,6 +48,14 @@ export const ColorPickerInput = forwardRef) => { + // Unless the user clicked inside the color picker, close it on blur + const isClickInPopover = document.querySelector('[data-testid="color-popover"]')?.contains(evt.relatedTarget); + if (!isClickInPopover) { + setIsOpen(false); + } + }; + return ( setIsOpen(false)}>
@@ -66,7 +74,7 @@ export const ColorPickerInput = forwardRef setIsOpen(true)} - onBlur={() => setIsOpen(false)} + onBlur={(e) => handleBlur(e)} ref={ref} isClearable />