tag picker

This commit is contained in:
2025-11-11 15:59:17 +01:00
parent cd9a8a0204
commit 1193c71579
5 changed files with 53 additions and 35 deletions
+2 -1
View File
@@ -84,12 +84,13 @@ const createDesktopSurface = ({
const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null;
const detail = detailOpen && detailProps
? (() => {
const { onClose, onOpenPreview, ...restDetailProps } = detailProps;
const { onClose, onOpenPreview, tags: tagOptions, ...restDetailProps } = detailProps;
return (
<DocumentViewerPanel
variant="sidebar"
onCollapsePanel={onClose}
onMaximizePanel={onOpenPreview}
tagOptions={tagOptions}
{...restDetailProps}
/>
);
@@ -1,10 +1,6 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import useFloatingMenu from '../ui/useFloatingMenu';
import {
PlusIcon,
CheckIcon,
CircleDashedCheckIcon,
} from '../ui/icons';
import { CheckIcon, CircleDashedCheckIcon, PlusIcon } from '../ui/icons';
const STATE_ORDER = {
all: 0,
@@ -117,7 +113,8 @@ const SelectionAssignmentMenu = ({
);
const handleCreate = useCallback(
async () => {
async (event) => {
event?.preventDefault?.();
if (typeof onCreate !== 'function') {
return;
}
@@ -144,9 +141,12 @@ const SelectionAssignmentMenu = ({
);
const canCreate = Boolean(onCreate);
const showCreateOption = canCreate
&& query.trim().length > 0
&& !existingLabels.has(query.trim().toLowerCase());
const trimmedQuery = query.trim();
const queryKey = trimmedQuery.toLowerCase();
const canSubmitCreate = canCreate
&& trimmedQuery.length > 0
&& !existingLabels.has(queryKey)
&& !pending;
const handleTriggerClick = useCallback(() => {
if (disabled) {
@@ -184,15 +184,28 @@ const SelectionAssignmentMenu = ({
data-floating-position
>
<div className="selection-assignment__header">
<input
ref={inputRef}
type="text"
value={query}
onChange={(event) => setQuery(event.target.value)}
placeholder={placeholder}
aria-label={placeholder}
disabled={pending}
/>
<form className="selection-assignment__form" onSubmit={handleCreate}>
<input
ref={inputRef}
type="text"
value={query}
onChange={(event) => setQuery(event.target.value)}
placeholder={placeholder}
aria-label={placeholder}
disabled={pending}
/>
{canCreate ? (
<button
type="submit"
className="icon-button selection-assignment__add"
disabled={!canSubmitCreate}
aria-label={createLabel || 'Add'}
title={createLabel || 'Add'}
>
<PlusIcon aria-hidden="true" />
</button>
) : null}
</form>
</div>
<div className="selection-assignment__list" role="presentation">
{filteredItems.length ? (
@@ -237,19 +250,6 @@ const SelectionAssignmentMenu = ({
<div className="menu__empty selection-assignment__empty">{emptyMessage}</div>
)}
</div>
{showCreateOption ? (
<button
type="button"
className="menu__item selection-assignment__create"
onClick={handleCreate}
disabled={pending}
>
<PlusIcon className="selection-assignment__icon" aria-hidden="true" />
<span className="selection-assignment__label">
{createLabel ? `${createLabel}${query.trim()}` : `Create “${query.trim()}`}
</span>
</button>
) : null}
</div>
) : null}
</div>
@@ -93,12 +93,13 @@ const createDocumentsSurface = ({
const sidebarToggle = renderSidebarToggle ? renderSidebarToggle() : null;
const detail = detailOpen && detailProps
? (() => {
const { onClose, onOpenPreview, ...restDetailProps } = detailProps;
const { onClose, onOpenPreview, tags: tagOptions, ...restDetailProps } = detailProps;
return (
<DocumentViewerPanel
variant="sidebar"
onCollapsePanel={onClose}
onMaximizePanel={onOpenPreview}
tagOptions={tagOptions}
{...restDetailProps}
/>
);
+17 -2
View File
@@ -191,7 +191,14 @@
border-bottom: 1px solid var(--border-subtle);
}
.selection-assignment__header input {
.selection-assignment__form {
display: flex;
gap: 0.4rem;
align-items: stretch;
}
.selection-assignment__form input {
flex: 1 1 auto;
width: 100%;
padding: 0.35rem 0.6rem;
border: 1px solid var(--border-subtle);
@@ -201,12 +208,20 @@
font-size: 0.95rem;
}
.selection-assignment__header input:focus-visible {
.selection-assignment__form input:focus-visible {
outline: none;
border-color: color-mix(in oklch, var(--accent) 60%, transparent);
box-shadow: 0 0 0 1px color-mix(in oklch, var(--accent) 35%, transparent);
}
.selection-assignment__add {
align-self: stretch;
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 2rem;
}
.selection-assignment__list {
max-height: max(240px, 50vh);
overflow-y: auto;
+1
View File
@@ -247,6 +247,7 @@
.menu__list {
overflow-y: auto;
max-height: min(20rem, 60vh);
padding: 0.25rem;
display: flex;
flex-direction: column;