fix(ui): refine icon picker appearance
This commit is contained in:
@@ -110,7 +110,7 @@ describe('TypeCustomizePopover', () => {
|
||||
it('calls onChangeColor when a color is clicked', () => {
|
||||
renderPopover()
|
||||
|
||||
const colorButtons = screen.getAllByTitle(/red|blue|green|purple|yellow|orange|teal|pink/i)
|
||||
const colorButtons = screen.getAllByTitle(/red|blue|green|purple|yellow|orange|pink/i)
|
||||
fireEvent.click(colorButtons[0])
|
||||
|
||||
expect(onChangeColor).toHaveBeenCalled()
|
||||
@@ -123,6 +123,31 @@ describe('TypeCustomizePopover', () => {
|
||||
expect(onChangeIcon).toHaveBeenCalledWith('wrench')
|
||||
})
|
||||
|
||||
it('renders picker icons slightly larger than the sidebar icon size', () => {
|
||||
renderPopover()
|
||||
|
||||
const icon = screen.getByTitle('wrench').querySelector('svg')
|
||||
expect(icon).toHaveAttribute('width', '18')
|
||||
expect(icon).toHaveAttribute('height', '18')
|
||||
expect(icon).toHaveClass('size-[18px]')
|
||||
})
|
||||
|
||||
it('orders color swatches by hue before neutral gray', () => {
|
||||
renderPopover()
|
||||
|
||||
const colorRow = screen.getByTitle('Red').parentElement
|
||||
expect(Array.from(colorRow?.children ?? []).map((element) => element.getAttribute('title'))).toEqual([
|
||||
'Red',
|
||||
'Orange',
|
||||
'Yellow',
|
||||
'Green',
|
||||
'Blue',
|
||||
'Purple',
|
||||
'Pink',
|
||||
'Gray',
|
||||
])
|
||||
})
|
||||
|
||||
it('calls onClose when Done is clicked', () => {
|
||||
renderPopover()
|
||||
|
||||
@@ -130,10 +155,10 @@ describe('TypeCustomizePopover', () => {
|
||||
expect(onClose).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('renders all color options including teal and pink', () => {
|
||||
it('renders curated color options without the teal near-duplicate', () => {
|
||||
renderPopover()
|
||||
|
||||
expect(screen.getByTitle('Teal')).toBeInTheDocument()
|
||||
expect(screen.queryByTitle('Teal')).not.toBeInTheDocument()
|
||||
expect(screen.getByTitle('Pink')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
|
||||
@@ -49,6 +49,20 @@ interface TemplateSectionProps {
|
||||
onTemplateChange: (value: string) => void
|
||||
}
|
||||
|
||||
const ICON_PICKER_ICON_SIZE = 18
|
||||
const ICON_PICKER_ICON_CLASS_NAME = 'size-[18px]'
|
||||
const COLOR_PICKER_ACCENT_COLORS = [
|
||||
'red',
|
||||
'orange',
|
||||
'yellow',
|
||||
'green',
|
||||
'blue',
|
||||
'purple',
|
||||
'pink',
|
||||
'gray',
|
||||
].map((key) => ACCENT_COLORS.find((color) => color.key === key) ?? null)
|
||||
.filter((color): color is typeof ACCENT_COLORS[number] => color !== null)
|
||||
|
||||
/** Debounce a callback by `delay` ms. Returns a stable ref-based wrapper. */
|
||||
function useDebouncedCallback(fn: (v: string) => void, delay: number): (v: string) => void {
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)
|
||||
@@ -68,7 +82,7 @@ function ColorSection({ selectedColor, locale, onSelectColor }: ColorSectionProp
|
||||
<>
|
||||
<div className="font-mono-overline mb-2 text-muted-foreground">{translate(locale, 'customize.color')}</div>
|
||||
<div className="flex gap-2 mb-3 flex-wrap">
|
||||
{ACCENT_COLORS.map((color) => (
|
||||
{COLOR_PICKER_ACCENT_COLORS.map((color) => (
|
||||
<Button
|
||||
key={color.key}
|
||||
type="button"
|
||||
@@ -118,7 +132,10 @@ function IconSection({
|
||||
className="h-7 pl-7 pr-2 py-1 text-[12px]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-1 overflow-y-auto" style={{ maxHeight: 160 }}>
|
||||
<div
|
||||
className="grid gap-1 overflow-y-auto"
|
||||
style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(30px, 1fr))', maxHeight: 160 }}
|
||||
>
|
||||
{filteredIcons.length === 0 ? (
|
||||
<div className="w-full py-6 text-center text-[12px] text-muted-foreground">
|
||||
{translate(locale, 'customize.noIconsFound')}
|
||||
@@ -131,7 +148,7 @@ function IconSection({
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
className={cn(
|
||||
'h-[30px] w-[30px] rounded p-0 transition-colors',
|
||||
'h-[30px] w-[30px] justify-self-center rounded p-0 transition-colors',
|
||||
selectedIcon === name
|
||||
? 'bg-primary/10 text-primary'
|
||||
: 'text-muted-foreground hover:bg-accent hover:text-foreground',
|
||||
@@ -140,7 +157,7 @@ function IconSection({
|
||||
title={name}
|
||||
aria-label={name}
|
||||
>
|
||||
<Icon size={16} />
|
||||
<Icon size={ICON_PICKER_ICON_SIZE} className={ICON_PICKER_ICON_CLASS_NAME} />
|
||||
</Button>
|
||||
))
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user