mirror of
https://github.com/Athou/commafeed.git
synced 2026-03-21 21:37:29 +00:00
add aria-label to action buttons (#1507)
This commit is contained in:
@@ -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>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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()}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -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} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user