fix: restore shared UI behavior and keyboard accessibility

This commit is contained in:
webadderall
2026-09-21 18:28:25 +10:00
parent be60576475
commit bdc403e3e7
22 changed files with 132 additions and 42 deletions
@@ -275,7 +275,11 @@ export function AnnouncementDialog({ audience }: { audience: AnnouncementAudienc
type="button"
variant="ghost"
size="icon"
className={usesCoverMedia ? "" : undefined}
className={
usesCoverMedia
? "text-white hover:text-white hover:bg-white/15"
: undefined
}
onClick={() =>
setCurrentIndex(
(index) =>
@@ -297,7 +301,8 @@ export function AnnouncementDialog({ audience }: { audience: AnnouncementAudienc
<Button
type="button"
key={announcement.id}
className={`h-1.5 ${
variant="ghost"
className={`h-1.5 min-w-0 p-0 rounded-full ${
index === currentIndex
? `w-6 ${usesCoverMedia ? "bg-white" : "bg-primary"}`
: `w-1.5 ${usesCoverMedia ? "bg-white/40" : "bg-foreground/25"}`
@@ -313,7 +318,11 @@ export function AnnouncementDialog({ audience }: { audience: AnnouncementAudienc
type="button"
variant="ghost"
size="icon"
className={usesCoverMedia ? "" : undefined}
className={
usesCoverMedia
? "text-white hover:text-white hover:bg-white/15"
: undefined
}
onClick={() =>
setCurrentIndex(
(index) => (index + 1) % announcements.length,
@@ -332,7 +341,11 @@ export function AnnouncementDialog({ audience }: { audience: AnnouncementAudienc
<Button
type="button"
variant="ghost"
className={usesCoverMedia ? "" : undefined}
className={
usesCoverMedia
? "text-white hover:text-white hover:bg-white/15"
: undefined
}
onClick={dismissCurrent}
>
{t("announcements.dismiss", "Dismiss")}
@@ -118,7 +118,7 @@ export function EditorAnnouncementBanner() {
variant="link"
size="sm"
onClick={() => void openAction()}
className="h-auto shrink-0 gap-1 px-1 py-0 text-xs underline decoration-white/50 underline-offset-2 dark:decoration-black/50"
className="text-current h-auto shrink-0 gap-1 px-1 py-0 text-xs underline decoration-white/50 underline-offset-2 dark:decoration-black/50"
>
{current.action?.label}
{current.action?.url ? (
@@ -133,7 +133,7 @@ export function EditorAnnouncementBanner() {
variant="ghost"
type="button"
onClick={dismissCurrent}
className="absolute right-4 inline-flex h-6 w-6 items-center justify-center"
className="text-current absolute right-4 inline-flex h-6 w-6 items-center justify-center"
aria-label={t("announcements.dismiss", "Dismiss")}
>
<X className="h-3.5 w-3.5" />
+1 -1
View File
@@ -372,7 +372,7 @@ function LaunchWindowContent() {
onOpenProject={openProjectFromLibrary}
trigger={
<Button
aria-label={t("recording.openProject")}
aria-hidden="true"
tabIndex={-1}
variant="ghost"
className="absolute size-px min-w-0 p-0 pointer-events-none opacity-0"
+1
View File
@@ -62,6 +62,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button
"[&_svg]:size-5": iconSize === "lg",
"[&_svg]:size-6": iconSize === "xl",
},
variant === "link" && "h-auto p-0 underline underline-offset-4",
className,
),
};
+1 -1
View File
@@ -20,7 +20,7 @@ export function ChoiceGroup({
}) {
return (
<TagGroup
size="md"
size={props.size ?? "md"}
aria-label={props["aria-label"]}
selectionMode="single"
disallowEmptySelection
+9 -2
View File
@@ -31,10 +31,13 @@ export function DropdownMenuContent({
}
export function DropdownMenuItem({
onSelect,
onClick,
onAction,
disabled,
children,
...props
}: Omit<ComponentProps<typeof Dropdown.Item>, "onSelect"> & {
}: Omit<ComponentProps<typeof Dropdown.Item>, "onSelect" | "onClick"> & {
onClick?: () => void;
onSelect?: (event: Event) => void;
disabled?: boolean;
}) {
@@ -46,7 +49,11 @@ export function DropdownMenuItem({
props.textValue ??
(typeof children === "string" ? children : String(props.id ?? "Action"))
}
onAction={() => onSelect?.(new Event("select"))}
onAction={() => {
onSelect?.(new Event("select"));
onClick?.();
onAction?.();
}}
>
{children}
</Dropdown.Item>
+10 -1
View File
@@ -1,4 +1,5 @@
import { ToggleButton } from "@heroui/react";
import { cn } from "@/lib/utils";
import type { ComponentProps } from "react";
type Props = Omit<ComponentProps<typeof ToggleButton>, "size" | "variant"> & {
pressed?: boolean;
@@ -15,7 +16,15 @@ export function Toggle({ pressed, onPressedChange, disabled, size, variant, ...p
onChange={onPressedChange}
isDisabled={disabled}
size={size === "default" ? "md" : size}
variant={variant === "outline" ? "default" : "ghost"}
variant="ghost"
className={(state) =>
cn(
variant === "outline" && "border border-border bg-transparent",
typeof props.className === "function"
? props.className(state)
: props.className,
)
}
/>
);
}
@@ -115,7 +115,9 @@ export function EditorHeader(props: Props) {
onClick={props.onToggleVideos}
>
<FilmStrip className="h-4 w-4" />
<span className="text-sm font-semibold tracking-tight">Videos</span>
<span className="text-sm font-semibold tracking-tight">
{t("editor.library.videos", "Videos")}
</span>
</Button>
<Button
ref={projectBrowserTriggerRef}
+1
View File
@@ -106,6 +106,7 @@ const modes = [
"presets-empty",
"presets-saved",
"announcement-popup",
"announcement-cover",
"announcement-banner",
"announcement-notification",
];
+48 -26
View File
@@ -111,8 +111,8 @@ function TimelineSample({
videoPath={media}
videoSourcePath={media}
disableSuggestedZooms
clipRegions={clips}
zoomRegions={zooms}
clipRegions={selection === "empty" ? [] : clips}
zoomRegions={selection === "empty" ? [] : zooms}
onZoomAdded={noop}
onZoomSpanChange={noop}
onZoomDelete={noop}
@@ -123,40 +123,62 @@ function TimelineSample({
onClipDelete={noop}
selectedClipId={selection === "clip" ? "clip-a" : null}
onSelectClip={noop}
annotationRegions={[
annotation,
{
...annotation,
id: "annotation-b",
startMs: 3500,
endMs: 5100,
content: "A second callout",
trackIndex: 1,
},
]}
annotationRegions={
selection === "empty"
? []
: [
annotation,
{
...annotation,
id: "annotation-b",
startMs: 3500,
endMs: 5100,
content: "A second callout",
trackIndex: 1,
},
]
}
onAnnotationAdded={noop}
onAnnotationSpanChange={noop}
onAnnotationDelete={noop}
onSelectAnnotation={noop}
selectedAnnotationId={selection === "annotation" ? "annotation-a" : null}
audioRegions={[
{
id: "audio-a",
startMs: 0,
endMs: 6000,
audioPath: `${location.origin}/tests/ui/fixtures/preview.mp4`,
volume: 0.8,
},
]}
audioRegions={
selection === "empty"
? []
: [
{
id: "audio-a",
startMs: 0,
endMs: 6000,
audioPath: `${location.origin}/tests/ui/fixtures/preview.mp4`,
volume: 0.8,
},
]
}
onAudioAdded={noop}
onAudioSpanChange={noop}
onAudioDelete={noop}
onSelectAudio={noop}
selectedAudioId={selection === "audio" ? "audio-a" : null}
captionRegions={[
{ id: "caption-a", startMs: 100, endMs: 2000, text: "Welcome to Recordly" },
{ id: "caption-b", startMs: 2900, endMs: 5200, text: "Create something clear." },
]}
captionRegions={
selection === "empty"
? []
: [
{
id: "caption-a",
startMs: 100,
endMs: 2000,
text: "Welcome to Recordly",
},
{
id: "caption-b",
startMs: 2900,
endMs: 5200,
text: "Create something clear.",
},
]
}
captionsEnabled
captionQuickAddEnabled
onCaptionAdded={noop}
+3
View File
@@ -1,4 +1,7 @@
{
"library": {
"videos": "Videos"
},
"playback": {
"play": "Wiedergabe",
"pause": "Pause",
+3
View File
@@ -1,4 +1,7 @@
{
"library": {
"videos": "Videos"
},
"playback": {
"play": "Play",
"pause": "Pause",
+3
View File
@@ -1,4 +1,7 @@
{
"library": {
"videos": "Vídeos"
},
"playback": {
"play": "Reproducir",
"pause": "Pausar",
+3
View File
@@ -1,4 +1,7 @@
{
"library": {
"videos": "Vidéos"
},
"playback": {
"play": "Lecture",
"pause": "Pause",
+3
View File
@@ -1,4 +1,7 @@
{
"library": {
"videos": "Video"
},
"playback": {
"play": "Riproduci",
"pause": "Pausa",
+3
View File
@@ -1,4 +1,7 @@
{
"library": {
"videos": "동영상"
},
"playback": {
"play": "재생",
"pause": "일시 정지",
+3
View File
@@ -1,4 +1,7 @@
{
"library": {
"videos": "Video’s"
},
"playback": {
"play": "Afspelen",
"pause": "Pauzeren",
+3
View File
@@ -1,4 +1,7 @@
{
"library": {
"videos": "Vídeos"
},
"playback": {
"play": "Reproduzir",
"pause": "Pausar",
+3
View File
@@ -1,4 +1,7 @@
{
"library": {
"videos": "Видео"
},
"playback": {
"play": "Воспроизвести",
"pause": "Пауза",
+3
View File
@@ -1,4 +1,7 @@
{
"library": {
"videos": "视频"
},
"playback": {
"play": "播放",
"pause": "暂停",
+3
View File
@@ -1,4 +1,7 @@
{
"library": {
"videos": "影片"
},
"playback": {
"play": "播放",
"pause": "暫停",
+6 -4
View File
@@ -127,13 +127,15 @@
}
}
/* highlight rings look ugly — keep them transparent; keyboard focus gets an inset underline. */
/* Visible keyboard focus for HeroUI controls and native focusable elements. */
:root,
.dark {
--focus: transparent;
--focus: var(--foreground);
}
[data-focus-visible="true"] {
box-shadow: inset 0 -2px 0 color-mix(in oklab, var(--foreground) 45%, transparent);
[data-focus-visible="true"],
:focus-visible {
outline: 2px solid var(--focus);
outline-offset: 2px;
}
@container (max-width: 110px) {