diff --git a/CHANGELOG.md b/CHANGELOG.md index 2acfc81..cc113d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,22 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] -Nothing yet. +### Fixed +- The security note in the ID generator rendered as overlapping fragments. It + was a paragraph with `display: flex`, which makes every inline child — both + text runs and the inline `` — a separate flex item laid out in a row. +- Dropdowns had cramped padding and the native arrow overlapped the border at + our control height. The native arrow is now suppressed and replaced with a + chevron drawn inside the padding box, with room reserved for it. +- The preset dropdown always displayed "Preset…" regardless of the settings in + use. It now shows whichever preset the current options match, derived from + those options rather than stored, so it survives a reload and falls back to + "Custom" as soon as any field changes. + +### Changed +- The sidebar collapse control moved from the bottom of the tool list to the + top, where it is visible without scrolling, and the collapse now animates. + Both respect `prefers-reduced-motion`. ## [0.2.2] — 2026-09-24 diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index ff2cdce..64d9c3d 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -54,7 +54,11 @@ function ToolLinks({ } > - {!collapsed && {tool.title}} + {!collapsed && ( + + {tool.title} + + )} ))} @@ -70,35 +74,40 @@ export function Sidebar() { return ( ) } diff --git a/src/components/ui/Select.tsx b/src/components/ui/Select.tsx index c8aabc2..35ae8d3 100644 --- a/src/components/ui/Select.tsx +++ b/src/components/ui/Select.tsx @@ -1,12 +1,25 @@ import type { ReactNode, SelectHTMLAttributes } from 'react' import { cn } from '@/lib/util/cn' -export function Select({ className, ...rest }: SelectHTMLAttributes) { +/** + * The native arrow sits outside the padding box and cannot be styled, so it + * collides with the border at our control height. We suppress it with + * appearance-none and draw our own chevron as a background image, leaving + * explicit room for it on the right. + */ +const CHEVRON = + "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%238b8d98' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E\")" + +export function Select({ className, style, ...rest }: SelectHTMLAttributes) { return ( { const preset = PRESETS.find((p) => p.name === e.target.value) if (preset) applyOptions((p) => ({ ...p, ...preset.options })) }} title="Load a preset" > - + {PRESETS.map((p) => (