fixup! ✨(frontend) re-focus toolbar on shortcut when already open
This commit is contained in:
+2
-3
@@ -16,13 +16,12 @@ and this project adheres to
|
||||
|
||||
- ♻️(frontend) replace custom reactions toolbar with react aria popover #985
|
||||
- 🔒️(frontend) uninstall curl from the frontend production image #987
|
||||
- 💄(frontend) add focus ring to reaction emoji buttons
|
||||
- 💄(frontend) add focus ring to reaction emoji buttons #1002
|
||||
- ✨(frontend) introduce a shortcut settings tab #975
|
||||
- 🚚(frontend) rename "wellknown" directory to "well-known" #1009
|
||||
- 🌐(frontend) localize SR modifier labels #1010
|
||||
- ⬆️(backend) update python dependencies #1011
|
||||
- ♿️(a11y) fix focus ring on tab container components #1012
|
||||
|
||||
- ♿️(frontend) fix focus ring on tab container components #1012
|
||||
- ♻️(frontend) use react aria toolbar for arrow key navigation #1005
|
||||
|
||||
## [1.8.0] - 2026-02-20
|
||||
|
||||
@@ -12,11 +12,7 @@ import {
|
||||
} from '@/features/rooms/livekit/components/ReactionPortal'
|
||||
import { getEmojiLabel } from '@/features/rooms/livekit/utils/reactionUtils'
|
||||
import { useRegisterKeyboardShortcut } from '@/features/shortcuts/useRegisterKeyboardShortcut'
|
||||
import {
|
||||
Popover as RACPopover,
|
||||
DialogTrigger,
|
||||
Toolbar,
|
||||
} from 'react-aria-components'
|
||||
import { Popover as RACPopover, Toolbar } from 'react-aria-components'
|
||||
import { FocusScope } from '@react-aria/focus'
|
||||
import { Participant } from 'livekit-client'
|
||||
import useRateLimiter from '@/hooks/useRateLimiter'
|
||||
@@ -44,6 +40,7 @@ export const ReactionsToggle = () => {
|
||||
const [reactions, setReactions] = useState<Reaction[]>([])
|
||||
const instanceIdRef = useRef(0)
|
||||
const room = useRoomContext()
|
||||
const triggerRef = useRef<HTMLButtonElement>(null)
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
|
||||
@@ -126,73 +123,76 @@ export const ReactionsToggle = () => {
|
||||
return (
|
||||
<>
|
||||
<div className={css({ position: 'relative' })}>
|
||||
<DialogTrigger isOpen={isOpen} onOpenChange={setIsOpen}>
|
||||
<ToggleButton
|
||||
id="reaction-toggle"
|
||||
square
|
||||
variant="primaryDark"
|
||||
aria-label={t('button')}
|
||||
tooltip={t('button')}
|
||||
isSelected={isOpen}
|
||||
onChange={setIsOpen}
|
||||
>
|
||||
<RiEmotionLine />
|
||||
</ToggleButton>
|
||||
<RACPopover
|
||||
placement="top"
|
||||
offset={8}
|
||||
isNonModal
|
||||
shouldCloseOnInteractOutside={() => false}
|
||||
className={css({
|
||||
borderRadius: '8px',
|
||||
padding: '0.35rem',
|
||||
backgroundColor: 'primaryDark.50',
|
||||
'&[data-entering]': {
|
||||
animation: 'fade 200ms ease',
|
||||
},
|
||||
'&[data-exiting]': {
|
||||
animation: 'fade 200ms ease-in reverse',
|
||||
},
|
||||
})}
|
||||
>
|
||||
{/* eslint-disable-next-line jsx-a11y/no-autofocus -- FocusScope autoFocus is programmatic focus for overlays, not the HTML autofocus attribute */}
|
||||
<FocusScope autoFocus restoreFocus>
|
||||
<div onKeyDownCapture={handleToolbarKeyDown}>
|
||||
<Toolbar
|
||||
orientation="horizontal"
|
||||
aria-label={t('button')}
|
||||
className={css({
|
||||
display: 'flex',
|
||||
gap: '0.5rem',
|
||||
})}
|
||||
>
|
||||
{Object.values(Emoji).map((emoji, index) => (
|
||||
<Button
|
||||
key={index}
|
||||
onPress={() => debouncedSendReaction(emoji)}
|
||||
aria-label={t('send', { emoji: getEmojiLabel(emoji, t) })}
|
||||
variant="primaryTextDark"
|
||||
size="sm"
|
||||
square
|
||||
data-attr={`send-reaction-${emoji}`}
|
||||
>
|
||||
<img
|
||||
src={`/assets/reactions/${emoji}.png`}
|
||||
alt=""
|
||||
className={css({
|
||||
width: '28px',
|
||||
height: '28px',
|
||||
pointerEvents: 'none',
|
||||
userSelect: 'none',
|
||||
})}
|
||||
/>
|
||||
</Button>
|
||||
))}
|
||||
</Toolbar>
|
||||
</div>
|
||||
</FocusScope>
|
||||
</RACPopover>
|
||||
</DialogTrigger>
|
||||
<ToggleButton
|
||||
ref={triggerRef}
|
||||
id="reaction-toggle"
|
||||
square
|
||||
variant="primaryDark"
|
||||
aria-label={t('button')}
|
||||
tooltip={t('button')}
|
||||
isSelected={isOpen}
|
||||
onChange={setIsOpen}
|
||||
>
|
||||
<RiEmotionLine />
|
||||
</ToggleButton>
|
||||
<RACPopover
|
||||
triggerRef={triggerRef}
|
||||
isOpen={isOpen}
|
||||
onOpenChange={setIsOpen}
|
||||
placement="top"
|
||||
offset={8}
|
||||
isNonModal
|
||||
shouldCloseOnInteractOutside={() => false}
|
||||
className={css({
|
||||
borderRadius: '8px',
|
||||
padding: '0.35rem',
|
||||
backgroundColor: 'primaryDark.50',
|
||||
'&[data-entering]': {
|
||||
animation: 'fade 200ms ease',
|
||||
},
|
||||
'&[data-exiting]': {
|
||||
animation: 'fade 200ms ease-in reverse',
|
||||
},
|
||||
})}
|
||||
>
|
||||
{/* eslint-disable-next-line jsx-a11y/no-autofocus -- FocusScope autoFocus is programmatic focus for overlays, not the HTML autofocus attribute */}
|
||||
<FocusScope autoFocus restoreFocus>
|
||||
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions -- handles Tab exit and arrow wrapping for the portal-rendered toolbar */}
|
||||
<div onKeyDownCapture={handleToolbarKeyDown}>
|
||||
<Toolbar
|
||||
orientation="horizontal"
|
||||
aria-label={t('button')}
|
||||
className={css({
|
||||
display: 'flex',
|
||||
gap: '0.5rem',
|
||||
})}
|
||||
>
|
||||
{Object.values(Emoji).map((emoji, index) => (
|
||||
<Button
|
||||
key={index}
|
||||
onPress={() => debouncedSendReaction(emoji)}
|
||||
aria-label={t('send', { emoji: getEmojiLabel(emoji, t) })}
|
||||
variant="primaryTextDark"
|
||||
size="sm"
|
||||
square
|
||||
data-attr={`send-reaction-${emoji}`}
|
||||
>
|
||||
<img
|
||||
src={`/assets/reactions/${emoji}.pPng`}
|
||||
alt=""
|
||||
className={css({
|
||||
width: '28px',
|
||||
height: '28px',
|
||||
pointerEvents: 'none',
|
||||
userSelect: 'none',
|
||||
})}
|
||||
/>
|
||||
</Button>
|
||||
))}
|
||||
</Toolbar>
|
||||
</div>
|
||||
</FocusScope>
|
||||
</RACPopover>
|
||||
</div>
|
||||
<ReactionPortals reactions={reactions} />
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user