add aria-label to action buttons (#1507)

This commit is contained in:
Athou
2024-08-03 11:30:29 +02:00
parent 3a57b68fa3
commit a071b7c265
6 changed files with 51 additions and 31 deletions

View File

@@ -1,3 +1,5 @@
import type { MessageDescriptor } from "@lingui/core"
import { useLingui } from "@lingui/react"
import { ActionIcon, Button, type ButtonVariant, Tooltip, useMantineTheme } from "@mantine/core"
import type { ActionIconVariant } from "@mantine/core/lib/components/ActionIcon/ActionIcon"
import { Constants } from "app/constants"
@@ -7,7 +9,7 @@ import { type MouseEventHandler, type ReactNode, forwardRef } from "react"
interface ActionButtonProps {
className?: string
icon?: ReactNode
label: ReactNode
label?: string | MessageDescriptor
onClick?: MouseEventHandler
variant?: ActionIconVariant & ButtonVariant
hideLabelOnDesktop?: boolean
@@ -20,17 +22,35 @@ interface ActionButtonProps {
export const ActionButton = forwardRef<HTMLButtonElement, ActionButtonProps>((props: ActionButtonProps, ref) => {
const { mobile } = useActionButton()
const theme = useMantineTheme()
const { _ } = useLingui()
const label = typeof props.label === "string" ? props.label : props.label && _(props.label)
const variant = props.variant ?? "subtle"
const iconOnly = (mobile && !props.showLabelOnMobile) || (!mobile && props.hideLabelOnDesktop)
return iconOnly ? (
<Tooltip label={props.label} openDelay={Constants.tooltip.delay}>
<ActionIcon ref={ref} color={theme.primaryColor} variant={variant} className={props.className} onClick={props.onClick}>
<Tooltip label={label} openDelay={Constants.tooltip.delay}>
<ActionIcon
ref={ref}
color={theme.primaryColor}
variant={variant}
className={props.className}
onClick={props.onClick}
aria-label={label}
>
{props.icon}
</ActionIcon>
</Tooltip>
) : (
<Button ref={ref} variant={variant} size="xs" className={props.className} leftSection={props.icon} onClick={props.onClick}>
{props.label}
<Button
ref={ref}
variant={variant}
size="xs"
className={props.className}
leftSection={props.icon}
onClick={props.onClick}
aria-label={label}
>
{label}
</Button>
)
})

View File

@@ -1,4 +1,4 @@
import { Trans, t } from "@lingui/macro"
import { msg, t } from "@lingui/macro"
import { Group, Indicator, Popover, TagsInput } from "@mantine/core"
import { markEntriesUpToEntry, markEntry, starEntry, tagEntry } from "app/entries/thunks"
import { useAppDispatch, useAppSelector } from "app/store"
@@ -40,13 +40,13 @@ export function FeedEntryFooter(props: FeedEntryFooterProps) {
{props.entry.markable && (
<ActionButton
icon={props.entry.read ? <TbMail size={18} /> : <TbMailOpened size={18} />}
label={props.entry.read ? <Trans>Keep unread</Trans> : <Trans>Mark as read</Trans>}
label={props.entry.read ? msg`Keep unread` : msg`Mark as read`}
onClick={readStatusButtonClicked}
/>
)}
<ActionButton
icon={props.entry.starred ? <TbStarOff size={18} /> : <TbStar size={18} />}
label={props.entry.starred ? <Trans>Unstar</Trans> : <Trans>Star</Trans>}
label={props.entry.starred ? msg`Unstar` : msg`Star`}
onClick={async () =>
await dispatch(
starEntry({
@@ -59,7 +59,7 @@ export function FeedEntryFooter(props: FeedEntryFooterProps) {
<Popover withArrow withinPortal shadow="md" closeOnClickOutside={!mobile}>
<Popover.Target>
<ActionButton icon={<TbShare size={18} />} label={<Trans>Share</Trans>} />
<ActionButton icon={<TbShare size={18} />} label={msg`Share`} />
</Popover.Target>
<Popover.Dropdown>
<ShareButtons url={props.entry.url} description={props.entry.title} />
@@ -70,7 +70,7 @@ export function FeedEntryFooter(props: FeedEntryFooterProps) {
<Popover withArrow shadow="md" closeOnClickOutside={!mobile}>
<Popover.Target>
<Indicator label={props.entry.tags.length} disabled={props.entry.tags.length === 0} inline size={16}>
<ActionButton icon={<TbTag size={18} />} label={<Trans>Tags</Trans>} />
<ActionButton icon={<TbTag size={18} />} label={msg`Tags`} />
</Indicator>
</Popover.Target>
<Popover.Dropdown>
@@ -88,13 +88,13 @@ export function FeedEntryFooter(props: FeedEntryFooterProps) {
)}
<a href={props.entry.url} target="_blank" rel="noreferrer">
<ActionButton icon={<TbExternalLink size={18} />} label={<Trans>Open link</Trans>} />
<ActionButton icon={<TbExternalLink size={18} />} label={msg`Open link`} />
</a>
</Group>
<ActionButton
icon={<TbArrowBarToDown size={18} />}
label={<Trans>Mark as read up to here</Trans>}
label={msg`Mark as read up to here`}
onClick={async () => await dispatch(markEntriesUpToEntry(props.entry))}
/>
</Group>

View File

@@ -1,4 +1,4 @@
import { Trans, t } from "@lingui/macro"
import { msg, t } from "@lingui/macro"
import { Box, Center, CloseButton, Divider, Group, Indicator, Popover, TextInput } from "@mantine/core"
import { useForm } from "@mantine/form"
import { reloadEntries, search, selectNextEntry, selectPreviousEntry } from "app/entries/thunks"
@@ -77,7 +77,7 @@ export function Header() {
<HeaderToolbar>
<ActionButton
icon={<TbArrowUp size={iconSize} />}
label={<Trans>Previous</Trans>}
label={msg`Previous`}
onClick={async () =>
await dispatch(
selectPreviousEntry({
@@ -90,7 +90,7 @@ export function Header() {
/>
<ActionButton
icon={<TbArrowDown size={iconSize} />}
label={<Trans>Next</Trans>}
label={msg`Next`}
onClick={async () =>
await dispatch(
selectNextEntry({
@@ -106,7 +106,7 @@ export function Header() {
<ActionButton
icon={<TbRefresh size={iconSize} />}
label={<Trans>Refresh</Trans>}
label={msg`Refresh`}
onClick={async () => await dispatch(reloadEntries())}
/>
<MarkAllAsReadButton iconSize={iconSize} />
@@ -115,19 +115,19 @@ export function Header() {
<ActionButton
icon={settings.readingMode === "all" ? <TbEye size={iconSize} /> : <TbEyeOff size={iconSize} />}
label={settings.readingMode === "all" ? <Trans>All</Trans> : <Trans>Unread</Trans>}
label={settings.readingMode === "all" ? msg`All` : msg`Unread`}
onClick={async () => await dispatch(changeReadingMode(settings.readingMode === "all" ? "unread" : "all"))}
/>
<ActionButton
icon={settings.readingOrder === "asc" ? <TbSortAscending size={iconSize} /> : <TbSortDescending size={iconSize} />}
label={settings.readingOrder === "asc" ? <Trans>Asc</Trans> : <Trans>Desc</Trans>}
label={settings.readingOrder === "asc" ? msg`Asc` : msg`Desc`}
onClick={async () => await dispatch(changeReadingOrder(settings.readingOrder === "asc" ? "desc" : "asc"))}
/>
<Popover>
<Popover.Target>
<Indicator disabled={!searchFromStore}>
<ActionButton icon={<TbSearch size={iconSize} />} label={<Trans>Search</Trans>} />
<ActionButton icon={<TbSearch size={iconSize} />} label={msg`Search`} />
</Indicator>
</Popover.Target>
<Popover.Dropdown>
@@ -153,12 +153,12 @@ export function Header() {
<ActionButton
icon={<TbSettings size={iconSize} />}
label={<Trans>Extension options</Trans>}
label={msg`Extension options`}
onClick={() => openSettingsPage()}
/>
<ActionButton
icon={<TbExternalLink size={iconSize} />}
label={<Trans>Open CommaFeed</Trans>}
label={msg`Open CommaFeed`}
onClick={() => openAppInNewTab()}
/>
</>

View File

@@ -1,4 +1,4 @@
import { Trans } from "@lingui/macro"
import { Trans, msg } from "@lingui/macro"
import { Button, Code, Group, Modal, Slider, Stack, Text } from "@mantine/core"
import { markAllEntries } from "app/entries/thunks"
@@ -91,7 +91,7 @@ export function MarkAllAsReadButton(props: { iconSize: number }) {
</Group>
</Stack>
</Modal>
<ActionButton icon={<TbChecks size={props.iconSize} />} label={<Trans>Mark all as read</Trans>} onClick={buttonClicked} />
<ActionButton icon={<TbChecks size={props.iconSize} />} label={msg`Mark all as read`} onClick={buttonClicked} />
</>
)
}

View File

@@ -1,4 +1,4 @@
import { Trans } from "@lingui/macro"
import { msg } from "@lingui/macro"
import { Anchor, Box, Center, Container, Divider, Group, Image, Space, Title, useMantineColorScheme } from "@mantine/core"
import { client } from "app/client"
import { redirectToApiDocumentation, redirectToLogin, redirectToRegistration, redirectToRootCategory } from "app/redirect/thunks"
@@ -38,7 +38,7 @@ export function WelcomePage() {
{serverInfos?.demoAccountEnabled && (
<Center>
<ActionButton
label={<Trans>Try the demo!</Trans>}
label={msg`Try the demo!`}
icon={<TbClock size={iconSize} />}
variant="outline"
onClick={async () => await login.execute({ name: "demo", password: "demo" })}
@@ -96,7 +96,7 @@ function Buttons() {
return (
<Group gap={14}>
<ActionButton
label={<Trans>Log in</Trans>}
label={msg`Log in`}
icon={<TbKey size={iconSize} />}
variant="outline"
onClick={async () => await dispatch(redirectToLogin())}
@@ -104,7 +104,7 @@ function Buttons() {
/>
{serverInfos?.allowRegistrations && (
<ActionButton
label={<Trans>Sign up</Trans>}
label={msg`Sign up`}
icon={<TbUserPlus size={iconSize} />}
variant="filled"
onClick={async () => await dispatch(redirectToRegistration())}
@@ -113,7 +113,7 @@ function Buttons() {
)}
<ActionButton
label={dark ? <Trans>Switch to light theme</Trans> : <Trans>Switch to dark theme</Trans>}
label={dark ? msg`Switch to light theme` : msg`Switch to dark theme`}
icon={colorScheme === "dark" ? <TbSun size={18} /> : <TbMoon size={iconSize} />}
onClick={() => toggleColorScheme()}
hideLabelOnDesktop
@@ -121,7 +121,7 @@ function Buttons() {
{isBrowserExtensionPopup && (
<ActionButton
label={<Trans>Extension options</Trans>}
label={msg`Extension options`}
icon={<TbSettings size={iconSize} />}
onClick={() => openSettingsPage()}
hideLabelOnDesktop

View File

@@ -1,4 +1,4 @@
import { Trans } from "@lingui/macro"
import { msg } from "@lingui/macro"
import { ActionIcon, AppShell, Box, Center, Group, ScrollArea, Title, useMantineTheme } from "@mantine/core"
import { Constants } from "app/constants"
import { redirectToAdd, redirectToRootCategory } from "app/redirect/thunks"
@@ -101,7 +101,7 @@ export default function Layout(props: LayoutProps) {
const burger = (
<ActionButton
label={mobileMenuOpen ? <Trans>Close menu</Trans> : <Trans>Open menu</Trans>}
label={mobileMenuOpen ? msg`Close menu` : msg`Open menu`}
icon={mobileMenuOpen ? <TbX size={18} /> : <TbMenu2 size={18} />}
onClick={() => dispatch(setMobileMenuOpen(!mobileMenuOpen))}
/>