// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial import { md } from "md.slint"; export Ripple := Rectangle { in property ripple-x; in property ripple-y; in property active; in property has-effect; in property ripple-color <=> circle.background; circle := Rectangle { x: root.ripple-x - width / 2; y: root.ripple-y - width / 2; height: width; border-radius: width / 2; } states [ active when root.active && root.has-effect: { circle.width: root.width * 2 * 1.4142; } ] transitions [ in active : { animate circle.width { duration: 2s; easing: ease-out; } } ] } // A touch area that also represents a visual state. export StateLayer := TouchArea { in property focusable; in property selection-background; in property ripple-color; in property has-ripple; in property border-radius; out property has-focus <=> fs.has-focus; in-out property background; in-out property checked; forward-focus: fs; ripple := Ripple { width: 100%; height: 100%; opacity: 0; active: root.pressed; ripple-x: root.pressed-x; ripple-y: root.pressed-y; clip: true; border-radius: root.border-radius; background: root.background; ripple-color: root.ripple-color; has-effect: root.has-ripple; animate opacity { duration: 250ms; easing: ease; } animate background { duration: 250ms; } } fs := FocusScope { width: 0px; // Do not react on clicks enabled: root.enabled && root.focusable; key-pressed(event) => { if (event.text == " " || event.text == "\n") { root.clicked(); return accept; } return reject; } } states [ pressed when root.pressed: { ripple.opacity: 0.12; } checked when root.checked: { ripple.opacity: 1.0; ripple.background: selection-background; } hover when root.has-hover: { ripple.opacity: 0.08; } focused when root.has-focus: { ripple.opacity: 0.12; } ] }