Reference picker: improve usability

- show tags for nonexistent references
- click a badge to find the corresponding reference
This commit is contained in:
yu-i-i
2026-09-22 02:41:43 +02:00
parent f93211fd24
commit 07a77cafd9
2 changed files with 55 additions and 13 deletions
@@ -74,6 +74,7 @@ export default function ReferencePickerModal({
const [query, setQuery] = useState('')
const [selectedKeys, setSelectedKeys] = useState<string[]>([])
const [results, setResults] = useState<{ _source: Bib2JsonEntry }[]>([])
const [knownKeys, setKnownKeys] = useState<Set<string>>(() => new Set())
const pendingInitialKeysRef = useRef<string[]>([])
const requestIdRef = useRef(0)
@@ -109,9 +110,9 @@ export default function ReferencePickerModal({
setResults(r.hits)
if (pendingInitialKeysRef.current.length > 0) {
const knownKeys = new Set(r.hits.map(h => h._source.EntryKey))
const matched = pendingInitialKeysRef.current.filter(k => knownKeys.has(k))
if (matched.length > 0) setSelectedKeys(matched)
const known = new Set(r.hits.map(h => h._source.EntryKey))
setKnownKeys(known)
setSelectedKeys([...pendingInitialKeysRef.current])
pendingInitialKeysRef.current = []
}
}
@@ -143,6 +144,26 @@ export default function ReferencePickerModal({
const cancelButtonRef = useRef<HTMLButtonElement | null>(null)
const insertButtonRef = useRef<HTMLButtonElement | null>(null)
const scrollToReference = useCallback((key: string) => {
const index = results.findIndex(
r => r._source.EntryKey === key
)
if (index === -1) return
const el = document.getElementById(
`reference-picker-item-${index}`
)
el?.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
})
setFocusArea('list')
setFocusedIndex(index)
}, [results])
const removeOne = useCallback((key: string) => {
setSelectedKeys(prev => {
const index = prev.indexOf(key)
@@ -300,14 +321,23 @@ export default function ReferencePickerModal({
</OLRow>
<OLRow>
<div className="selected-key-tag">
<div className="selected-key-tags">
{selectedKeys.map((key, idx) => (
<OLTag
<span
key={`${key}-${idx}`}
className={
knownKeys.has(key)
? 'existing-key-tag'
: 'nonexistent-key-tag'
}
>
<OLTag
contentProps={{ onClick: () => scrollToReference(key) }}
closeBtnProps={{ onClick: () => removeOne(key) }}
>
{key}
</OLTag>
</span>
))}
</div>
</OLRow>
@@ -1,5 +1,5 @@
.references-search-modal {
.selected-key-tag {
.selected-key-tags {
position: relative;
display: flex;
flex-wrap: wrap;
@@ -13,10 +13,22 @@
margin-bottom: 8px;
box-shadow: 0 1px 0 var(--ds-color-neutral-100);
padding-bottom: 6px;
.badge-tag {
background-color:var(--ds-color-green-50) !important;
}
.selected-key-tags .existing-key-tag .badge-tag {
background-color: var(--ds-color-green-50) !important;
}
.selected-key-tags .nonexistent-key-tag .badge-tag {
background-color: var(--ds-color-red-50) !important;
}
.existing-key-tag .badge-tag-content-btn:hover {
background-color: var(--ds-color-green-100);
}
.nonexistent-key-tag .badge-tag-content-btn:hover {
background-color: transparent;
}
.badge-close:hover,
.badge-close:focus {
background-color: var(--ds-color-neutral-100);
}
.search-results {