Skip to content

Commit

Permalink
Merge pull request desktop#19649 from desktop/announce-panel-resize-e…
Browse files Browse the repository at this point in the history
…vents

Announce panel resize events to screen readers
  • Loading branch information
tidy-dev authored Dec 5, 2024
2 parents 465eb57 + 015a3f3 commit 53eafae
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 1 deletion.
1 change: 1 addition & 0 deletions app/src/ui/history/selected-commits.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ export class SelectedCommits extends React.Component<
maximumWidth={commitSummaryWidth.max}
onResize={this.onCommitSummaryResize}
onReset={this.onCommitSummaryReset}
description="Selected commit file list"
>
{this.renderFileList()}
</Resizable>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ export class PullRequestFilesChanged extends React.Component<
maximumWidth={fileListWidth.max}
onResize={this.onFileListResize}
onReset={this.onFileListSizeReset}
description="Pull request file list"
>
<FileList
files={files}
Expand Down
1 change: 1 addition & 0 deletions app/src/ui/repository.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ export class RepositoryView extends React.Component<
minimumWidth={this.props.sidebarWidth.min}
onReset={this.handleSidebarWidthReset}
onResize={this.handleSidebarResize}
description="Repository sidebar"
>
{this.renderTabs()}
{this.renderSidebarContents()}
Expand Down
46 changes: 45 additions & 1 deletion app/src/ui/resizable/resizable.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */
import * as React from 'react'
import { clamp } from '../../lib/clamp'
import { AriaLiveContainer } from '../accessibility/aria-live-container'

export const DefaultMaxWidth = 350
export const DefaultMinWidth = 200
Expand All @@ -14,17 +15,31 @@ export enum ResizeDirection {
Decrease = 'Decrease',
}

export interface IResizableState {
/** The message that is announced to screen reader users to inform them of
* resizable panel state */
readonly resizeMessage: string
}

/**
* Component abstracting a resizable panel.
*
* Note: this component is pure, consumers must subscribe to the
* onResize and onReset event and update the width prop accordingly.
*/
export class Resizable extends React.Component<IResizableProps> {
export class Resizable extends React.Component<
IResizableProps,
IResizableState
> {
private resizeContainer: HTMLDivElement | null = null
private startWidth: number | null = null
private startX: number | null = null

public constructor(props: IResizableProps) {
super(props)
this.state = { resizeMessage: '' }
}

/**
* Returns the current width as determined by props.
*
Expand Down Expand Up @@ -69,6 +84,9 @@ export class Resizable extends React.Component<IResizableProps> {
const deltaX = e.clientX - this.startX
const newWidth = this.startWidth + deltaX

this.updateResizeMessage(
deltaX > 0 ? ResizeDirection.Increase : ResizeDirection.Decrease
)
this.props.onResize(this.clampWidth(newWidth))
e.preventDefault()
}
Expand Down Expand Up @@ -120,6 +138,7 @@ export class Resizable extends React.Component<IResizableProps> {

const newWidth = this.clampWidth(changedWidth)

this.updateResizeMessage(resizeDirection)
this.props.onResize(this.clampWidth(newWidth))
}

Expand Down Expand Up @@ -150,6 +169,24 @@ export class Resizable extends React.Component<IResizableProps> {
this.resizeContainer = ref
}

private getResizePercentage() {
const minWidth = this.props.minimumWidth ?? 0
const maxWidth = this.props.maximumWidth ?? DefaultMaxWidth
return Math.round(
((this.getCurrentWidth() - minWidth) / (maxWidth - minWidth)) * 100
)
}

private updateResizeMessage(direction: ResizeDirection) {
const directionMessage =
direction === ResizeDirection.Increase ? 'increased' : 'decreased'
this.setState({
resizeMessage: `${
this.props.description
} width ${directionMessage}. Set to ${this.getResizePercentage()}%`,
})
}

public render() {
const style: React.CSSProperties = {
width: this.getCurrentWidth(),
Expand All @@ -170,6 +207,10 @@ export class Resizable extends React.Component<IResizableProps> {
onDoubleClick={this.props.onReset}
className="resize-handle"
/>
<AriaLiveContainer
message={this.state.resizeMessage}
trackedUserInput={this.state.resizeMessage}
/>
</div>
)
}
Expand All @@ -194,6 +235,9 @@ export interface IResizableProps {
/** The optional ID for the root element. */
readonly id?: string

/** Used to describe which resizable was updated to screen reader users */
readonly description: string

/**
* Handler called when the width of the component has changed
* through an explicit resize event (dragging the handle).
Expand Down
1 change: 1 addition & 0 deletions app/src/ui/stashing/stash-diff-viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export class StashDiffViewer extends React.PureComponent<IStashDiffViewerProps>
maximumWidth={fileListWidth.max}
onResize={this.onResize}
onReset={this.onReset}
description="Stash file list"
>
<FileList
files={files}
Expand Down
1 change: 1 addition & 0 deletions app/src/ui/toolbar/branch-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ export class BranchDropdown extends React.Component<IBranchDropdownProps> {
onResize={this.onResize}
maximumWidth={this.props.branchDropdownWidth.max}
minimumWidth={this.props.branchDropdownWidth.min}
description="Current branch dropdown button"
>
<ToolbarDropdown
className="branch-button"
Expand Down
1 change: 1 addition & 0 deletions app/src/ui/toolbar/push-pull-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ export class PushPullButton extends React.Component<
onResize={this.onResize}
maximumWidth={this.props.pushPullButtonWidth.max}
minimumWidth={this.props.pushPullButtonWidth.min}
description="Push pull button"
>
{this.renderButton()}
<span id="push-pull-button-state">
Expand Down
1 change: 1 addition & 0 deletions app/src/ui/toolbar/revert-progress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export class RevertProgress extends React.Component<IRevertProgressProps, {}> {
onResize={this.onResize}
maximumWidth={this.props.width.max}
minimumWidth={this.props.width.min}
description="Revert progress button"
>
<ToolbarButton
title="Reverting…"
Expand Down

0 comments on commit 53eafae

Please sign in to comment.