From ae12b4a356c1503a9f62d08a6befebeebaaaf866 Mon Sep 17 00:00:00 2001
From: Rebeka Dekany <50901361+rebekadekany@users.noreply.github.com>
Date: Thu, 24 Apr 2025 13:07:38 +0200
Subject: [PATCH] [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
---
.../features/ide-redesign/components/rail.tsx | 44 ++++++++-------
.../toolbar/change-layout-button.tsx | 53 +++++++++----------
.../toolbar/show-history-button.tsx | 14 +++--
.../ui/components/bootstrap-5/icon-button.tsx | 11 +++-
.../ui/components/types/icon-button-props.ts | 16 +++++-
.../bootstrap-5/pages/editor/rail.scss | 4 ++
.../pages/editor/toolbar-redesign.scss | 21 ++++++++
7 files changed, 105 insertions(+), 58 deletions(-)
diff --git a/services/web/frontend/js/features/ide-redesign/components/rail.tsx b/services/web/frontend/js/features/ide-redesign/components/rail.tsx
index 4459971c13..34cb7df3f4 100644
--- a/services/web/frontend/js/features/ide-redesign/components/rail.tsx
+++ b/services/web/frontend/js/features/ide-redesign/components/rail.tsx
@@ -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 ? (
-
+
) : (
)}
@@ -292,13 +297,6 @@ const RailTab = ({
}
const RailActionElement = ({ action }: { action: RailAction }) => {
- const icon = (
-
- )
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}
+
@@ -333,30 +336,31 @@ const RailActionElement = ({ action }: { action: RailAction }) => {
description={action.title}
overlayProps={{ delay: 0, placement: 'right' }}
>
-
+ icon={action.icon}
+ accessibilityLabel={action.title}
+ unfilled
+ />
)
}
}
export const RailPanelHeader: FC<{ title: string }> = ({ title }) => {
+ const { t } = useTranslation()
const { handlePaneCollapse } = useRailContext()
return (
)
}
diff --git a/services/web/frontend/js/features/ide-redesign/components/toolbar/change-layout-button.tsx b/services/web/frontend/js/features/ide-redesign/components/toolbar/change-layout-button.tsx
index db26928599..eb51dd51c8 100644
--- a/services/web/frontend/js/features/ide-redesign/components/toolbar/change-layout-button.tsx
+++ b/services/web/frontend/js/features/ide-redesign/components/toolbar/change-layout-button.tsx
@@ -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) => void
- }
->(({ onClick }, ref) => {
- return (
- }
- />
- )
-})
-
-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 (
-
+
+
+
+
+
+
+
diff --git a/services/web/frontend/js/features/ide-redesign/components/toolbar/show-history-button.tsx b/services/web/frontend/js/features/ide-redesign/components/toolbar/show-history-button.tsx
index 460fff20fc..97a37770e2 100644
--- a/services/web/frontend/js/features/ide-redesign/components/toolbar/show-history-button.tsx
+++ b/services/web/frontend/js/features/ide-redesign/components/toolbar/show-history-button.tsx
@@ -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' }}
>
- }
+
diff --git a/services/web/frontend/js/features/ui/components/bootstrap-5/icon-button.tsx b/services/web/frontend/js/features/ui/components/bootstrap-5/icon-button.tsx
index 29d6aa52ef..d738bd2cd5 100644
--- a/services/web/frontend/js/features/ui/components/bootstrap-5/icon-button.tsx
+++ b/services/web/frontend/js/features/ui/components/bootstrap-5/icon-button.tsx
@@ -6,7 +6,15 @@ import type { IconButtonProps } from '@/features/ui/components/types/icon-button
const IconButton = forwardRef(
(
- { 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(
const iconSizeClassName = size === 'lg' ? 'icon-large' : 'icon-small'
const materialIconClassName = classNames(iconSizeClassName, {
'button-content-hidden': isLoading,
+ unfilled,
})
return (
diff --git a/services/web/frontend/js/features/ui/components/types/icon-button-props.ts b/services/web/frontend/js/features/ui/components/types/icon-button-props.ts
index ec75bb6115..9cee07ebd9 100644
--- a/services/web/frontend/js/features/ui/components/types/icon-button-props.ts
+++ b/services/web/frontend/js/features/ui/components/types/icon-button-props.ts
@@ -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
diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/rail.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/rail.scss
index ffd0d78baa..96df113261 100644
--- a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/rail.scss
+++ b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/rail.scss
@@ -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);
diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/toolbar-redesign.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/toolbar-redesign.scss
index b207e99f15..10ffeb0f52 100644
--- a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/toolbar-redesign.scss
+++ b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/toolbar-redesign.scss
@@ -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 {