// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.0 OR LicenseRef-Slint-commercial import { Palette, Typography } from "styling.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 <=> i-focus-scope.has-focus; in-out property background; in-out property< bool> checked; forward-focus: i-focus-scope; i-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; } } i-focus-scope := 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: { i-ripple.opacity: 0.12; } checked when root.checked: { i-ripple.opacity: 1.0; i-ripple.background: root.selection-background; } hover when root.has-hover: { i-ripple.opacity: 0.08; } focused when root.has-focus: { i-ripple.opacity: 0.12; } ] } // A selectable item that is used by `StandardListView` and `ComboBox`. export component ListItem inherits Rectangle { callback clicked <=> i-state-layer.clicked; in property selected; in property text; height: max(48px, i-layout.min-height); i-state-layer := StateLayer { checked: root.selected; background: Palette.primary; selection-background: Palette.secondary-container; ripple-color: Palette.primary-ripple; has-ripple: true; } i-layout := HorizontalLayout { padding-left: 12px; padding-right: 12px; label := Text { text: root.text; color: Palette.on-surface; vertical-alignment: center; // FIXME after Roboto font can be loaded //font-family: Typography.label-large.font; font-size: Typography.label-large.font-size; font-weight: Typography.label-large.font-weight; } } states [ selected when root.selected : { i-state-layer.background: Palette.secondary-container; } ] }