mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-27 11:01:56 +02:00
[web] Ensure buttons and links have discernible text on the editor page (#25005)
* Use OLIconButton for buttons lacking visible text * Ensure correct ARIA attr for the Layout dropdown * Add a tooltip to Layout button * Add "Open dev tool" aria-label * Add accessible names to the rail tab items * Remove unused IconProps export GitOrigin-RevId: 185937384cf5ec87b32238111d6621ac07789fb4
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { FC, ReactElement, useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Nav, NavLink, Tab, TabContainer } from 'react-bootstrap-5'
|
||||
import MaterialIcon, {
|
||||
AvailableUnfilledIcon,
|
||||
@@ -16,10 +17,8 @@ import { ChatIndicator, ChatPane } from './chat/chat'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { HorizontalResizeHandle } from '@/features/ide-react/components/resize/horizontal-resize-handle'
|
||||
import { HorizontalToggler } from '@/features/ide-react/components/resize/horizontal-toggler'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import classNames from 'classnames'
|
||||
import IntegrationsPanel from './integrations-panel/integrations-panel'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownDivider,
|
||||
@@ -32,6 +31,7 @@ import { RailHelpContactUsModal } from './help/contact-us'
|
||||
import { HistorySidebar } from '@/features/ide-react/components/history-sidebar'
|
||||
import DictionarySettingsModal from './settings/editor-settings/dictionary-settings-modal'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import OLIconButton from '@/features/ui/components/ol/ol-icon-button'
|
||||
|
||||
type RailElement = {
|
||||
icon: AvailableUnfilledIcon
|
||||
@@ -277,11 +277,16 @@ const RailTab = ({
|
||||
})}
|
||||
>
|
||||
{open ? (
|
||||
<MaterialIcon className="ide-rail-tab-link-icon" type={icon} />
|
||||
<MaterialIcon
|
||||
className="ide-rail-tab-link-icon"
|
||||
type={icon}
|
||||
accessibilityLabel={title}
|
||||
/>
|
||||
) : (
|
||||
<MaterialIcon
|
||||
className="ide-rail-tab-link-icon"
|
||||
type={icon}
|
||||
accessibilityLabel={title}
|
||||
unfilled
|
||||
/>
|
||||
)}
|
||||
@@ -292,13 +297,6 @@ const RailTab = ({
|
||||
}
|
||||
|
||||
const RailActionElement = ({ action }: { action: RailAction }) => {
|
||||
const icon = (
|
||||
<MaterialIcon
|
||||
className="ide-rail-tab-link-icon"
|
||||
type={action.icon}
|
||||
unfilled
|
||||
/>
|
||||
)
|
||||
const onActionClick = useCallback(() => {
|
||||
if ('action' in action) {
|
||||
action.action()
|
||||
@@ -318,8 +316,13 @@ const RailActionElement = ({ action }: { action: RailAction }) => {
|
||||
id="rail-help-dropdown-btn"
|
||||
className="ide-rail-tab-link ide-rail-tab-button ide-rail-tab-dropdown"
|
||||
as="button"
|
||||
aria-label={action.title}
|
||||
>
|
||||
{icon}
|
||||
<MaterialIcon
|
||||
className="ide-rail-tab-link-icon"
|
||||
type={action.icon}
|
||||
unfilled
|
||||
/>
|
||||
</DropdownToggle>
|
||||
</span>
|
||||
</OLTooltip>
|
||||
@@ -333,30 +336,31 @@ const RailActionElement = ({ action }: { action: RailAction }) => {
|
||||
description={action.title}
|
||||
overlayProps={{ delay: 0, placement: 'right' }}
|
||||
>
|
||||
<button
|
||||
<OLIconButton
|
||||
onClick={onActionClick}
|
||||
className="ide-rail-tab-link ide-rail-tab-button"
|
||||
type="button"
|
||||
>
|
||||
{icon}
|
||||
</button>
|
||||
icon={action.icon}
|
||||
accessibilityLabel={action.title}
|
||||
unfilled
|
||||
/>
|
||||
</OLTooltip>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export const RailPanelHeader: FC<{ title: string }> = ({ title }) => {
|
||||
const { t } = useTranslation()
|
||||
const { handlePaneCollapse } = useRailContext()
|
||||
return (
|
||||
<header className="rail-panel-header">
|
||||
<h4 className="rail-panel-title">{title}</h4>
|
||||
<OLButton
|
||||
<OLIconButton
|
||||
onClick={handlePaneCollapse}
|
||||
className="rail-panel-header-button-subdued"
|
||||
icon="close"
|
||||
accessibilityLabel={t('close')}
|
||||
size="sm"
|
||||
>
|
||||
<MaterialIcon type="close" />
|
||||
</OLButton>
|
||||
/>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,41 +1,40 @@
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import classNames from 'classnames'
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownMenu,
|
||||
DropdownToggle,
|
||||
} from '@/features/ui/components/bootstrap-5/dropdown-menu'
|
||||
import React, { forwardRef } from 'react'
|
||||
import ChangeLayoutOptions from './change-layout-options'
|
||||
|
||||
const LayoutDropdownToggleButton = forwardRef<
|
||||
HTMLButtonElement,
|
||||
{
|
||||
onClick: (e: React.MouseEvent<HTMLButtonElement>) => void
|
||||
}
|
||||
>(({ onClick }, ref) => {
|
||||
return (
|
||||
<OLButton
|
||||
size="sm"
|
||||
className="ide-redesign-toolbar-button-subdued"
|
||||
ref={ref}
|
||||
onClick={onClick}
|
||||
leadingIcon={<MaterialIcon unfilled type="space_dashboard" />}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
LayoutDropdownToggleButton.displayName = 'LayoutDropdownToggleButton'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
|
||||
export default function ChangeLayoutButton() {
|
||||
const { t } = useTranslation()
|
||||
const toggleButtonClassName = classNames(
|
||||
'ide-redesign-toolbar-button-subdued',
|
||||
'ide-redesign-toolbar-dropdown-toggle-subdued',
|
||||
'ide-redesign-toolbar-button-icon'
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="ide-redesign-toolbar-button-container">
|
||||
<Dropdown className="toolbar-item layout-dropdown" align="end">
|
||||
<DropdownToggle
|
||||
id="layout-dropdown-btn"
|
||||
className="btn-full-height"
|
||||
as={LayoutDropdownToggleButton}
|
||||
/>
|
||||
<OLTooltip
|
||||
id="tooltip-open-layout-options"
|
||||
description={t('layout_options')}
|
||||
overlayProps={{ delay: 0, placement: 'bottom' }}
|
||||
>
|
||||
<span>
|
||||
<DropdownToggle
|
||||
id="layout-dropdown-btn"
|
||||
className={toggleButtonClassName}
|
||||
aria-label={t('layout_options')}
|
||||
>
|
||||
<MaterialIcon type="space_dashboard" unfilled />
|
||||
</DropdownToggle>
|
||||
</span>
|
||||
</OLTooltip>
|
||||
<DropdownMenu>
|
||||
<ChangeLayoutOptions />
|
||||
</DropdownMenu>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import * as eventTracking from '../../../../infrastructure/event-tracking'
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import { useCallback } from 'react'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import OLIconButton from '@/features/ui/components/ol/ol-icon-button'
|
||||
|
||||
export default function ShowHistoryButton() {
|
||||
const { t } = useTranslation()
|
||||
@@ -24,12 +23,11 @@ export default function ShowHistoryButton() {
|
||||
description={t('history')}
|
||||
overlayProps={{ delay: 0, placement: 'bottom' }}
|
||||
>
|
||||
<OLButton
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
className="ide-redesign-toolbar-button-subdued"
|
||||
leadingIcon={<MaterialIcon type="history" />}
|
||||
<OLIconButton
|
||||
icon="history"
|
||||
className="ide-redesign-toolbar-button-subdued ide-redesign-toolbar-button-icon"
|
||||
onClick={toggleHistoryOpen}
|
||||
accessibilityLabel={t('history')}
|
||||
/>
|
||||
</OLTooltip>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,15 @@ import type { IconButtonProps } from '@/features/ui/components/types/icon-button
|
||||
|
||||
const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
|
||||
(
|
||||
{ accessibilityLabel, icon, isLoading = false, size, className, ...props },
|
||||
{
|
||||
accessibilityLabel,
|
||||
icon,
|
||||
isLoading = false,
|
||||
size,
|
||||
className,
|
||||
unfilled,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const iconButtonClassName = classNames(className, {
|
||||
@@ -17,6 +25,7 @@ const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
|
||||
const iconSizeClassName = size === 'lg' ? 'icon-large' : 'icon-small'
|
||||
const materialIconClassName = classNames(iconSizeClassName, {
|
||||
'button-content-hidden': isLoading,
|
||||
unfilled,
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
import { AvailableUnfilledIcon } from '@/shared/components/material-icon'
|
||||
import { ButtonProps } from './button-props'
|
||||
|
||||
export type IconButtonProps = ButtonProps & {
|
||||
type BaseIconButtonProps = ButtonProps & {
|
||||
accessibilityLabel?: string
|
||||
icon: string
|
||||
type?: 'button' | 'submit'
|
||||
}
|
||||
|
||||
type FilledIconButtonProps = BaseIconButtonProps & {
|
||||
icon: string
|
||||
unfilled?: false
|
||||
}
|
||||
|
||||
type UnfilledIconButtonProps = BaseIconButtonProps & {
|
||||
icon: AvailableUnfilledIcon
|
||||
unfilled: true
|
||||
}
|
||||
|
||||
export type IconButtonProps = FilledIconButtonProps | UnfilledIconButtonProps
|
||||
|
||||
@@ -72,6 +72,10 @@
|
||||
color: var(--ide-rail-color);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--ide-rail-link-hover-color);
|
||||
background-color: var(--ide-rail-link-hover-background);
|
||||
|
||||
@@ -59,6 +59,27 @@
|
||||
);
|
||||
|
||||
text-decoration: none;
|
||||
|
||||
&.ide-redesign-toolbar-button-icon {
|
||||
@include ol-button-variant(
|
||||
var(--redesign-subdued-button-color),
|
||||
var(--redesign-toolbar-background),
|
||||
transparent,
|
||||
var(--redesign-subdued-button-hover-background),
|
||||
transparent,
|
||||
true
|
||||
);
|
||||
|
||||
border-radius: var(--border-radius-full);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: var(--spacing-02);
|
||||
|
||||
&:visited,
|
||||
&:focus {
|
||||
color: var(--redesign-subdued-button-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ide-redesign-toolbar-home-link {
|
||||
|
||||
Reference in New Issue
Block a user