From b23327443e17eedcfeef8a297788c4f59746de1d Mon Sep 17 00:00:00 2001 From: Ben Henning Date: Thu, 3 Jul 2025 00:45:37 +0000 Subject: [PATCH] feat: Use pure CSS for selection highlights. This is still a WIP solution, but it's a possible approach. --- core/block_svg.ts | 4 ---- core/renderers/common/path_object.ts | 19 ++++++++++++++++++- core/renderers/zelos/constants.ts | 12 +++++++++--- core/renderers/zelos/path_object.ts | 4 ++-- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/core/block_svg.ts b/core/block_svg.ts index 49b4a1ee6f6..5ebe7b7bb85 100644 --- a/core/block_svg.ts +++ b/core/block_svg.ts @@ -55,7 +55,6 @@ import type {IPathObject} from './renderers/common/i_path_object.js'; import * as blocks from './serialization/blocks.js'; import type {BlockStyle} from './theme.js'; import * as Tooltip from './tooltip.js'; -import {idGenerator} from './utils.js'; import {Coordinate} from './utils/coordinate.js'; import * as dom from './utils/dom.js'; import {Rect} from './utils/rect.js'; @@ -212,9 +211,6 @@ export class BlockSvg // Expose this block's ID on its top-level SVG group. this.svgGroup.setAttribute('data-id', this.id); - // The page-wide unique ID of this Block used for focusing. - svgPath.id = idGenerator.getNextUniqueId(); - this.doInit_(); } diff --git a/core/renderers/common/path_object.ts b/core/renderers/common/path_object.ts index f6291b9f0fa..d492b82def4 100644 --- a/core/renderers/common/path_object.ts +++ b/core/renderers/common/path_object.ts @@ -10,6 +10,7 @@ import type {BlockSvg} from '../../block_svg.js'; import type {Connection} from '../../connection.js'; import {RenderedConnection} from '../../rendered_connection.js'; import type {BlockStyle} from '../../theme.js'; +import {idGenerator} from '../../utils.js'; import {Coordinate} from '../../utils/coordinate.js'; import * as dom from '../../utils/dom.js'; import {Svg} from '../../utils/svg.js'; @@ -23,6 +24,8 @@ import type {IPathObject} from './i_path_object.js'; export class PathObject implements IPathObject { svgRoot: SVGElement; svgPath: SVGElement; + private clip: SVGElement; + private clipPath: SVGElement; constants: ConstantProvider; style: BlockStyle; @@ -50,9 +53,21 @@ export class PathObject implements IPathObject { /** The primary path of the block. */ this.svgPath = dom.createSvgElement( Svg.PATH, - {'class': 'blocklyPath'}, + { + 'class': 'blocklyPath', + // The page-wide unique ID of this Block used for focusing. + 'id': idGenerator.getNextUniqueId(), + }, + this.svgRoot, + ); + // TODO: Move this to a ? + this.clip = dom.createSvgElement( + Svg.CLIPPATH, + {'id': `${this.svgPath.id}_clip`}, this.svgRoot, ); + this.clipPath = dom.createSvgElement(Svg.PATH, {}, this.clip); + this.svgPath.setAttribute('clip-path', `url(#${this.clip.id})`); this.setClass_('blocklyBlock', true); } @@ -64,6 +79,7 @@ export class PathObject implements IPathObject { */ setPath(pathString: string) { this.svgPath.setAttribute('d', pathString); + this.clipPath.setAttribute('d', pathString); } /** @@ -82,6 +98,7 @@ export class PathObject implements IPathObject { */ applyColour(block: BlockSvg) { this.svgPath.setAttribute('stroke', this.style.colourTertiary); + this.svgPath.setAttribute('stroke-width', '2px'); this.svgPath.setAttribute('fill', this.style.colourPrimary); this.updateShadow_(block.isShadow()); diff --git a/core/renderers/zelos/constants.ts b/core/renderers/zelos/constants.ts index 8cd36e02589..218f5e651fd 100644 --- a/core/renderers/zelos/constants.ts +++ b/core/renderers/zelos/constants.ts @@ -900,11 +900,17 @@ export class ConstantProvider extends BaseConstantProvider { `stroke: none;`, `}`, - `${selector} .blocklySelected>.blocklyPath.blocklyPathSelected {`, - `fill: none;`, - `filter: var(--blocklySelectedGlowFilter);`, + // Selection highlight. + `${selector} .blocklySelected>.blocklyPath {`, + `stroke: #fc3;`, + `stroke-width: 6px;`, `}`, + // `${selector} .blocklySelected>.blocklyPath.blocklyPathSelected {`, + // `fill: none;`, + // `filter: var(--blocklySelectedGlowFilter);`, + // `}`, + `${selector} .blocklyReplaceable>.blocklyPath {`, `filter: var(--blocklyReplacementGlowFilter);`, `}`, diff --git a/core/renderers/zelos/path_object.ts b/core/renderers/zelos/path_object.ts index 3c304fd6bf8..5f75fbaa89a 100644 --- a/core/renderers/zelos/path_object.ts +++ b/core/renderers/zelos/path_object.ts @@ -103,11 +103,11 @@ export class PathObject extends BasePathObject { ); this.svgPathSelected.removeAttribute('tabindex'); this.svgPathSelected.removeAttribute('id'); - this.svgRoot.appendChild(this.svgPathSelected); + // this.svgRoot.appendChild(this.svgPathSelected); } } else { if (this.svgPathSelected) { - this.svgRoot.removeChild(this.svgPathSelected); + // this.svgRoot.removeChild(this.svgPathSelected); this.svgPathSelected = null; } }