Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions packages/blockly/core/block_animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// Former goog.module ID: Blockly.blockAnimations

import type {BlockSvg} from './block_svg.js';
import * as accessibility from './utils/accessibility.js';
import * as dom from './utils/dom.js';
import {Svg} from './utils/svg.js';

Expand All @@ -31,13 +32,18 @@ let wobblingBlock: BlockSvg | null = null;
* @internal
*/
export function disposeUiEffect(block: BlockSvg) {
// Disposing is going to take so long the animation won't play anyway.
if (block.getDescendants(false).length > 100) return;

const workspace = block.workspace;
const svgGroup = block.getSvgRoot();
workspace.getAudioManager().play('delete');

// Disposing is going to take so long the animation won't play anyway.
if (
block.getDescendants(false).length > 100 ||
accessibility.shouldReduceMotion()
) {
return;
}

const xy = block.getRelativeToSurfaceXY();
// Deeply clone the current block.
const clone: SVGGElement = svgGroup.cloneNode(true) as SVGGElement;
Expand Down Expand Up @@ -97,7 +103,7 @@ export function connectionUiEffect(block: BlockSvg) {
const workspace = block.workspace;
const scale = workspace.scale;
workspace.getAudioManager().play('click');
if (scale < 1) {
if (scale < 1 || accessibility.shouldReduceMotion()) {
return; // Too small to care about visual effects.
}
// Determine the absolute coordinates of the inferior block.
Expand Down Expand Up @@ -163,7 +169,7 @@ export function connectionUiEffect(block: BlockSvg) {
export function disconnectUiEffect(block: BlockSvg) {
disconnectUiStop();
block.workspace.getAudioManager().play('disconnect');
if (block.workspace.scale < 1) {
if (block.workspace.scale < 1 || accessibility.shouldReduceMotion()) {
return; // Too small to care about visual effects.
}
// Horizontal distance for bottom of block to wiggle.
Expand Down
8 changes: 8 additions & 0 deletions packages/blockly/core/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -715,4 +715,12 @@ input[type=number] {
flex-direction: ${userAgent.MOBILE || userAgent.APPLE ? 'row-reverse' : 'row'};
column-gap: 8px;
}

@media (prefers-reduced-motion: reduce) {
.blocklyBlockCanvas.blocklyCanvasTransitioning,
.blocklyBubbleCanvas.blocklyCanvasTransitioning,
.blocklyDropDownDiv {
transition: none !important;
}
}
`;
6 changes: 6 additions & 0 deletions packages/blockly/core/toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,10 @@ Css.register(`
border: none;
cursor: pointer;
}

@media (prefers-reduced-motion: reduce) {
.${CLASS_NAME} {
transition: none;
}
}
`);
7 changes: 7 additions & 0 deletions packages/blockly/core/trashcan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -741,4 +741,11 @@ Css.register(`
.blocklyRTL .blocklyTrash.blocklyTrashFull:focus .blocklyTrashLid {
rotate: -45deg;
}

@media (prefers-reduced-motion: reduce) {
.blocklyTrash > image,
.blocklyTrashLid {
transition: none;
}
}
`);
2 changes: 2 additions & 0 deletions packages/blockly/core/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import * as browserEvents from './browser_events.js';
import * as extensions from './extensions.js';
import * as accessibility from './utils/accessibility.js';
import * as aria from './utils/aria.js';
import * as arrayUtils from './utils/array.js';
import * as colour from './utils/colour.js';
Expand All @@ -32,6 +33,7 @@ import * as userAgent from './utils/useragent.js';
import * as xml from './utils/xml.js';

export {
accessibility,
aria,
arrayUtils as array,
browserEvents,
Expand Down
23 changes: 23 additions & 0 deletions packages/blockly/core/utils/accessibility.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @license
* Copyright 2026 Raspberry Pi Foundation
* SPDX-License-Identifier: Apache-2.0
*/

let reduceMotion: MediaQueryList | undefined = undefined;

/**
* Returns true if motion and animations should be minimized.
*/
export function shouldReduceMotion(): boolean {
if (reduceMotion === undefined) {
if (typeof window === 'undefined' || !('matchMedia' in window)) {
// No point in animating if there's no window, i.e. we're running under
// Node.
return true;
}

reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
}
return reduceMotion.matches;
}
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,10 @@ export class ContinuousFlyout extends Blockly.VerticalFlyout {
if (this.scrollTarget === undefined) return;
const currentScrollPos = -this.getWorkspace().scrollY;
const diff = this.scrollTarget - currentScrollPos;
if (Math.abs(diff) < 1) {
if (
Math.abs(diff) < 1 ||
Blockly.utils.accessibility.shouldReduceMotion()
) {
this.getWorkspace().scrollbar?.setY(this.scrollTarget);
this.scrollTarget = undefined;
return;
Expand Down
Loading