mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-10-03 17:15:19 -07:00
fix: keep the active tag row in view and document the full tag set
The 19-row menu is taller than its 280px max-height, so arrow-key navigation past the fold lost its highlight. Scroll the active row into view on index change, list the delivery tags in the README, and give [sarcastic] and [whispering] emoji that are not already used by [chuckle] and [shush].
This commit is contained in:
committed by
capy-ai-staging[bot]
parent
50d8d6a34f
commit
214adc5ff2
@@ -130,7 +130,9 @@ literally as text.
|
|||||||
With **Chatterbox Turbo** selected, type `/` in the text input to open the tag
|
With **Chatterbox Turbo** selected, type `/` in the text input to open the tag
|
||||||
inserter and add expressive tags inline with speech:
|
inserter and add expressive tags inline with speech:
|
||||||
|
|
||||||
`[laugh]` `[chuckle]` `[gasp]` `[cough]` `[sigh]` `[groan]` `[sniff]` `[shush]` `[clear throat]`
|
Sounds: `[laugh]` `[chuckle]` `[gasp]` `[cough]` `[sigh]` `[groan]` `[sniff]` `[shush]` `[clear throat]`
|
||||||
|
|
||||||
|
Delivery: `[angry]` `[crying]` `[dramatic]` `[fear]` `[happy]` `[narration]` `[sarcastic]` `[surprised]` `[whispering]` `[advertisement]`
|
||||||
|
|
||||||
### Post-Processing Effects
|
### Post-Processing Effects
|
||||||
|
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ const PARALINGUISTIC_TAGS = [
|
|||||||
{ tag: '[fear]', label: 'fear', emoji: '\u{1F628}' },
|
{ tag: '[fear]', label: 'fear', emoji: '\u{1F628}' },
|
||||||
{ tag: '[happy]', label: 'happy', emoji: '\u{1F60A}' },
|
{ tag: '[happy]', label: 'happy', emoji: '\u{1F60A}' },
|
||||||
{ tag: '[narration]', label: 'narration', emoji: '\u{1F4D6}' },
|
{ tag: '[narration]', label: 'narration', emoji: '\u{1F4D6}' },
|
||||||
{ tag: '[sarcastic]', label: 'sarcastic', emoji: '\u{1F60F}' },
|
{ tag: '[sarcastic]', label: 'sarcastic', emoji: '\u{1F644}' },
|
||||||
{ tag: '[surprised]', label: 'surprised', emoji: '\u{1F632}' },
|
{ tag: '[surprised]', label: 'surprised', emoji: '\u{1F632}' },
|
||||||
{ tag: '[whispering]', label: 'whispering', emoji: '\u{1F92B}' },
|
{ tag: '[whispering]', label: 'whispering', emoji: '\u{1F62F}' },
|
||||||
{ tag: '[advertisement]', label: 'advertisement', emoji: '\u{1F4E2}' },
|
{ tag: '[advertisement]', label: 'advertisement', emoji: '\u{1F4E2}' },
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
@@ -147,6 +147,7 @@ export const ParalinguisticInput = forwardRef<ParalinguisticInputRef, Paralingui
|
|||||||
left: 0,
|
left: 0,
|
||||||
});
|
});
|
||||||
const triggerRangeRef = useRef<Range | null>(null);
|
const triggerRangeRef = useRef<Range | null>(null);
|
||||||
|
const menuListRef = useRef<HTMLDivElement | null>(null);
|
||||||
const lastSerializedRef = useRef<string>('');
|
const lastSerializedRef = useRef<string>('');
|
||||||
const isComposingRef = useRef(false);
|
const isComposingRef = useRef(false);
|
||||||
|
|
||||||
@@ -155,6 +156,14 @@ export const ParalinguisticInput = forwardRef<ParalinguisticInputRef, Paralingui
|
|||||||
element: editorRef.current,
|
element: editorRef.current,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// The list is taller than the menu's max-height, so keep the keyboard
|
||||||
|
// highlight visible as ArrowUp/ArrowDown move it.
|
||||||
|
useEffect(() => {
|
||||||
|
if (!showMenu) return;
|
||||||
|
const item = menuListRef.current?.children[menuIndex] as HTMLElement | undefined;
|
||||||
|
item?.scrollIntoView({ block: 'nearest' });
|
||||||
|
}, [showMenu, menuIndex]);
|
||||||
|
|
||||||
// Filtered tag list for the autocomplete menu
|
// Filtered tag list for the autocomplete menu
|
||||||
const filteredTags = PARALINGUISTIC_TAGS.filter((t) =>
|
const filteredTags = PARALINGUISTIC_TAGS.filter((t) =>
|
||||||
t.label.toLowerCase().includes(menuFilter.toLowerCase()),
|
t.label.toLowerCase().includes(menuFilter.toLowerCase()),
|
||||||
@@ -392,6 +401,7 @@ export const ParalinguisticInput = forwardRef<ParalinguisticInputRef, Paralingui
|
|||||||
createPortal(
|
createPortal(
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
<motion.div
|
<motion.div
|
||||||
|
ref={menuListRef}
|
||||||
initial={{ opacity: 0, y: 4 }}
|
initial={{ opacity: 0, y: 4 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
exit={{ opacity: 0, y: 4 }}
|
exit={{ opacity: 0, y: 4 }}
|
||||||
|
|||||||
Reference in New Issue
Block a user