Skip to content

Commit 03edba2

Browse files
author
Johannes Weber
committed
chore: Add UAP Action support to resize and drag handle
1 parent 69b272a commit 03edba2

File tree

17 files changed

+329
-199
lines changed

17 files changed

+329
-199
lines changed

pages/shared/i18n.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ export const boardItemI18nStrings: BoardItemProps.I18nStrings = {
6161
resizeHandleAriaLabel: "Resize handle",
6262
resizeHandleAriaDescription:
6363
"Use Space or Enter to activate resize, arrow keys to move, Space or Enter to submit, or Escape to discard. Be sure to temporarily disable any screen reader navigation feature that may interfere with the functionality of the arrow keys.",
64+
dragHandleTooltipText: "Drag or select to move",
65+
resizeHandleTooltipText: "Drag or select to resize",
6466
};
6567

6668
export const itemsPaletteI18nStrings: ItemsPaletteProps.I18nStrings<ItemData> = {

src/__tests__/__snapshots__/documenter.test.ts.snap

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,10 @@ ARIA labels:
201201
* \`dragHandleAriaLabel\` (string) - the ARIA label for the drag handle.
202202
* \`dragHandleAriaDescription\` (string, optional) - the ARIA description for the drag handle.
203203
* \`resizeHandleAriaLabel\` (string) - the ARIA label for the resize handle.
204-
* \`resizeHandleAriaDescription\` (string, optional) - the ARIA description for the resize handle.",
204+
* \`resizeHandleAriaDescription\` (string, optional) - the ARIA description for the resize handle.
205+
* \`dragHandleTooltipText\` (string, optional) - the ARIA description for the resize handle.
206+
* \`dragHandleTooltipText\` (string, optional) - the Text for the drag handle Tooltip.
207+
* \`resizeHandleTooltipText\` (string, optional) - the Text for the resize handle Tooltip.",
205208
"inlineType": {
206209
"name": "BoardItemProps.I18nStrings",
207210
"properties": [
@@ -215,6 +218,11 @@ ARIA labels:
215218
"optional": false,
216219
"type": "string",
217220
},
221+
{
222+
"name": "dragHandleTooltipText",
223+
"optional": true,
224+
"type": "string",
225+
},
218226
{
219227
"name": "resizeHandleAriaDescription",
220228
"optional": true,
@@ -225,6 +233,11 @@ ARIA labels:
225233
"optional": false,
226234
"type": "string",
227235
},
236+
{
237+
"name": "resizeHandleTooltipText",
238+
"optional": true,
239+
"type": "string",
240+
},
228241
],
229242
"type": "object",
230243
},

src/board-item/__tests__/board-item-wrapper.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,21 @@ export function ItemContextWrapper({ children }: { children: ReactNode }) {
99
<ItemContext.Provider
1010
value={{
1111
isActive: false,
12+
isHidden: false,
1213
dragHandle: {
1314
ref: { current: null },
1415
onPointerDown: () => {},
1516
onKeyDown: () => {},
16-
isActive: false,
17+
isActivePointer: false,
18+
isActiveUap: false,
19+
onDirectionClick: () => {},
1720
},
1821
resizeHandle: {
1922
onPointerDown: () => {},
2023
onKeyDown: () => {},
21-
isActive: false,
24+
isActivePointer: false,
25+
isActiveUap: false,
26+
onDirectionClick: () => {},
2227
},
2328
}}
2429
>

src/board-item/interfaces.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ export interface BoardItemProps {
3737
* * `dragHandleAriaDescription` (string, optional) - the ARIA description for the drag handle.
3838
* * `resizeHandleAriaLabel` (string) - the ARIA label for the resize handle.
3939
* * `resizeHandleAriaDescription` (string, optional) - the ARIA description for the resize handle.
40+
* * `dragHandleTooltipText` (string, optional) - the ARIA description for the resize handle.
41+
* * `dragHandleTooltipText` (string, optional) - the Text for the drag handle Tooltip.
42+
* * `resizeHandleTooltipText` (string, optional) - the Text for the resize handle Tooltip.
4043
*/
4144
i18nStrings: BoardItemProps.I18nStrings;
4245
}
@@ -47,5 +50,7 @@ export namespace BoardItemProps {
4750
dragHandleAriaDescription?: string;
4851
resizeHandleAriaLabel: string;
4952
resizeHandleAriaDescription?: string;
53+
dragHandleTooltipText?: string;
54+
resizeHandleTooltipText?: string;
5055
}
5156
}

src/board-item/internal.tsx

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useId } from "react";
44
import clsx from "clsx";
55

66
import Container from "@cloudscape-design/components/container";
7+
import { InternalDragHandleProps } from "@cloudscape-design/components/internal/do-not-use/drag-handle";
78

89
import { getDataAttributes } from "../internal/base-component/get-data-attributes";
910
import { InternalBaseComponentProps } from "../internal/base-component/use-base-component";
@@ -16,6 +17,16 @@ import type { BoardItemProps } from "./interfaces";
1617

1718
import styles from "./styles.css.js";
1819

20+
const mapHandleDirectionToKeyboardDirection = (direction: InternalDragHandleProps.Direction) => {
21+
const directionMap = {
22+
"inline-start": "left",
23+
"inline-end": "right",
24+
"block-start": "up",
25+
"block-end": "down",
26+
};
27+
return directionMap[direction] as any;
28+
};
29+
1930
export function InternalBoardItem({
2031
children,
2132
header,
@@ -26,7 +37,7 @@ export function InternalBoardItem({
2637
__internalRootRef,
2738
...rest
2839
}: BoardItemProps & InternalBaseComponentProps) {
29-
const { dragHandle, resizeHandle, isActive } = useItemContext();
40+
const { dragHandle, resizeHandle, isActive, isHidden } = useItemContext();
3041

3142
const dragHandleAriaLabelledBy = useId();
3243
const dragHandleAriaDescribedBy = useId();
@@ -42,14 +53,24 @@ export function InternalBoardItem({
4253
header={
4354
<WidgetContainerHeader
4455
handle={
45-
<DragHandle
46-
ref={dragHandle.ref}
47-
ariaLabelledBy={dragHandleAriaLabelledBy}
48-
ariaDescribedBy={dragHandleAriaDescribedBy}
49-
onPointerDown={dragHandle.onPointerDown}
50-
onKeyDown={dragHandle.onKeyDown}
51-
isActive={dragHandle.isActive}
52-
/>
56+
<>
57+
{!isHidden && (
58+
<DragHandle
59+
ref={dragHandle.ref}
60+
ariaLabelledBy={dragHandleAriaLabelledBy}
61+
ariaDescribedBy={dragHandleAriaDescribedBy}
62+
onPointerDown={dragHandle.onPointerDown}
63+
onKeyDown={dragHandle.onKeyDown}
64+
isActivePointer={dragHandle.isActivePointer}
65+
isActiveUap={dragHandle.isActiveUap}
66+
initialShowButtons={dragHandle.initialShowButtons}
67+
onDirectionClick={(direction) =>
68+
dragHandle.onDirectionClick(mapHandleDirectionToKeyboardDirection(direction), "drag")
69+
}
70+
dragHandleTooltipText={i18nStrings.dragHandleTooltipText}
71+
/>
72+
)}
73+
</>
5374
}
5475
settings={settings}
5576
>
@@ -62,14 +83,19 @@ export function InternalBoardItem({
6283
>
6384
{children}
6485
</Container>
65-
{resizeHandle && (
86+
{resizeHandle && !isHidden && (
6687
<div className={styles.resizer}>
6788
<ResizeHandle
6889
ariaLabelledBy={resizeHandleAriaLabelledBy}
6990
ariaDescribedBy={resizeHandleAriaDescribedBy}
7091
onPointerDown={resizeHandle.onPointerDown}
7192
onKeyDown={resizeHandle.onKeyDown}
72-
isActive={resizeHandle.isActive}
93+
isActivePointer={resizeHandle.isActivePointer}
94+
isActiveUap={resizeHandle.isActiveUap}
95+
onDirectionClick={(direction) => {
96+
resizeHandle.onDirectionClick(mapHandleDirectionToKeyboardDirection(direction), "resize");
97+
}}
98+
resizeHandleTooltipText={i18nStrings.resizeHandleTooltipText}
7399
/>
74100
</div>
75101
)}

src/internal/drag-handle/index.tsx

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,60 @@
33
import { ForwardedRef, forwardRef, KeyboardEvent, PointerEvent } from "react";
44
import clsx from "clsx";
55

6-
import Icon from "@cloudscape-design/components/icon";
7-
8-
import Handle from "../handle";
6+
import {
7+
InternalDragHandle,
8+
InternalDragHandleProps,
9+
} from "@cloudscape-design/components/internal/do-not-use/drag-handle";
910

1011
import styles from "./styles.css.js";
12+
import testUtilsStyles from "./test-classes/styles.css.js";
1113

1214
export interface DragHandleProps {
1315
ariaLabelledBy: string;
1416
ariaDescribedBy: string;
1517
onPointerDown: (event: PointerEvent) => void;
1618
onKeyDown: (event: KeyboardEvent) => void;
17-
isActive: boolean;
19+
isActivePointer: boolean;
20+
isActiveUap: boolean;
21+
initialShowButtons?: boolean;
22+
onDirectionClick: InternalDragHandleProps["onDirectionClick"];
23+
dragHandleTooltipText?: string;
1824
}
1925

2026
function DragHandle(
21-
{ ariaLabelledBy, ariaDescribedBy, onPointerDown, onKeyDown, isActive }: DragHandleProps,
22-
ref: ForwardedRef<HTMLButtonElement>,
27+
{
28+
ariaLabelledBy,
29+
ariaDescribedBy,
30+
onPointerDown,
31+
onKeyDown,
32+
isActivePointer,
33+
isActiveUap,
34+
initialShowButtons,
35+
onDirectionClick,
36+
dragHandleTooltipText,
37+
}: DragHandleProps,
38+
ref: ForwardedRef<HTMLDivElement>,
2339
) {
2440
return (
25-
<Handle
41+
<InternalDragHandle
2642
ref={ref}
27-
className={clsx(styles.handle, isActive && styles.active)}
28-
aria-labelledby={ariaLabelledBy}
29-
aria-describedby={ariaDescribedBy}
30-
onPointerDown={onPointerDown}
43+
className={clsx(styles.handle, isActivePointer && styles.active, isActiveUap && testUtilsStyles["active-uap"])}
44+
ariaLabelledBy={ariaLabelledBy}
45+
ariaDescribedby={ariaDescribedBy}
46+
variant="drag-indicator"
47+
tooltipText={dragHandleTooltipText}
3148
onKeyDown={onKeyDown}
32-
>
33-
<Icon name="drag-indicator" />
34-
</Handle>
49+
onPointerDown={onPointerDown}
50+
directions={{
51+
"block-start": "active",
52+
"block-end": "active",
53+
"inline-start": "active",
54+
"inline-end": "active",
55+
}}
56+
triggerMode="keyboard-activate"
57+
onDirectionClick={onDirectionClick}
58+
initialShowButtons={initialShowButtons}
59+
/>
3560
);
3661
}
3762

src/internal/drag-handle/styles.scss

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@
77

88
.handle {
99
cursor: grab;
10+
@include shared.handle();
1011
}
1112

1213
.handle:active {
1314
cursor: grabbing;
1415
}
1516

16-
.handle:not(.active):focus-visible {
17-
@include shared.focus-highlight();
18-
}
19-
2017
.active {
2118
outline: none;
2219
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
.active-uap {
7+
/* used in test-utils */
8+
}

src/internal/global-drag-state-styles/index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,25 @@ function assertNever(value: never) {
99
}
1010

1111
function setup({ operation, interactionType }: DragAndDropData) {
12+
const isPointerInteraction = interactionType === "pointer";
1213
switch (operation) {
1314
case "insert":
1415
case "reorder":
15-
document.body.classList.add(styles["show-grab-cursor"]);
16+
if (isPointerInteraction) {
17+
document.body.classList.add(styles["show-grab-cursor"]);
18+
}
1619
break;
1720
case "resize":
18-
document.body.classList.add(styles["show-resize-cursor"]);
21+
if (isPointerInteraction) {
22+
document.body.classList.add(styles["show-resize-cursor"]);
23+
}
1924
break;
2025
default:
2126
// there will be a type error if not all operation types are handled
2227
assertNever(operation);
2328
}
2429

25-
if (interactionType === "pointer") {
30+
if (isPointerInteraction) {
2631
document.body.classList.add(styles["disable-selection"]);
2732
}
2833
}

src/internal/handle/index.tsx

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)