// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial import { md } from "md.slint"; export component Ripple inherits 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 - self.width / 2; y: root.ripple-y - self.width / 2; height: self.width; border-radius: self.width / 2; } states [ active when root.active && root.has-effect: { circle.width: root.width * 2 * 1.4142; in { animate circle.width { duration: 2s; easing: ease-out; } } } ] } // A touch area that also represents a visual state. export component StateLayer inherits 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 { x:0; 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: root.selection-background; } hover when root.has-hover: { ripple.opacity: 0.08; } focused when root.has-focus: { ripple.opacity: 0.12; } ] }