fix: align Properties panel visual style to design (pills, truncation, labels)

Sentence-case labels, colored tag pills, date chips, checkbox booleans,
blue URL links, status dot indicator, subtle Add Property button.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
lucaronin
2026-03-29 16:36:31 +02:00
parent 730b56ecbd
commit 08bcbc065e
5 changed files with 81 additions and 72 deletions

View File

@@ -5,7 +5,7 @@ import { EditableValue, TagPillList, UrlValue } from './EditableValue'
import { isUrlValue } from '../utils/url'
import { Calendar } from '@/components/ui/calendar'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { CalendarIcon, XIcon } from 'lucide-react'
import { XIcon } from 'lucide-react'
import { isValidCssColor } from '../utils/colorUtils'
import {
type PropertyDisplayMode,
@@ -14,7 +14,8 @@ import {
DISPLAY_MODE_OPTIONS,
DISPLAY_MODE_ICONS,
} from '../utils/propertyTypes'
import { StatusPill, StatusDropdown } from './StatusDropdown'
import { StatusDropdown } from './StatusDropdown'
import { getStatusStyle } from '../utils/statusStyles'
import { TagsDropdown } from './TagsDropdown'
import { getTagStyle } from '../utils/tagStyles'
import { ColorEditableValue } from './ColorInput'
@@ -37,14 +38,17 @@ function StatusValue({ propKey, value, isEditing, vaultStatuses, onSave, onStart
onSave: (key: string, value: string) => void; onStartEdit: (key: string | null) => void
}) {
const statusStr = String(value)
const style = getStatusStyle(statusStr)
return (
<span className="relative inline-flex min-w-0 items-center">
<span
className="cursor-pointer transition-opacity hover:opacity-80"
className="inline-flex cursor-pointer items-center gap-1.5 rounded px-2 py-0.5 text-[12px] font-medium transition-opacity hover:opacity-80"
style={{ backgroundColor: style.bg, color: style.color }}
onClick={() => onStartEdit(propKey)}
data-testid="status-badge"
>
<StatusPill status={statusStr} />
<span className="inline-block size-1.5 shrink-0 rounded-full" style={{ backgroundColor: style.color }} />
{statusStr}
</span>
{isEditing && (
<StatusDropdown
@@ -86,11 +90,8 @@ function TagsValue({ propKey, value, isEditing, vaultTags, onSave, onStartEdit }
className="transition-[max-width] duration-150 group-hover/tag:[mask-image:linear-gradient(to_right,black_60%,transparent_100%)]"
style={{
color: style.color,
fontFamily: "'IBM Plex Mono', monospace",
fontSize: 10,
fontWeight: 600,
letterSpacing: '0',
textTransform: 'uppercase' as const,
fontSize: 11,
fontWeight: 500,
overflow: 'hidden',
whiteSpace: 'nowrap' as const,
}}
@@ -99,7 +100,7 @@ function TagsValue({ propKey, value, isEditing, vaultTags, onSave, onStartEdit }
</span>
<button
className="ml-0.5 max-w-0 overflow-hidden border-none bg-transparent p-0 leading-none opacity-0 transition-all duration-150 group-hover/tag:max-w-[14px] group-hover/tag:opacity-100"
style={{ color: style.color, fontSize: 10, flexShrink: 0 }}
style={{ color: style.color, fontSize: 11, flexShrink: 0 }}
onClick={() => handleRemove(tag)}
title={`Remove ${tag}`}
>
@@ -128,13 +129,15 @@ function TagsValue({ propKey, value, isEditing, vaultTags, onSave, onStartEdit }
function BooleanToggle({ value, onToggle }: { value: boolean; onToggle: () => void }) {
return (
<button
className="rounded border border-border bg-transparent px-2 py-0.5 text-xs text-secondary-foreground transition-colors hover:bg-muted"
onClick={onToggle}
data-testid="boolean-toggle"
>
{value ? '\u2713 Yes' : '\u2717 No'}
</button>
<label className="inline-flex cursor-pointer items-center gap-1.5" data-testid="boolean-toggle">
<input
type="checkbox"
checked={value}
onChange={onToggle}
className="size-3.5 cursor-pointer accent-primary"
/>
<span className="text-[12px] text-secondary-foreground">{value ? 'Yes' : 'No'}</span>
</label>
)
}
@@ -160,11 +163,10 @@ function DateValue({ value, onSave }: {
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<button
className="inline-flex min-w-0 cursor-pointer items-center gap-1 rounded border-none bg-transparent px-1 py-0.5 text-right text-[12px] text-secondary-foreground transition-colors hover:bg-muted"
className={`inline-flex min-w-0 cursor-pointer items-center gap-1 border-none px-2 py-0.5 text-right text-[12px] font-medium transition-colors hover:opacity-80${formatted ? ' rounded bg-muted text-accent-foreground' : ' bg-transparent text-muted-foreground'}`}
title={value}
data-testid="date-display"
>
<CalendarIcon className="size-3 shrink-0 text-muted-foreground" />
<span className={`min-w-0 truncate${!formatted ? ' text-muted-foreground' : ''}`}>{formatted || 'Pick a date\u2026'}</span>
</button>
</PopoverTrigger>