Merge pull request #1509 from feat/m3-revamp

Material 3 expressive revamp
This commit is contained in:
2 * r + 2 * t 2026-06-02 22:45:40 +10:00 committed by GitHub
commit b620f4c772
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
279 changed files with 10783 additions and 6501 deletions

View file

@ -71,3 +71,20 @@ if("shell" IN_LIST ENABLE_MODULES)
install(FILES LICENSE DESTINATION "${INSTALL_QSCONFDIR}")
endif()
if("plugin" IN_LIST ENABLE_MODULES OR "shell" IN_LIST ENABLE_MODULES)
message(STATUS "Fetching M3Shapes module")
include(FetchContent)
FetchContent_Declare(
m3shapes_external
GIT_REPOSITORY https://github.com/soramanew/m3shapes.git
GIT_TAG main
)
FetchContent_MakeAvailable(m3shapes_external)
message(STATUS "Done fetching M3Shapes module")
# Fix m3shapes wrong rpath
if(TARGET m3shapesplugin)
set_target_properties(m3shapesplugin PROPERTIES INSTALL_RPATH "$ORIGIN")
endif()
endif()

View file

@ -0,0 +1,91 @@
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View file

@ -1,26 +0,0 @@
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
mat4 qt_Matrix;
float qt_Opacity;
float fadeMargin;
};
layout(binding = 1) uniform sampler2D source;
void main() {
vec4 tex = texture(source, qt_TexCoord0);
float factor = 1.0;
float margin = 0.1;
if (qt_TexCoord0.y < margin) {
factor = qt_TexCoord0.y / margin;
} else if (qt_TexCoord0.y > (1.0 - margin)) {
factor = (1.0 - qt_TexCoord0.y) / margin;
}
fragColor = tex * factor * qt_Opacity;
}

Binary file not shown.

View file

@ -1,19 +0,0 @@
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
// qt_Matrix and qt_Opacity must always be both present
// if the built-in vertex shader is used.
mat4 qt_Matrix;
float qt_Opacity;
};
layout(binding = 1) uniform sampler2D source;
layout(binding = 2) uniform sampler2D maskSource;
void main()
{
fragColor = texture(source, qt_TexCoord0.st) * (texture(maskSource, qt_TexCoord0.st).a) * qt_Opacity;
}

Binary file not shown.

View file

@ -13,33 +13,48 @@ NumberAnimation {
EmphasizedExtraLarge,
FastSpatial,
DefaultSpatial,
SlowSpatial
SlowSpatial,
FastEffects,
DefaultEffects,
SlowEffects
}
property int type: Anim.Standard
property int type: Anim.DefaultSpatial
duration: {
if (type < Anim.StandardSmall || type > Anim.SlowSpatial)
if (type < Anim.StandardSmall || type > Anim.SlowEffects)
return Tokens.anim.durations.normal;
if (type == Anim.FastSpatial)
if (type === Anim.FastSpatial)
return Tokens.anim.durations.expressiveFastSpatial;
if (type == Anim.DefaultSpatial)
if (type === Anim.DefaultSpatial)
return Tokens.anim.durations.expressiveDefaultSpatial;
if (type == Anim.SlowSpatial)
if (type === Anim.SlowSpatial)
return Tokens.anim.durations.expressiveSlowSpatial;
if (type === Anim.FastEffects)
return Tokens.anim.durations.expressiveFastEffects;
if (type === Anim.DefaultEffects)
return Tokens.anim.durations.expressiveDefaultEffects;
if (type === Anim.SlowEffects)
return Tokens.anim.durations.expressiveSlowEffects;
const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4; // 0-7 are the 4 standard types
return Tokens.anim.durations[types[idx]];
}
easing: {
if (type == Anim.FastSpatial)
if (type === Anim.FastSpatial)
return Tokens.anim.expressiveFastSpatial;
if (type == Anim.DefaultSpatial)
if (type === Anim.DefaultSpatial)
return Tokens.anim.expressiveDefaultSpatial;
if (type == Anim.SlowSpatial)
if (type === Anim.SlowSpatial)
return Tokens.anim.expressiveSlowSpatial;
if (type === Anim.FastEffects)
return Tokens.anim.expressiveFastEffects;
if (type === Anim.DefaultEffects)
return Tokens.anim.expressiveDefaultEffects;
if (type === Anim.SlowEffects)
return Tokens.anim.expressiveSlowEffects;
if (type >= Anim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Tokens.anim.emphasized;

View file

@ -2,6 +2,6 @@ import QtQuick
import Caelestia.Config
ColorAnimation {
duration: Tokens.anim.durations.normal
easing: Tokens.anim.standard
duration: Tokens.anim.durations.expressiveSlowEffects
easing: Tokens.anim.expressiveSlowEffects
}

View file

@ -9,22 +9,20 @@ ColumnLayout {
required property string icon
required property string title
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
Layout.alignment: Qt.AlignHCenter
MaterialIcon {
Layout.alignment: Qt.AlignHCenter
animate: true
text: root.icon
font.pointSize: Tokens.font.size.extraLarge * 3
font.bold: true
fontStyle: Tokens.font.icon.builders.extraLarge.scale(3).weight(Font.Bold).build()
}
StyledText {
Layout.alignment: Qt.AlignHCenter
animate: true
text: root.title
font.pointSize: Tokens.font.size.large
font.bold: true
font: Tokens.font.title.builders.medium.weight(Font.Bold).build()
}
}

View file

@ -9,7 +9,7 @@ ColumnLayout {
required property var deviceDetails
spacing: Tokens.spacing.small / 2
spacing: Tokens.spacing.extraSmall
StyledText {
text: qsTr("IP Address")
@ -18,40 +18,40 @@ ColumnLayout {
StyledText {
text: root.deviceDetails?.ipAddress || qsTr("Not available")
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
StyledText {
Layout.topMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.spacing.medium
text: qsTr("Subnet Mask")
}
StyledText {
text: root.deviceDetails?.subnet || qsTr("Not available")
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
StyledText {
Layout.topMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.spacing.medium
text: qsTr("Gateway")
}
StyledText {
text: root.deviceDetails?.gateway || qsTr("Not available")
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
StyledText {
Layout.topMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.spacing.medium
text: qsTr("DNS Servers")
}
StyledText {
text: (root.deviceDetails && root.deviceDetails.dns && root.deviceDetails.dns.length > 0) ? root.deviceDetails.dns.join(", ") : qsTr("Not available")
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
wrapMode: Text.Wrap
Layout.maximumWidth: parent.width
}

View file

@ -1,16 +1,11 @@
import QtQuick
import Caelestia.Config
import qs.services
StyledText {
property real fill
property int grade: Colours.light ? 0 : -25
property font fontStyle: Tokens.font.icon.small
font.family: Tokens.font.family.material
font.pointSize: Tokens.font.size.larger
font.variableAxes: ({
FILL: fill.toFixed(1),
GRAD: grade,
opsz: fontInfo.pixelSize,
wght: fontInfo.weight
})
font: Tokens.font.icon.size(fontStyle.pointSize).weight(fontStyle.weight).vaxes(fontStyle.variableAxes).fill(fill.toFixed(1)).grade(grade).build()
}

View file

@ -11,16 +11,16 @@ ColumnLayout {
required property string value
property bool showTopMargin: false
spacing: Tokens.spacing.small / 2
spacing: Tokens.spacing.extraSmall
StyledText {
Layout.topMargin: root.showTopMargin ? Tokens.spacing.normal : 0
Layout.topMargin: root.showTopMargin ? Tokens.spacing.medium : 0
text: root.label
}
StyledText {
text: root.value
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
}

View file

@ -8,13 +8,13 @@ StyledRect {
id: root
default property alias content: contentColumn.data
property real contentSpacing: Tokens.spacing.larger
property real contentSpacing: Tokens.spacing.large
property bool alignTop: false
Layout.fillWidth: true
implicitHeight: contentColumn.implicitHeight + Tokens.padding.large * 2
implicitHeight: contentColumn.implicitHeight + Tokens.padding.extraLargeIncreased
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
color: Colours.transparency.enabled ? Colours.layer(Colours.palette.m3surfaceContainer, 2) : Colours.palette.m3surfaceContainerHigh
ColumnLayout {

View file

@ -13,10 +13,9 @@ ColumnLayout {
spacing: 0
StyledText {
Layout.topMargin: Tokens.spacing.large
Layout.topMargin: Tokens.spacing.largeIncreased
text: root.title
font.pointSize: Tokens.font.size.larger
font.weight: 500
font: Tokens.font.title.builders.medium.weight(Font.Medium).build()
}
StyledText {

View file

@ -29,7 +29,7 @@ MouseArea {
const d2 = distSq(width, 0);
const d3 = distSq(0, height);
const d4 = distSq(width, height);
return Math.sqrt(Math.max(d1, d2, d3, d4)) * (shapeMorph ? 1.16 : 1);
return Math.sqrt(Math.max(d1, d2, d3, d4)) + (shapeMorph ? 24 : 0);
}
property real endRadiusAtPress
@ -85,8 +85,7 @@ MouseArea {
target: circle
property: "opacity"
to: 0
easing: Tokens.anim.expressiveSlowEffects
duration: Tokens.anim.durations.expressiveSlowEffects
type: Anim.SlowEffects
}
StyledRect {
@ -135,14 +134,14 @@ MouseArea {
startY: 0
PathLine {
x: root.width - root.clamp(base.topLeftRadius)
x: root.width - root.clamp(base.topRightRadius)
y: 0
}
PathArc {
relativeX: root.clamp(base.topLeftRadius)
relativeY: root.clamp(base.topLeftRadius)
radiusX: root.clamp(base.topLeftRadius)
radiusY: root.clamp(base.topLeftRadius)
relativeX: root.clamp(base.topRightRadius)
relativeY: root.clamp(base.topRightRadius)
radiusX: root.clamp(base.topRightRadius)
radiusY: root.clamp(base.topRightRadius)
}
PathLine {
x: root.width
@ -179,8 +178,7 @@ MouseArea {
Behavior on stateOpacity {
Anim {
easing: Tokens.anim.expressiveDefaultEffects
duration: Tokens.anim.durations.expressiveDefaultEffects
type: Anim.DefaultEffects
}
}
}

View file

@ -8,16 +8,11 @@ Text {
id: root
property bool animate: false
property string animateProp: "scale"
property real animateFrom: 0
property real animateTo: 1
property int animateDuration: Tokens.anim.durations.normal
renderType: Text.NativeRendering
textFormat: Text.PlainText
color: Colours.palette.m3onSurface
font.family: Tokens.font.family.sans
font.pointSize: Tokens.font.size.smaller
font: Tokens.font.body.small
Behavior on color {
CAnim {}
@ -28,20 +23,18 @@ Text {
SequentialAnimation {
Anim {
to: root.animateFrom
easing: Tokens.anim.standardAccel
target: root
property: "opacity"
to: 0
type: Anim.FastEffects
}
PropertyAction {}
Anim {
to: root.animateTo
easing: Tokens.anim.standardDecel
}
}
}
component Anim: NumberAnimation {
target: root
property: root.animateProp
duration: root.animateDuration / 2
property: "opacity"
to: 1
type: Anim.DefaultEffects
}
}
}
}

View file

@ -0,0 +1,97 @@
//@ pragma Internal
import QtQuick
import Caelestia.Config
import qs.components
import qs.services
StyledRect {
id: root
enum ButtonType {
Filled,
Tonal,
Text
}
property bool checked
property alias disabled: stateLayer.disabled
property bool isToggle
property bool isRound
property bool radiusMorph: true
property alias shapeMorph: stateLayer.shapeMorph
property bool fillWidth // For ButtonRow
property font font
property int type: ButtonBase.Filled
property real padding
property real horizontalPadding: padding
property real verticalPadding: padding
readonly property alias pressed: stateLayer.pressed
readonly property alias hovered: stateLayer.containsMouse
readonly property alias stateLayer: stateLayer
readonly property alias radiusAnim: radiusAnim
required property color activeColour
required property color inactiveColour
required property color activeOnColour
required property color inactiveOnColour
property color disabledColour: Qt.alpha(Colours.palette.m3onSurface, 0.1)
property color disabledOnColour: Qt.alpha(Colours.palette.m3onSurface, 0.38)
property bool internalChecked
property real shapeMorphExpansion: shapeMorph && pressed ? 24 : 0 // Apparently it's always 24px no matter the width of the button
readonly property color onColour: disabled ? disabledOnColour : internalChecked ? activeOnColour : inactiveOnColour
property real pressedRadius: Tokens.rounding.small
property real checkedRadius: Tokens.rounding.medium
property real defaultRadius: Tokens.rounding.large
signal clicked
onCheckedChanged: internalChecked = checked
radius: {
if (radiusMorph && pressed)
return pressedRadius;
if (internalChecked)
return checkedRadius;
if (isRound)
return implicitHeight / 2 * Math.min(1, Tokens.rounding.scale);
return defaultRadius;
}
color: type === ButtonBase.Text ? "transparent" : disabled ? disabledColour : internalChecked ? activeColour : inactiveColour
// Make size required so we don't forget to set it
required implicitWidth
required implicitHeight
StateLayer {
id: stateLayer
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
disabled: root.disabled
onClicked: {
if (root.isToggle)
root.internalChecked = !root.internalChecked;
root.clicked();
}
}
Behavior on radius {
Anim {
id: radiusAnim
type: Anim.DefaultEffects
}
}
Behavior on shapeMorphExpansion {
Anim {
type: Anim.FastSpatial
}
}
}

View file

@ -19,8 +19,8 @@ BusyIndicator {
Completing
}
property real implicitSize: Tokens.font.size.normal * 3
property real strokeWidth: Tokens.padding.small * 0.8
property real implicitSize: Tokens.font.body.medium.pointSize * 3
property real strokeWidth: Tokens.padding.extraSmall
property color fgColour: Colours.palette.m3primary
property color bgColour: Colours.palette.m3secondaryContainer
@ -63,6 +63,7 @@ BusyIndicator {
transitions: Transition {
Anim {
type: Anim.DefaultEffects
properties: "opacity,internalStrokeWidth"
duration: manager.completeEndDuration * Tokens.anim.durations.scale
}
@ -77,6 +78,7 @@ BusyIndicator {
rotation: manager.rotation
startAngle: manager.startFraction * 360
value: manager.endFraction - manager.startFraction
hasEndIndicator: false
}
CircularIndicatorManager {

View file

@ -1,69 +1,122 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Shapes
import Caelestia.Components
import Caelestia.Config
import qs.components
import qs.services
Shape {
Item {
id: root
property real value
property int startAngle: -90
property int strokeWidth: Tokens.padding.smaller
property int sweepAngle: 360
property int strokeWidth: Tokens.padding.small
property int padding: 0
property int spacing: Tokens.spacing.small
property color fgColour: Colours.palette.m3primary
property color bgColour: Colours.palette.m3secondaryContainer
property alias hasEndIndicator: dot.active
property bool wavy: false
property alias waveFrequency: wave.frequency
property alias waveAmplitude: wave.amplitudeMultiplier
property bool wavePaused
property alias waveDuration: waveProgAnim.duration
readonly property real size: Math.min(width, height)
readonly property real arcRadius: (size - padding - strokeWidth) / 2
readonly property real vValue: value || 1 / 360
readonly property real arcRadius: (size - padding - strokeWidth * (1 + waveAmplitude * 2)) / 2
property real clampedVal: Math.max(1 / 360, Math.min(1, isNaN(value) ? 0 : value)) // Not readonly for animations
readonly property real gapAngle: ((spacing + strokeWidth) / (arcRadius || 1)) * (180 / Math.PI)
readonly property real dotAngleRad: (startAngle + sweepAngle - gapAngle * (sweepAngle < 360 ? 0 : 1)) * Math.PI / 180
readonly property real thickness: strokeWidth * (1 + waveAmplitude) * 2 // For consumers
property real implicitSize
implicitWidth: implicitSize
implicitHeight: implicitSize
Shape {
preferredRendererType: Shape.CurveRenderer
asynchronous: true
opacity: Math.min(1, remainingArc.sweepAngle)
ShapePath {
fillColor: "transparent"
strokeColor: root.bgColour
strokeWidth: root.strokeWidth
capStyle: root.Tokens.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap
strokeWidth: Math.min(1, remainingArc.sweepAngle) * root.strokeWidth
capStyle: ShapePath.RoundCap
PathAngleArc {
startAngle: root.startAngle + 360 * root.vValue + root.gapAngle
sweepAngle: Math.max(-root.gapAngle, 360 * (1 - root.vValue) - root.gapAngle * 2)
id: remainingArc
radiusX: root.arcRadius
radiusY: root.arcRadius
centerX: root.size / 2
centerY: root.size / 2
startAngle: root.startAngle + root.clampedVal * root.sweepAngle + root.gapAngle
sweepAngle: Math.max(1 / 360, root.sweepAngle * (1 - root.clampedVal) - root.gapAngle * (root.sweepAngle < 360 ? 1 : 2))
}
Behavior on strokeColor {
CAnim {
duration: Tokens.anim.durations.large
CAnim {}
}
}
}
ShapePath {
fillColor: "transparent"
strokeColor: root.fgColour
strokeWidth: root.strokeWidth
capStyle: root.Tokens.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap
WavyLine {
id: wave
PathAngleArc {
anchors.fill: parent
anchors.margins: -lineWidth * amplitudeMultiplier
lineWidth: root.strokeWidth
color: root.fgColour
pathType: WavyLine.Arc
radius: root.arcRadius
startAngle: root.startAngle
sweepAngle: 360 * root.vValue
radiusX: root.arcRadius
radiusY: root.arcRadius
centerX: root.size / 2
centerY: root.size / 2
fullAngle: root.sweepAngle
value: root.clampedVal
frequency: 8
amplitudeMultiplier: root.wavy ? 0.5 : 0
Anim on waveProgress {
id: waveProgAnim
running: true
paused: root.wavePaused || wave.amplitudeMultiplier === 0
from: 0
to: 1
duration: 2000
easing.type: Easing.Linear
loops: Animation.Infinite
}
Behavior on strokeColor {
CAnim {
duration: Tokens.anim.durations.large
Behavior on color {
CAnim {}
}
Behavior on amplitudeMultiplier {
Anim {
type: Anim.DefaultEffects
}
}
}
Loader {
id: dot
x: root.size / 2 + root.arcRadius * Math.cos(root.dotAngleRad) - width / 2
y: root.size / 2 + root.arcRadius * Math.sin(root.dotAngleRad) - height / 2
sourceComponent: StyledRect {
radius: Tokens.rounding.full
color: root.fgColour
opacity: Math.min(1, remainingArc.sweepAngle)
implicitWidth: Math.min(1, remainingArc.sweepAngle) * Math.min(4, root.strokeWidth)
implicitHeight: Math.min(1, remainingArc.sweepAngle) * Math.min(4, root.strokeWidth)
}
}
}

View file

@ -24,7 +24,7 @@ ColumnLayout {
id: sectionHeaderItem
Layout.fillWidth: true
Layout.preferredHeight: Math.max(titleRow.implicitHeight + Tokens.padding.normal * 2, 48)
Layout.preferredHeight: Math.max(titleRow.implicitHeight + Tokens.padding.medium * 2, 48)
RowLayout {
id: titleRow
@ -32,14 +32,13 @@ ColumnLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Tokens.padding.normal
anchors.rightMargin: Tokens.padding.normal
spacing: Tokens.spacing.normal
anchors.leftMargin: Tokens.padding.medium
anchors.rightMargin: Tokens.padding.medium
spacing: Tokens.spacing.medium
StyledText {
text: root.title
font.pointSize: Tokens.font.size.larger
font.weight: 500
font: Tokens.font.title.builders.medium.weight(Font.Medium).build()
}
Item {
@ -50,7 +49,7 @@ ColumnLayout {
text: "expand_more"
rotation: root.expanded ? 180 : 0
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.normal
fontStyle: Tokens.font.icon.medium
Behavior on rotation {
Anim {
@ -63,7 +62,7 @@ ColumnLayout {
StateLayer {
anchors.fill: parent
color: Colours.palette.m3onSurface
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
showHoverBackground: false
onClicked: {
root.toggleRequested();
@ -76,7 +75,7 @@ ColumnLayout {
id: contentWrapper
Layout.fillWidth: true
Layout.preferredHeight: root.expanded ? (contentColumn.implicitHeight + Tokens.spacing.small * 2) : 0
Layout.preferredHeight: root.expanded ? (contentColumn.implicitHeight + Tokens.spacing.large) : 0
clip: true
Behavior on Layout.preferredHeight {
@ -87,13 +86,15 @@ ColumnLayout {
id: backgroundRect
anchors.fill: parent
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
color: Colours.transparency.enabled ? Colours.layer(Colours.palette.m3surfaceContainer, root.nested ? 3 : 2) : (root.nested ? Colours.palette.m3surfaceContainerHigh : Colours.palette.m3surfaceContainer)
opacity: root.showBackground && root.expanded ? 1.0 : 0.0
visible: root.showBackground
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
@ -103,26 +104,28 @@ ColumnLayout {
anchors.left: parent.left
anchors.right: parent.right
y: Tokens.spacing.small
anchors.leftMargin: Tokens.padding.normal
anchors.rightMargin: Tokens.padding.normal
anchors.leftMargin: Tokens.padding.medium
anchors.rightMargin: Tokens.padding.medium
anchors.bottomMargin: Tokens.spacing.small
spacing: Tokens.spacing.small
opacity: root.expanded ? 1.0 : 0.0
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
StyledText {
id: descriptionText
Layout.fillWidth: true
Layout.topMargin: root.description !== "" ? Tokens.spacing.smaller : 0
Layout.topMargin: root.description !== "" ? Tokens.spacing.medium : 0
Layout.bottomMargin: root.description !== "" ? Tokens.spacing.small : 0
visible: root.description !== ""
text: root.description
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
wrapMode: Text.Wrap
}
}

View file

@ -73,23 +73,23 @@ RowLayout {
root.isEditing = false;
}
padding: Tokens.padding.small
leftPadding: Tokens.padding.normal
rightPadding: Tokens.padding.normal
padding: Tokens.padding.extraSmall
leftPadding: Tokens.padding.medium
rightPadding: Tokens.padding.medium
background: StyledRect {
implicitWidth: 100
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
color: Colours.tPalette.m3surfaceContainerHigh
}
}
StyledRect {
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
color: Colours.palette.m3primary
implicitWidth: implicitHeight
implicitHeight: upIcon.implicitHeight + Tokens.padding.small * 2
implicitHeight: upIcon.implicitHeight + Tokens.padding.small
StateLayer {
id: upState
@ -120,11 +120,11 @@ RowLayout {
}
StyledRect {
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
color: Colours.palette.m3primary
implicitWidth: implicitHeight
implicitHeight: downIcon.implicitHeight + Tokens.padding.small * 2
implicitHeight: downIcon.implicitHeight + Tokens.padding.small
StateLayer {
id: downState

View file

@ -67,41 +67,22 @@ Slider {
property bool moving
function update(): void {
animate = !moving;
binding.when = moving;
font.pointSize = moving ? Tokens.font.size.small : Tokens.font.size.larger;
font.family = moving ? Tokens.font.family.sans : Tokens.font.family.material;
}
text: root.icon
color: Colours.palette.m3inverseOnSurface
anchors.centerIn: parent
anchors.verticalCenterOffset: 1
text: moving ? Math.round(root.value * 100) : root.icon
color: Colours.palette.m3inverseOnSurface
font: moving ? Tokens.font.body.small : Tokens.font.icon.medium
onMovingChanged: anim.restart()
Binding {
id: binding
target: icon
property: "text"
value: Math.round(root.value * 100)
when: false
}
Behavior on moving {
SequentialAnimation {
id: anim
Anim {
target: icon
property: "scale"
to: 0
duration: Tokens.anim.durations.normal / 2
to: 0.3
duration: Tokens.anim.durations.small / 2
easing: Tokens.anim.standardAccel
}
ScriptAction {
script: icon.update()
}
PropertyAction {}
Anim {
target: icon
property: "scale"
@ -113,6 +94,7 @@ Slider {
}
}
}
}
onPressedChanged: handle.moving = pressed

View file

@ -3,80 +3,50 @@ import Caelestia.Config
import qs.components
import qs.services
StyledRect {
ButtonBase {
id: root
enum Type {
Filled,
Tonal,
Text
}
property alias icon: label.text
property bool checked
property bool toggle
property real padding: type === IconButton.Text ? Tokens.padding.small / 2 : Tokens.padding.smaller
property alias font: label.font
property int type: IconButton.Filled
property bool disabled
readonly property alias label: label
property alias stateLayer: stateLayer
property alias label: label
property alias radiusAnim: radiusAnim
font: Tokens.font.icon.medium
padding: type === IconButton.Text ? Tokens.padding.extraSmall / 2 : Tokens.padding.small
property bool internalChecked
property color activeColour: type === IconButton.Filled ? Colours.palette.m3primary : Colours.palette.m3secondary
property color inactiveColour: {
if (!toggle && type === IconButton.Filled)
activeColour: type === IconButton.Filled ? Colours.palette.m3primary : Colours.palette.m3secondary
inactiveColour: {
if (!isToggle && type === IconButton.Filled)
return Colours.palette.m3primary;
return type === IconButton.Filled ? Colours.tPalette.m3surfaceContainer : Colours.palette.m3secondaryContainer;
}
property color activeOnColour: type === IconButton.Filled ? Colours.palette.m3onPrimary : type === IconButton.Tonal ? Colours.palette.m3onSecondary : Colours.palette.m3primary
property color inactiveOnColour: {
if (!toggle && type === IconButton.Filled)
activeOnColour: type === IconButton.Filled ? Colours.palette.m3onPrimary : type === IconButton.Tonal ? Colours.palette.m3onSecondary : Colours.palette.m3primary
inactiveOnColour: {
if (!isToggle && type === IconButton.Filled)
return Colours.palette.m3onPrimary;
return type === IconButton.Tonal ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurfaceVariant;
}
property color disabledColour: Qt.alpha(Colours.palette.m3onSurface, 0.1)
property color disabledOnColour: Qt.alpha(Colours.palette.m3onSurface, 0.38)
signal clicked
onCheckedChanged: internalChecked = checked
radius: internalChecked ? Tokens.rounding.small : implicitHeight / 2 * Math.min(1, Tokens.rounding.scale)
color: type === IconButton.Text ? "transparent" : disabled ? disabledColour : internalChecked ? activeColour : inactiveColour
implicitWidth: implicitHeight
implicitHeight: label.implicitHeight + padding * 2
StateLayer {
id: stateLayer
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
disabled: root.disabled
onClicked: {
if (root.toggle)
root.internalChecked = !root.internalChecked;
root.clicked();
}
implicitHeight: {
// Ensure even size so icon is centered properly
const h = label.implicitHeight + padding * 2;
if (h % 2 !== 0)
return h + 1;
return h;
}
MaterialIcon {
id: label
anchors.centerIn: parent
color: root.disabled ? root.disabledOnColour : root.internalChecked ? root.activeOnColour : root.inactiveOnColour
fill: !root.toggle || root.internalChecked ? 1 : 0
anchors.verticalCenterOffset: 1 // AHHHHHHH material symbols whyyyy
color: root.onColour
fontStyle: root.font
fill: !root.isToggle || root.internalChecked ? 1 : 0
Behavior on fill {
Anim {}
}
}
Behavior on radius {
Anim {
id: radiusAnim
type: Anim.DefaultEffects
}
}
}
}

View file

@ -4,55 +4,23 @@ import Caelestia.Config
import qs.components
import qs.services
StyledRect {
ButtonBase {
id: root
enum Type {
Filled,
Tonal,
Text
}
property alias icon: iconLabel.text
property alias text: label.text
property bool checked
property bool toggle
property real horizontalPadding: Tokens.padding.normal
property real verticalPadding: Tokens.padding.smaller
property alias font: label.font
property int type: IconTextButton.Filled
property alias stateLayer: stateLayer
property alias iconLabel: iconLabel
property alias label: label
readonly property alias iconLabel: iconLabel
readonly property alias label: label
property bool internalChecked
property color activeColour: type === IconTextButton.Filled ? Colours.palette.m3primary : Colours.palette.m3secondary
property color inactiveColour: type === IconTextButton.Filled ? Colours.tPalette.m3surfaceContainer : Colours.palette.m3secondaryContainer
property color activeOnColour: type === IconTextButton.Filled ? Colours.palette.m3onPrimary : Colours.palette.m3onSecondary
property color inactiveOnColour: type === IconTextButton.Filled ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
signal clicked
onCheckedChanged: internalChecked = checked
radius: internalChecked ? Tokens.rounding.small : implicitHeight / 2 * Math.min(1, Tokens.rounding.scale)
color: type === IconTextButton.Text ? "transparent" : internalChecked ? activeColour : inactiveColour
activeColour: type === IconTextButton.Filled ? Colours.palette.m3primary : Colours.palette.m3secondary
inactiveColour: type === IconTextButton.Filled ? Colours.tPalette.m3surfaceContainer : Colours.palette.m3secondaryContainer
activeOnColour: type === IconTextButton.Filled ? Colours.palette.m3onPrimary : Colours.palette.m3onSecondary
inactiveOnColour: type === IconTextButton.Filled ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
implicitWidth: row.implicitWidth + horizontalPadding * 2
implicitHeight: row.implicitHeight + verticalPadding * 2
StateLayer {
id: stateLayer
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
onClicked: {
if (root.toggle)
root.internalChecked = !root.internalChecked;
root.clicked();
}
}
RowLayout {
id: row
@ -64,11 +32,13 @@ StyledRect {
Layout.alignment: Qt.AlignVCenter
Layout.topMargin: Math.round(fontInfo.pointSize * 0.0575)
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
color: root.onColour
fill: root.internalChecked ? 1 : 0
Behavior on fill {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
@ -77,11 +47,7 @@ StyledRect {
Layout.alignment: Qt.AlignVCenter
Layout.topMargin: -Math.round(iconLabel.fontInfo.pointSize * 0.0575)
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
color: root.onColour
}
}
Behavior on radius {
Anim {}
}
}

View file

@ -0,0 +1,116 @@
import QtQuick
import Quickshell
import M3Shapes
import qs.components
import qs.services
MaterialShape {
id: root
property list<int> shapes: {
if (containsIcon)
return [MaterialShape.SoftBurst, MaterialShape.Cookie9Sided, MaterialShape.Pill, MaterialShape.Sunny, MaterialShape.Cookie4Sided, MaterialShape.Oval];
return [MaterialShape.SoftBurst, MaterialShape.Cookie9Sided, MaterialShape.Pentagon, MaterialShape.Pill, MaterialShape.Sunny, MaterialShape.Cookie4Sided, MaterialShape.Oval];
}
property int shapeIndex
property real cRotation
property real lRotation
property real thisLRotation
property bool containsIcon
property bool animated: true
property int morphAnimRotation: 60
property real morphScale: 0.14
property alias rotateAnimDuration: rotateAnim.duration
property real stiffness: 180
property real dampingRatio: 0.6
property real visibilityThreshold: 0.075
readonly property real springDuration: {
const wn = Math.sqrt(stiffness);
const r = -dampingRatio * wn;
const c = 1 / Math.sqrt(1 - dampingRatio * dampingRatio);
return Math.log(visibilityThreshold / c) / r;
}
readonly property real springMaxVelocity: {
const wn = Math.sqrt(stiffness);
const factor = Math.exp(-z * Math.acos(z) / Math.sqrt(1 - z * z));
return wn * factor;
}
property bool springSettled: true
function spring(t: real): var {
const wn = Math.sqrt(stiffness);
const za = dampingRatio * wn;
const wd = wn * Math.sqrt(1 - dampingRatio * dampingRatio);
const r = za / wd;
const pos = 1 - Math.exp(-za * t) * (Math.cos(wd * t) + r * Math.sin(wd * t));
const vel = Math.exp(-za * t) * (wn * wn / wd) * Math.sin(wd * t);
return [pos, vel];
}
implicitSize: 38
color: Colours.palette.m3primary
toShape: shapes[0]
ElapsedTimer {
id: timer
}
FrameAnimation {
running: root.animated && !root.springSettled
onTriggered: {
const t = timer.elapsed();
if (t >= root.springDuration) {
root.springSettled = true;
} else {
const [pos, vel] = root.spring(t);
root.morphProgress = Math.min(1, pos); // Overshooting the morph looks weird
root.thisLRotation = pos * root.morphAnimRotation;
root.scale = 1 + vel * root.morphScale / root.springMaxVelocity;
}
}
}
Timer {
interval: 650
repeat: true
triggeredOnStart: true
running: root.animated
onTriggered: {
root.beginBatchUpdate();
root.fromShape = root.toShape;
root.shapeIndex = (root.shapeIndex + 1) % root.shapes.length;
root.toShape = root.shapes[root.shapeIndex];
root.morphProgress = 0;
root.rotation = root.rotation;
root.lRotation = (root.lRotation + root.thisLRotation) % 360;
root.thisLRotation = 0;
root.rotation = Qt.binding(() => root.cRotation + root.lRotation + root.thisLRotation);
root.springSettled = false;
timer.restart();
root.endBatchUpdate();
}
}
RotationAnimation on cRotation {
id: rotateAnim
running: root.animated
from: 0
to: 360
easing.type: Easing.Linear
loops: Animation.Infinite
duration: 4666
}
Behavior on color {
CAnim {}
}
}

View file

@ -48,7 +48,7 @@ MouseArea {
Behavior on opacity {
Anim {
duration: Tokens.anim.durations.small
type: Anim.DefaultEffects
}
}
@ -79,7 +79,7 @@ MouseArea {
return item.mapToItem(root.parent, 0, off).y + root.marginY;
}
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
level: 2
implicitWidth: Math.max(200, column.implicitWidth + column.anchors.margins * 2)
@ -90,9 +90,7 @@ MouseArea {
origin.y: root.thisSideY === Menu.Bottom ? menu.height : 0
Behavior on yScale {
Anim {
type: Anim.DefaultSpatial
}
Anim {}
}
}
@ -105,7 +103,7 @@ MouseArea {
id: column
anchors.fill: parent
anchors.margins: Tokens.padding.small
anchors.margins: Tokens.padding.extraSmall
spacing: 0
Repeater {
@ -121,14 +119,14 @@ MouseArea {
readonly property bool active: modelData === root.active
Layout.fillWidth: true
implicitWidth: menuOptionRow.implicitWidth + Tokens.padding.normal * 2
implicitHeight: menuOptionRow.implicitHeight + Tokens.padding.normal * 2
implicitWidth: menuOptionRow.implicitWidth + Tokens.padding.medium * 2
implicitHeight: menuOptionRow.implicitHeight + Tokens.padding.medium * 2
radius: active ? 12 : Tokens.rounding.extraSmall // This should use a token, but tokens are currently extremely scuffed
topLeftRadius: index === 0 ? Tokens.rounding.small : radius
topRightRadius: index === 0 ? Tokens.rounding.small : radius
bottomLeftRadius: index === repeater.count - 1 ? Tokens.rounding.small : radius
bottomRightRadius: index === repeater.count - 1 ? Tokens.rounding.small : radius
radius: active ? Tokens.rounding.medium : Tokens.rounding.extraSmall
topLeftRadius: index === 0 ? Tokens.rounding.medium : radius
topRightRadius: index === 0 ? Tokens.rounding.medium : radius
bottomLeftRadius: index === repeater.count - 1 ? Tokens.rounding.medium : radius
bottomRightRadius: index === repeater.count - 1 ? Tokens.rounding.medium : radius
color: Qt.alpha(Colours.palette.m3tertiaryContainer, active ? 1 : 0)
@ -156,7 +154,7 @@ MouseArea {
id: menuOptionRow
anchors.fill: parent
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
spacing: Tokens.spacing.small
MaterialIcon {

View file

@ -15,8 +15,8 @@ StyledRect {
property var onValueModified: function (value) {}
Layout.fillWidth: true
implicitHeight: row.implicitHeight + Tokens.padding.large * 2
radius: Tokens.rounding.normal
implicitHeight: row.implicitHeight + Tokens.padding.extraLargeIncreased
radius: Tokens.rounding.large
color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
Behavior on implicitHeight {
@ -30,7 +30,7 @@ StyledRect {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
Layout.fillWidth: true

View file

@ -12,43 +12,46 @@ Row {
Tonal
}
property real horizontalPadding: Tokens.padding.normal
property real verticalPadding: Tokens.padding.smaller
property real horizontalPadding: Tokens.padding.medium
property real verticalPadding: Tokens.padding.small
property int type: SplitButton.Filled
property bool disabled
property bool menuOnTop
property string fallbackIcon
property string fallbackText
property real minLeftWidth
property alias menuItems: menu.items
property alias active: menu.active
property alias expanded: menu.expanded
property alias menu: menu
property alias iconLabel: iconLabel
property alias label: label
property alias stateLayer: stateLayer
readonly property alias menu: menu
readonly property alias iconLabel: iconLabel
readonly property alias label: label
readonly property alias stateLayer: stateLayer
readonly property alias textRow: textRow
readonly property alias expandBtn: expandBtn
property color colour: type == SplitButton.Filled ? Colours.palette.m3primary : Colours.palette.m3secondaryContainer
property color textColour: type == SplitButton.Filled ? Colours.palette.m3onPrimary : Colours.palette.m3onSecondaryContainer
property color disabledColour: Qt.alpha(Colours.palette.m3onSurface, 0.1)
property color disabledTextColour: Qt.alpha(Colours.palette.m3onSurface, 0.38)
spacing: Math.floor(Tokens.spacing.small / 2)
spacing: Math.floor(Tokens.spacing.extraSmall)
StyledRect {
radius: implicitHeight / 2 * Math.min(1, Tokens.rounding.scale)
topRightRadius: Tokens.rounding.small / 2
bottomRightRadius: Tokens.rounding.small / 2
topRightRadius: Tokens.rounding.medium / 2
bottomRightRadius: Tokens.rounding.medium / 2
color: root.disabled ? root.disabledColour : root.colour
implicitWidth: textRow.implicitWidth + root.horizontalPadding * 2
implicitWidth: Math.max(root.minLeftWidth, textRow.implicitWidth + root.horizontalPadding * 2)
implicitHeight: expandBtn.implicitHeight
StateLayer {
id: stateLayer
rect.topRightRadius: parent.topRightRadius
rect.bottomRightRadius: parent.bottomRightRadius
topRightRadius: parent.topRightRadius
bottomRightRadius: parent.bottomRightRadius
color: root.textColour
disabled: root.disabled
onClicked: root.active?.clicked()
@ -93,7 +96,7 @@ Row {
StyledRect {
id: expandBtn
property real rad: root.expanded ? implicitHeight / 2 * Math.min(1, Tokens.rounding.scale) : Tokens.rounding.small / 2
property real rad: root.expanded ? implicitHeight / 2 * Math.min(1, Tokens.rounding.scale) : Tokens.rounding.medium / 2
radius: implicitHeight / 2 * Math.min(1, Tokens.rounding.scale)
topLeftRadius: rad

View file

@ -20,8 +20,8 @@ StyledRect {
signal selected(item: MenuItem)
Layout.fillWidth: true
implicitHeight: row.implicitHeight + Tokens.padding.large * 2
radius: Tokens.rounding.normal
implicitHeight: row.implicitHeight + Tokens.padding.extraLargeIncreased
radius: Tokens.rounding.large
color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
clip: false
@ -33,7 +33,7 @@ StyledRect {
anchors.fill: parent
anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
Layout.fillWidth: true

View file

@ -21,14 +21,14 @@ Item {
signal editingFinished
implicitWidth: 70
implicitHeight: inputField.implicitHeight + Tokens.padding.small * 2
implicitHeight: inputField.implicitHeight + Tokens.padding.small
StyledRect {
id: container
anchors.fill: parent
color: inputHover.containsMouse || inputField.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2)
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
border.width: 1
border.color: inputField.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3)
opacity: root.enabled ? 1 : 0.5
@ -54,7 +54,7 @@ Item {
id: inputField
anchors.centerIn: parent
width: parent.width - Tokens.padding.normal
width: parent.width - Tokens.padding.medium
horizontalAlignment: root.horizontalAlignment
validator: root.validator
readOnly: root.readOnly

View file

@ -0,0 +1,247 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Templates
import Caelestia
import Caelestia.Components
import Caelestia.Config
import Caelestia.Internal
import qs.components
import qs.services
ProgressBar {
id: root
enum IndeterminateAnimState {
Running,
Completing,
Stopped
}
property color fgColour: Colours.palette.m3primary
property color bgColour: Colours.palette.m3secondaryContainer
property bool wavy
property bool wavePaused
property int waveFrequency: 6
property real waveAmplitude: 0.5
property int waveDuration: 1000
property int indeterminateAnimState: StyledProgressBar.Stopped
function toBounds(startFrac: real, endFrac: real, gapSize: real): point {
startFrac = CUtils.clamp(startFrac, 0, 1);
endFrac = CUtils.clamp(endFrac, 0, 1);
// Ramp down gap size
const GAP_RAMP_DOWN_THRESHOLD = 0.01;
gapSize += height / 2;
const startGapSize = (gapSize * CUtils.clamp(startFrac, 0, GAP_RAMP_DOWN_THRESHOLD) / GAP_RAMP_DOWN_THRESHOLD);
const endGapSize = (gapSize * (1 - CUtils.clamp(endFrac, 1 - GAP_RAMP_DOWN_THRESHOLD, 1)) / GAP_RAMP_DOWN_THRESHOLD);
const start = width * startFrac + startGapSize;
const end = width * endFrac - endGapSize;
return start >= end ? Qt.point(0, 0) : Qt.point(start, end);
}
function updateIAnimState(): void {
if (indeterminate) {
manager.completeEndProgress = 0;
indeterminateAnimState = StyledProgressBar.Running;
} else if (indeterminateAnimState === StyledProgressBar.Running) {
indeterminateAnimState = StyledProgressBar.Completing;
}
}
onIndeterminateChanged: updateIAnimState()
Component.onCompleted: updateIAnimState()
implicitWidth: 200
implicitHeight: 4
contentItem: Loader {
anchors.fill: parent
asynchronous: true
sourceComponent: root.indeterminate || root.indeterminateAnimState !== StyledProgressBar.Stopped ? indeterminateComp : determinateComp
}
LinearIndicatorManager {
id: manager
gap: root.Tokens.spacing.extraSmall
Anim on progress {
running: root.indeterminateAnimState !== StyledProgressBar.Stopped
from: 0
to: 1
duration: manager.duration
easing.type: Easing.Linear
loops: Animation.Infinite
}
Anim on completeEndProgress {
running: root.indeterminateAnimState === StyledProgressBar.Completing
to: 1
duration: manager.completeEndDuration
onFinished: {
if (root.indeterminateAnimState === StyledProgressBar.Completing)
root.indeterminateAnimState = StyledProgressBar.Stopped;
}
}
}
Component {
id: determinateComp
Item {
Line {
id: remaining
anchors.right: parent.right
implicitWidth: parent.width - wave.implicitWidth - Tokens.spacing.extraSmall
}
Line {
property real implicitSize
Component.onCompleted: implicitSize = Qt.binding(() => parent.width - wave.implicitWidth < parent.height ? parent.height : 4)
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: (parent.height - implicitHeight) / 2
implicitWidth: implicitSize
implicitHeight: implicitSize
radius: Tokens.rounding.full
color: root.fgColour
Behavior on implicitSize {
Anim {
type: Anim.FastSpatial
}
}
}
Wave {
id: wave
anchors.left: parent.left
Component.onCompleted: implicitWidth = Qt.binding(() => parent.width * root.visualPosition)
Behavior on implicitWidth {
Anim {}
}
}
}
}
Component {
id: indeterminateComp
Item {
id: content
Line {
bounds: {
const i = manager.activeIndicators[0]; // qmllint disable unresolved-type
return i ? root.toBounds(0, i.startFraction, i.gapSize / 2) : Qt.point(0, 0);
}
}
Line {
bounds: {
const i = manager.activeIndicators[manager.activeIndicators.length - 1]; // qmllint disable unresolved-type
return i ? root.toBounds(i.endFraction, 1, i.gapSize / 2) : Qt.point(0, 0);
}
}
Instantiator {
model: Math.max(manager.activeIndicators.length, 1) - 1 // qmllint disable unresolved-type
delegate: Line {
required property int index
readonly property LinearIndicatorSegment cur: manager.activeIndicators[index] // qmllint disable unresolved-type
readonly property LinearIndicatorSegment next: manager.activeIndicators[index + 1 % manager.activeIndicators.length] // qmllint disable unresolved-type
bounds: root.toBounds(cur.endFraction, next.startFraction, cur.gapSize / 2)
}
onObjectAdded: (_, obj) => content.data.push(obj)
onObjectRemoved: (_, obj) => {
const idx = content.data.indexOf(obj);
if (idx !== -1)
content.data.splice(idx, 1);
}
}
Instantiator {
model: manager.activeIndicators // qmllint disable unresolved-type
delegate: Wave {
required property LinearIndicatorSegment modelData
readonly property point bounds: root.toBounds(modelData.startFraction, modelData.endFraction, modelData.gapSize / 2)
x: bounds.x
implicitWidth: bounds.y - bounds.x
color: root.fgColour
}
onObjectAdded: (_, obj) => content.data.push(obj)
onObjectRemoved: (_, obj) => {
const idx = content.data.indexOf(obj);
if (idx !== -1)
content.data.splice(idx, 1);
}
}
}
}
component Line: StyledRect {
property point bounds
x: bounds.x
implicitWidth: bounds.y - bounds.x
anchors.verticalCenter: parent.verticalCenter
implicitHeight: parent.height
radius: Tokens.rounding.full
color: root.bgColour
}
component Wave: WavyLine {
id: wave
anchors.verticalCenter: parent.verticalCenter
implicitHeight: lineWidth * amplitudeMultiplier * 2 + lineWidth
lineWidth: parent.height
amplitudeMultiplier: root.wavy ? root.waveAmplitude : 0
frequency: root.waveFrequency
startX: x
fullLength: parent.width
color: root.fgColour
Anim on waveProgress {
running: true
paused: wave.amplitudeMultiplier === 0 || root.wavePaused
from: 0
to: 1
duration: root.waveDuration
easing.type: Easing.Linear
loops: Animation.Infinite
}
Behavior on amplitudeMultiplier {
Anim {
type: Anim.DefaultEffects
}
}
Behavior on color {
CAnim {}
}
}
}

View file

@ -7,7 +7,7 @@ import qs.services
RadioButton {
id: root
font.pointSize: Tokens.font.size.smaller
font: Tokens.font.body.small
implicitWidth: implicitIndicatorWidth + implicitContentWidth + contentItem.anchors.leftMargin
implicitHeight: Math.max(implicitIndicatorHeight, implicitContentHeight)
@ -24,7 +24,7 @@ RadioButton {
anchors.verticalCenter: parent.verticalCenter
StateLayer {
anchors.margins: -Tokens.padding.smaller
anchors.margins: -Tokens.padding.small
color: root.checked ? Colours.palette.m3onSurface : Colours.palette.m3primary
z: -1
onClicked: root.click()
@ -46,9 +46,9 @@ RadioButton {
contentItem: StyledText {
text: root.text
font.pointSize: root.font.pointSize
font: root.font
anchors.verticalCenter: parent.verticalCenter
anchors.left: outerCircle.right
anchors.leftMargin: Tokens.spacing.smaller
anchors.leftMargin: Tokens.spacing.medium
}
}

View file

@ -45,7 +45,7 @@ ScrollBar {
}
}
}
implicitWidth: Tokens.padding.small
implicitWidth: Tokens.padding.extraSmall
contentItem: StyledRect {
anchors.left: parent.left
@ -74,7 +74,9 @@ ScrollBar {
}
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}

View file

@ -1,5 +1,9 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Templates
import Caelestia
import Caelestia.Components
import Caelestia.Config
import qs.components
import qs.services
@ -7,51 +11,177 @@ import qs.services
Slider {
id: root
background: Item {
StyledRect {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.topMargin: root.implicitHeight / 3
anchors.bottomMargin: root.implicitHeight / 3
property bool wavy
property bool animateWave
property real waveFrequency: 6
property int waveDuration: 1000
implicitWidth: root.handle.x - root.implicitHeight / 6
property color fgColour: enabled ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3onSurface, 0.38)
property color bgColour: enabled ? Colours.palette.m3secondaryContainer : Qt.alpha(Colours.palette.m3onSurface, 0.1)
color: Colours.palette.m3primary
radius: Tokens.rounding.full
topRightRadius: root.implicitHeight / 15
bottomRightRadius: root.implicitHeight / 15
}
property real pos: visualPosition
property real filledWidth
signal interaction(v: real)
Component.onCompleted: filledWidth = Qt.binding(() => (width - handle.implicitWidth - handle.anchors.leftMargin) * pos)
implicitWidth: 200
implicitHeight: 12
contentItem: Item {
anchors.fill: parent
StyledRect {
anchors.top: parent.top
anchors.bottom: parent.bottom
id: remaining
anchors.left: handle.right
anchors.right: parent.right
anchors.topMargin: root.implicitHeight / 3
anchors.bottomMargin: root.implicitHeight / 3
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Tokens.spacing.extraSmall
implicitWidth: parent.width - root.handle.x - root.handle.implicitWidth - root.implicitHeight / 6
implicitHeight: parent.height * (parent.height <= 12 ? opacity : Math.min(opacity * 2, 1))
opacity: Math.min(width, 12) / 12
radius: Tokens.rounding.medium
topLeftRadius: Tokens.rounding.extraSmall / 2
bottomLeftRadius: Tokens.rounding.extraSmall / 2
color: root.bgColour
}
StyledRect {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: 4 * remaining.opacity
implicitWidth: implicitHeight
implicitHeight: 4 * remaining.opacity
opacity: remaining.opacity
color: Colours.palette.m3surfaceContainerHighest
radius: Tokens.rounding.full
topLeftRadius: root.implicitHeight / 15
bottomLeftRadius: root.implicitHeight / 15
color: root.fgColour
}
StyledRect {
id: handle
anchors.left: filled.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Tokens.spacing.extraSmall
implicitWidth: 4
implicitHeight: {
const mult = parent.height <= 12 ? 3 : 1.2;
const pressMult = parent.height <= 12 ? 4 : 1.5;
return parent.height * (mouse.pressed ? pressMult : mult);
}
radius: Tokens.rounding.full
color: root.fgColour
Behavior on implicitHeight {
Anim {
type: Anim.FastSpatial
}
}
}
handle: StyledRect {
x: root.visualPosition * root.availableWidth - implicitWidth / 2
Loader {
id: filled
implicitWidth: root.implicitHeight / 4.5
implicitHeight: root.implicitHeight
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
asynchronous: true
color: Colours.palette.m3primary
radius: Tokens.rounding.full
sourceComponent: root.wavy ? waveComp : lineComp
}
Component {
id: lineComp
StyledRect {
implicitWidth: root.filledWidth
implicitHeight: root.height
radius: Tokens.rounding.medium
topRightRadius: Tokens.rounding.extraSmall / 2
bottomRightRadius: Tokens.rounding.extraSmall / 2
color: root.fgColour
}
}
Component {
id: waveComp
WavyLine {
lineWidth: root.height * 0.7
frequency: root.waveFrequency
startX: x
fullLength: root.width - handle.implicitWidth - handle.anchors.leftMargin
color: root.fgColour
implicitWidth: root.filledWidth
implicitHeight: lineWidth * amplitudeMultiplier * 2 + lineWidth
Anim on waveProgress {
running: true
paused: !root.animateWave
from: 0
to: 1
duration: root.waveDuration
easing.type: Easing.Linear
loops: Animation.Infinite
}
Behavior on color {
CAnim {}
}
}
}
}
Binding {
id: posBinding
target: root
property: "pos"
value: CUtils.clamp(mouse.pressStartPos + mouse.dragMovement, 0, 1)
when: mouse.pressed
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: Qt.PointingHandCursor
id: mouse
property real pressStartX
property real pressStartPos
property real dragMovement
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
preventStealing: true
implicitHeight: handle.implicitHeight
onPressed: e => {
widthBehavior.enabled = false;
pressStartX = e.x;
pressStartPos = root.visualPosition;
}
onPositionChanged: e => {
dragMovement = (e.x - pressStartX) / width;
root.interaction(posBinding.value);
}
onReleased: e => {
root.interaction(posBinding.value);
widthBehavior.enabled = true;
dragMovement = 0;
}
}
Behavior on filledWidth {
id: widthBehavior
Anim {}
}
}

View file

@ -18,17 +18,17 @@ Switch {
color: root.checked ? Colours.palette.m3primary : Colours.layer(Colours.palette.m3surfaceContainerHighest, root.cLayer)
implicitWidth: implicitHeight * 1.7
implicitHeight: Tokens.font.size.normal + Tokens.padding.smaller * 2
implicitHeight: Tokens.font.body.medium.pointSize + Tokens.padding.small * 2
StyledRect {
readonly property real nonAnimWidth: root.pressed ? implicitHeight * 1.3 : implicitHeight
readonly property real nonAnimWidth: root.pressed ? implicitHeight * 1.2 : implicitHeight
radius: Tokens.rounding.full
color: root.checked ? Colours.palette.m3onPrimary : Colours.layer(Colours.palette.m3outline, root.cLayer + 1)
x: root.checked ? parent.implicitWidth - nonAnimWidth - Tokens.padding.small / 2 : Tokens.padding.small / 2
x: root.checked ? parent.implicitWidth - nonAnimWidth - Tokens.padding.extraSmall / 2 : Tokens.padding.extraSmall / 2
implicitWidth: nonAnimWidth
implicitHeight: parent.implicitHeight - Tokens.padding.small
implicitHeight: parent.implicitHeight - Tokens.padding.extraSmall
anchors.verticalCenter: parent.verticalCenter
StyledRect {
@ -39,7 +39,9 @@ Switch {
opacity: root.pressed ? 0.1 : root.hovered ? 0.08 : 0
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
@ -83,12 +85,12 @@ Switch {
anchors.centerIn: parent
width: height
height: parent.implicitHeight - Tokens.padding.small * 2
height: parent.implicitHeight - Tokens.padding.medium
preferredRendererType: Shape.CurveRenderer
asynchronous: true
ShapePath {
strokeWidth: root.Tokens.font.size.larger * 0.15
strokeWidth: root.Tokens.font.body.large.pointSize * 0.15
strokeColor: root.checked ? Colours.palette.m3primary : Colours.palette.m3surfaceContainerHighest
fillColor: "transparent"
capStyle: root.Tokens.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap
@ -129,11 +131,15 @@ Switch {
}
Behavior on x {
Anim {}
Anim {
type: Anim.FastSpatial
}
}
Behavior on implicitWidth {
Anim {}
Anim {
type: Anim.FastSpatial
}
}
}
}
@ -145,7 +151,7 @@ Switch {
}
component PropAnim: PropertyAnimation {
duration: Tokens.anim.durations.normal
easing: Tokens.anim.standard
duration: Tokens.anim.durations.expressiveFastSpatial
easing: Tokens.anim.expressiveFastSpatial
}
}

View file

@ -11,8 +11,7 @@ TextField {
color: Colours.palette.m3onSurface
placeholderTextColor: Colours.palette.m3outline
font.family: Tokens.font.family.sans
font.pointSize: Tokens.font.size.smaller
font: Tokens.font.body.small
renderType: echoMode === TextField.Password ? TextField.QtRendering : TextField.NativeRendering
cursorVisible: !readOnly
@ -25,7 +24,7 @@ TextField {
implicitWidth: 2
color: Colours.palette.m3primary
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
Connections {
function onCursorPositionChanged(): void {

View file

@ -13,8 +13,8 @@ StyledRect {
signal toggled(checked: bool)
Layout.fillWidth: true
implicitHeight: row.implicitHeight + Tokens.padding.large * 2
radius: Tokens.rounding.normal
implicitHeight: row.implicitHeight + Tokens.padding.extraLargeIncreased
radius: Tokens.rounding.large
color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
Behavior on implicitHeight {
@ -28,7 +28,7 @@ StyledRect {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
Layout.fillWidth: true

View file

@ -3,75 +3,41 @@ import Caelestia.Config
import qs.components
import qs.services
StyledRect {
ButtonBase {
id: root
enum Type {
Filled,
Tonal,
Text
}
property alias text: label.text
property bool checked
property bool toggle
property real horizontalPadding: Tokens.padding.normal
property real verticalPadding: Tokens.padding.smaller
property alias font: label.font
property int type: TextButton.Filled
readonly property alias label: label
property alias stateLayer: stateLayer
property alias label: label
horizontalPadding: Tokens.padding.medium
verticalPadding: Tokens.padding.small
property bool internalChecked
property color activeColour: type === TextButton.Filled ? Colours.palette.m3primary : Colours.palette.m3secondary
property color inactiveColour: {
if (!toggle && type === TextButton.Filled)
activeColour: type === TextButton.Filled ? Colours.palette.m3primary : Colours.palette.m3secondary
inactiveColour: {
if (!isToggle && type === TextButton.Filled)
return Colours.palette.m3primary;
return type === TextButton.Filled ? Colours.tPalette.m3surfaceContainer : Colours.palette.m3secondaryContainer;
}
property color activeOnColour: {
activeOnColour: {
if (type === TextButton.Text)
return Colours.palette.m3primary;
return type === TextButton.Filled ? Colours.palette.m3onPrimary : Colours.palette.m3onSecondary;
}
property color inactiveOnColour: {
if (!toggle && type === TextButton.Filled)
inactiveOnColour: {
if (!isToggle && type === TextButton.Filled)
return Colours.palette.m3onPrimary;
if (type === TextButton.Text)
return Colours.palette.m3primary;
return type === TextButton.Filled ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer;
}
signal clicked
onCheckedChanged: internalChecked = checked
radius: internalChecked ? Tokens.rounding.small : implicitHeight / 2 * Math.min(1, Tokens.rounding.scale)
color: type === TextButton.Text ? "transparent" : internalChecked ? activeColour : inactiveColour
implicitWidth: label.implicitWidth + horizontalPadding * 2
implicitHeight: label.implicitHeight + verticalPadding * 2
StateLayer {
id: stateLayer
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
onClicked: {
if (root.toggle)
root.internalChecked = !root.internalChecked;
root.clicked();
}
}
StyledText {
id: label
anchors.centerIn: parent
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
}
Behavior on radius {
Anim {}
color: root.onColour
}
}

View file

@ -14,9 +14,9 @@ StyledRect {
property string icon
property string label
property string accent: "Secondary"
property real iconSize: Tokens.font.size.large
property real iconSize: Tokens.font.icon.large.pointSize
property real horizontalPadding: Tokens.padding.large
property real verticalPadding: Tokens.padding.normal
property real verticalPadding: Tokens.padding.medium
property string tooltip: ""
property bool hovered: false
@ -24,10 +24,10 @@ StyledRect {
Component.onCompleted: hovered = toggleStateLayer.containsMouse
Layout.preferredWidth: implicitWidth + (toggleStateLayer.pressed ? Tokens.padding.normal * 2 : toggled ? Tokens.padding.small * 2 : 0)
Layout.preferredWidth: implicitWidth + (toggleStateLayer.pressed ? Tokens.padding.medium * 2 : toggled ? Tokens.padding.small : 0)
implicitWidth: toggleBtnInner.implicitWidth + horizontalPadding * 2
implicitHeight: toggleBtnIcon.implicitHeight + verticalPadding * 2
radius: toggled || toggleStateLayer.pressed ? Tokens.rounding.small : Math.min(width, height) / 2 * Math.min(1, Tokens.rounding.scale)
radius: toggled || toggleStateLayer.pressed ? Tokens.rounding.medium : Math.min(width, height) / 2 * Math.min(1, Tokens.rounding.scale)
color: toggled ? Colours.palette[`m3${accent.toLowerCase()}`] : Colours.palette[`m3${accent.toLowerCase()}Container`]
Connections {
@ -52,7 +52,7 @@ StyledRect {
id: toggleBtnInner
anchors.centerIn: parent
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
MaterialIcon {
id: toggleBtnIcon
@ -61,10 +61,12 @@ StyledRect {
fill: root.toggled ? 1 : 0
text: root.icon
color: root.toggled ? Colours.palette[`m3on${root.accent}`] : Colours.palette[`m3on${root.accent}Container`]
font.pointSize: root.iconSize
fontStyle: Tokens.font.icon.size(root.iconSize).build()
Behavior on fill {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}

View file

@ -12,7 +12,7 @@ RowLayout {
property alias toggle: toggle
Layout.fillWidth: true
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
Layout.fillWidth: true

View file

@ -47,7 +47,7 @@ Popup {
let newY = targetPos.y - tooltipHeight - Tokens.spacing.small;
// Keep within bounds
const padding = Tokens.padding.normal;
const padding = Tokens.padding.medium;
if (newX < padding) {
newX = padding;
} else if (newX + tooltipWidth > (parent.width - padding)) {
@ -116,11 +116,11 @@ Popup {
contentItem: StyledRect {
id: tooltipRect
implicitWidth: tooltipText.implicitWidth + Tokens.padding.normal * 2
implicitHeight: tooltipText.implicitHeight + Tokens.padding.smaller * 2
implicitWidth: tooltipText.implicitWidth + Tokens.padding.medium * 2
implicitHeight: tooltipText.implicitHeight + Tokens.padding.large
color: Colours.palette.m3surfaceContainerHighest
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
antialiasing: true
// Add elevation for depth
@ -138,7 +138,7 @@ Popup {
text: root.text
color: Colours.palette.m3onSurface
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
}

View file

@ -13,6 +13,8 @@ RectangularShadow {
offset.y: dp / 2
Behavior on dp {
Anim {}
Anim {
type: Anim.SlowEffects
}
}
}

View file

@ -37,8 +37,8 @@ StyledRect {
id: maskInner
anchors.fill: parent
anchors.margins: Tokens.padding.normal
radius: Tokens.rounding.normal
anchors.margins: Tokens.padding.medium
radius: Tokens.rounding.large
}
}
}

View file

@ -0,0 +1,7 @@
import QtQuick.Effects
MultiEffect {
maskEnabled: true
maskSpreadAtMin: 1
maskThresholdMin: 0.5
}

View file

@ -1,9 +0,0 @@
import QtQuick
import Quickshell
ShaderEffect {
required property Item source
required property Item maskSource
fragmentShader: Quickshell.shellPath("assets/shaders/opacitymask.frag.qsb")
}

View file

@ -9,8 +9,8 @@ Item {
required property var currentItem
implicitWidth: content.implicitWidth + Tokens.padding.larger + content.anchors.rightMargin
implicitHeight: currentItem ? content.implicitHeight + Tokens.padding.normal + content.anchors.bottomMargin : 0
implicitWidth: content.implicitWidth + Tokens.padding.medium + content.anchors.rightMargin
implicitHeight: currentItem ? content.implicitHeight + Tokens.padding.medium + content.anchors.bottomMargin : 0
Shape {
preferredRendererType: Shape.CurveRenderer
@ -18,7 +18,7 @@ Item {
ShapePath {
id: path
readonly property real rounding: Tokens.rounding.small
readonly property real rounding: root.Tokens.rounding.medium
readonly property bool flatten: root.implicitHeight < rounding * 2
readonly property real roundingY: flatten ? root.implicitHeight / 2 : rounding
@ -76,8 +76,8 @@ Item {
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: Tokens.padding.larger - Tokens.padding.small
anchors.bottomMargin: Tokens.padding.normal - Tokens.padding.small
anchors.rightMargin: Tokens.padding.medium - Tokens.padding.extraSmall
anchors.bottomMargin: Tokens.padding.medium - Tokens.padding.extraSmall
Connections {
function onCurrentItemChanged(): void {

View file

@ -9,7 +9,7 @@ StyledRect {
required property var dialog
required property FolderContents folder
implicitHeight: inner.implicitHeight + Tokens.padding.normal * 2
implicitHeight: inner.implicitHeight + Tokens.padding.medium * 2
color: Colours.tPalette.m3surfaceContainer
@ -17,7 +17,7 @@ StyledRect {
id: inner
anchors.fill: parent
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
spacing: Tokens.spacing.small
@ -28,14 +28,14 @@ StyledRect {
StyledRect {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.rightMargin: Tokens.spacing.normal
Layout.rightMargin: Tokens.spacing.medium
color: Colours.tPalette.m3surfaceContainerHigh
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
StyledText {
anchors.fill: parent
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
text: `${root.dialog.filterLabel} (${root.dialog.filters.map(f => `*.${f}`).join(", ")})`
}
@ -43,10 +43,10 @@ StyledRect {
StyledRect {
color: Colours.tPalette.m3surfaceContainerHigh
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
implicitWidth: cancelText.implicitWidth + Tokens.padding.normal * 2
implicitHeight: cancelText.implicitHeight + Tokens.padding.normal * 2
implicitWidth: cancelText.implicitWidth + Tokens.padding.medium * 2
implicitHeight: cancelText.implicitHeight + Tokens.padding.medium * 2
StateLayer {
disabled: !root.dialog.selectionValid
@ -57,7 +57,7 @@ StyledRect {
id: selectText
anchors.centerIn: parent
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
text: qsTr("Select")
color: root.dialog.selectionValid ? Colours.palette.m3onSurface : Colours.palette.m3outline
@ -66,10 +66,10 @@ StyledRect {
StyledRect {
color: Colours.tPalette.m3surfaceContainerHigh
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
implicitWidth: cancelText.implicitWidth + Tokens.padding.normal * 2
implicitHeight: cancelText.implicitHeight + Tokens.padding.normal * 2
implicitWidth: cancelText.implicitWidth + Tokens.padding.medium * 2
implicitHeight: cancelText.implicitHeight + Tokens.padding.medium * 2
StateLayer {
onClicked: {
@ -81,7 +81,7 @@ StyledRect {
id: cancelText
anchors.centerIn: parent
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
text: qsTr("Cancel")
}

View file

@ -1,13 +1,13 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell
import Caelestia.Config
import Caelestia.Models
import qs.components
import qs.components.controls
import qs.components.effects
import qs.components.filedialog
import qs.components.images
import qs.services
@ -24,12 +24,9 @@ Item {
color: Colours.tPalette.m3surfaceContainer
layer.enabled: true
layer.effect: MultiEffect {
layer.effect: Mask {
maskSource: mask
maskEnabled: true
maskInverted: true
maskThresholdMin: 0.5
maskSpreadAtMin: 1
}
}
@ -42,8 +39,8 @@ Item {
Rectangle {
anchors.fill: parent
anchors.margins: Tokens.padding.small
radius: Tokens.rounding.small
anchors.margins: Tokens.padding.extraSmall
radius: Tokens.rounding.medium
}
}
@ -59,20 +56,20 @@ Item {
Layout.alignment: Qt.AlignHCenter
text: "scan_delete"
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.extraLarge * 2
font.weight: 500
fontStyle: Tokens.font.icon.builders.extraLarge.scale(2).weight(Font.Medium).build()
}
StyledText {
text: qsTr("This folder is empty")
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.large
font.weight: 500
font: Tokens.font.body.builders.large.weight(Font.Medium).build()
}
}
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
@ -80,10 +77,10 @@ Item {
id: view
anchors.fill: parent
anchors.margins: Tokens.padding.small + Tokens.padding.normal
anchors.margins: Tokens.padding.extraSmall + Tokens.padding.medium
cellWidth: Sizes.itemWidth + Tokens.spacing.small
cellHeight: Sizes.itemWidth + Tokens.spacing.small * 2 + Tokens.padding.normal * 2 + 1
cellHeight: Sizes.itemWidth + Tokens.spacing.large + Tokens.padding.medium * 2 + 1
clip: true
focus: true
@ -120,12 +117,12 @@ Item {
properties: "opacity,scale"
from: 0
to: 1
type: Anim.DefaultSpatial
}
}
remove: Transition {
Anim {
type: Anim.DefaultEffects
property: "opacity"
to: 0
}
@ -137,13 +134,13 @@ Item {
displaced: Transition {
Anim {
type: Anim.DefaultEffects
properties: "opacity,scale"
to: 1
easing: Tokens.anim.standardDecel
}
Anim {
properties: "x,y"
type: Anim.DefaultSpatial
}
}
}
@ -151,7 +148,7 @@ Item {
CurrentItem {
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: Tokens.padding.small
anchors.margins: Tokens.padding.extraSmall
currentItem: view.currentItem
}
@ -162,12 +159,12 @@ Item {
required property int index
required property FileSystemEntry modelData
readonly property real nonAnimHeight: icon.implicitHeight + name.anchors.topMargin + name.implicitHeight + Tokens.padding.normal * 2
readonly property real nonAnimHeight: icon.implicitHeight + name.anchors.topMargin + name.implicitHeight + Tokens.padding.medium * 2
implicitWidth: Sizes.itemWidth
implicitHeight: nonAnimHeight
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
color: Qt.alpha(Colours.tPalette.m3surfaceContainerHighest, GridView.isCurrentItem ? Colours.tPalette.m3surfaceContainerHighest.a : 0)
z: GridView.isCurrentItem || implicitHeight !== nonAnimHeight ? 1 : 0
clip: true
@ -187,9 +184,9 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: Tokens.padding.normal
anchors.topMargin: Tokens.padding.medium
implicitSize: Sizes.itemWidth - Tokens.padding.normal * 2
implicitSize: Sizes.itemWidth - Tokens.padding.medium * 2
Component.onCompleted: {
const file = item.modelData;
@ -211,7 +208,7 @@ Item {
anchors.right: parent.right
anchors.top: icon.bottom
anchors.topMargin: Tokens.spacing.small
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
horizontalAlignment: Text.AlignHCenter
elide: item.GridView.isCurrentItem ? Text.ElideNone : Text.ElideRight

View file

@ -11,8 +11,8 @@ StyledRect {
required property var dialog
implicitWidth: inner.implicitWidth + Tokens.padding.normal * 2
implicitHeight: inner.implicitHeight + Tokens.padding.normal * 2
implicitWidth: inner.implicitWidth + Tokens.padding.medium * 2
implicitHeight: inner.implicitHeight + Tokens.padding.medium * 2
color: Colours.tPalette.m3surfaceContainer
@ -20,15 +20,15 @@ StyledRect {
id: inner
anchors.fill: parent
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
spacing: Tokens.spacing.small
Item {
implicitWidth: implicitHeight
implicitHeight: upIcon.implicitHeight + Tokens.padding.small * 2
implicitHeight: upIcon.implicitHeight + Tokens.padding.small
StateLayer {
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
disabled: root.dialog.cwd.length === 1
onClicked: root.dialog.cwd.pop()
}
@ -46,7 +46,7 @@ StyledRect {
StyledRect {
Layout.fillWidth: true
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
color: Colours.tPalette.m3surfaceContainerHigh
implicitHeight: pathComponents.implicitHeight + pathComponents.anchors.margins * 2
@ -55,7 +55,7 @@ StyledRect {
id: pathComponents
anchors.fill: parent
anchors.margins: Tokens.padding.small / 2
anchors.margins: Tokens.padding.extraSmall / 2
anchors.leftMargin: 0
spacing: Tokens.spacing.small
@ -78,13 +78,13 @@ StyledRect {
sourceComponent: StyledText {
text: "/"
color: Colours.palette.m3onSurfaceVariant
font.bold: true
font: Tokens.font.body.builders.small.weight(Font.Bold).build()
}
}
Item {
implicitWidth: homeIcon.implicitWidth + (homeIcon.active ? Tokens.padding.small : 0) + folderName.implicitWidth + Tokens.padding.normal * 2
implicitHeight: folderName.implicitHeight + Tokens.padding.small * 2
implicitWidth: homeIcon.implicitWidth + (homeIcon.active ? Tokens.padding.extraSmall : 0) + folderName.implicitWidth + Tokens.padding.medium * 2
implicitHeight: folderName.implicitHeight + Tokens.padding.small
Loader {
asynchronous: true
@ -95,7 +95,7 @@ StyledRect {
root.dialog.cwd = root.dialog.cwd.slice(0, folder.index + 1);
}
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
}
}
@ -106,7 +106,7 @@ StyledRect {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Tokens.padding.normal
anchors.leftMargin: Tokens.padding.medium
active: folder.index === 0 && folder.modelData === "Home"
sourceComponent: MaterialIcon {
@ -121,11 +121,11 @@ StyledRect {
anchors.left: homeIcon.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: homeIcon.active ? Tokens.padding.small : 0
anchors.leftMargin: homeIcon.active ? Tokens.padding.extraSmall : 0
text: folder.modelData
color: folder.index < root.dialog.cwd.length - 1 ? Colours.palette.m3onSurfaceVariant : Colours.palette.m3onSurface
font.bold: true
font: Tokens.font.body.builders.small.weight(Font.Bold).build()
}
}
}

View file

@ -13,7 +13,7 @@ StyledRect {
required property var dialog
implicitWidth: Sizes.sidebarWidth
implicitHeight: inner.implicitHeight + Tokens.padding.normal * 2
implicitHeight: inner.implicitHeight + Tokens.padding.medium * 2
color: Colours.tPalette.m3surfaceContainer
@ -23,17 +23,16 @@ StyledRect {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Tokens.padding.normal
spacing: Tokens.spacing.small / 2
anchors.margins: Tokens.padding.medium
spacing: Tokens.spacing.extraSmall
StyledText {
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: Tokens.padding.small / 2
Layout.bottomMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.padding.extraSmall / 2
Layout.bottomMargin: Tokens.spacing.medium
text: qsTr("Files")
color: Colours.palette.m3onSurface
font.pointSize: Tokens.font.size.larger
font.bold: true
font: Tokens.font.body.builders.large.weight(Font.Bold).build()
}
Repeater {
@ -46,7 +45,7 @@ StyledRect {
readonly property bool selected: modelData === root.dialog.cwd[root.dialog.cwd.length - 1]
Layout.fillWidth: true
implicitHeight: placeInner.implicitHeight + Tokens.padding.normal * 2
implicitHeight: placeInner.implicitHeight + Tokens.padding.medium * 2
radius: Tokens.rounding.full
color: Qt.alpha(Colours.palette.m3secondaryContainer, selected ? 1 : 0)
@ -65,11 +64,11 @@ StyledRect {
id: placeInner
anchors.fill: parent
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
anchors.leftMargin: Tokens.padding.large
anchors.rightMargin: Tokens.padding.large
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
MaterialIcon {
text: {
@ -91,11 +90,13 @@ StyledRect {
return "folder";
}
color: place.selected ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
fill: place.selected ? 1 : 0
Behavior on fill {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
@ -103,7 +104,7 @@ StyledRect {
Layout.fillWidth: true
text: place.modelData
color: place.selected ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
font.pointSize: Tokens.font.size.normal
font: Tokens.font.body.medium
elide: Text.ElideRight
}
}

View file

@ -0,0 +1,56 @@
import QtQuick
import Quickshell
import qs.components
Image {
id: root
property bool hadPrevious
function maybeStartInAnim(): void {
if (!opacityInAnim.running && status === Image.Ready) {
opacityInAnim.type = hadPrevious ? Anim.DefaultEffects : Anim.StandardLarge;
opacityInAnim.start();
}
}
asynchronous: true
fillMode: Image.PreserveAspectCrop
sourceSize: {
const dpr = (QsWindow.window as QsWindow)?.devicePixelRatio ?? 1;
return Qt.size(width * dpr, height * dpr);
}
retainWhileLoading: true
opacity: 0
onStatusChanged: maybeStartInAnim()
Anim on opacity {
id: opacityInAnim
running: false
to: 1
}
Behavior on source {
SequentialAnimation {
Anim {
target: root
property: "opacity"
to: 0
type: Anim.FastEffects
}
PropertyAction {
target: root
property: "hadPrevious"
value: root.source
}
PropertyAction {}
ScriptAction {
script: root.maybeStartInAnim()
}
}
}
}

View file

@ -0,0 +1,107 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Effects
import M3Shapes
import Caelestia.Config
import qs.components
import qs.components.controls
import qs.components.effects
import qs.components.images
import qs.services
Item {
id: root
readonly property alias shape: shape
property bool hadPrevious
property color fallbackColour: Colours.layer(Colours.palette.m3surfaceContainerHighest, 2)
// Slight glow to separate from bg
layer.enabled: true
layer.effect: MultiEffect {
shadowEnabled: true
blurMax: 1
shadowColor: Colours.palette.m3outline
shadowOpacity: 0.3
}
Behavior on fallbackColour {
CAnim {}
}
Item {
id: shapeWrapper
anchors.fill: parent
layer.enabled: true
opacity: root.fallbackColour.a
MaterialShape {
id: shape
implicitSize: root.width
shape: MaterialShape.Cookie12Sided
color: Qt.alpha(root.fallbackColour, 1)
Anim on rotation {
running: true
paused: !Players.active?.isPlaying
from: 360
to: 0
duration: 23500
easing.type: Easing.Linear
loops: Animation.Infinite
}
}
}
MaterialIcon {
anchors.centerIn: parent
grade: 200
text: image.status === Image.Error ? "broken_image" : "art_track"
color: Colours.palette.m3onSurfaceVariant
fontStyle: Tokens.font.icon.size((parent.width * 0.35) || 1).build()
opacity: image.status === Image.Null || image.status === Image.Error ? 1 : 0
animate: true
Behavior on opacity {
Anim {
type: Anim.DefaultEffects
}
}
}
Loader {
anchors.centerIn: parent
asynchronous: true
active: opacity > 0
opacity: image.status === Image.Loading ? 1 : 0
sourceComponent: LoadingIndicator {
implicitSize: root.width * 0.3
color: Colours.palette.m3primaryContainer
}
Behavior on opacity {
Anim {
type: Anim.DefaultEffects
}
}
}
FadeImage {
id: image
anchors.fill: parent
source: Players.getArtUrl(Players.active)
layer.enabled: true
layer.effect: Mask {
maskSource: shapeWrapper
}
}
}

View file

@ -8,13 +8,13 @@ StyledRect {
required property int extra
anchors.right: parent.right
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
color: Colours.palette.m3tertiary
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
implicitWidth: count.implicitWidth + Tokens.padding.normal * 2
implicitHeight: count.implicitHeight + Tokens.padding.small * 2
implicitWidth: count.implicitWidth + Tokens.padding.medium * 2
implicitHeight: count.implicitHeight + Tokens.padding.small
opacity: extra > 0 ? 1 : 0
scale: extra > 0 ? 1 : 0.5
@ -38,6 +38,7 @@ StyledRect {
Behavior on opacity {
Anim {
type: Anim.DefaultEffects
duration: Tokens.anim.durations.expressiveFastSpatial
}
}

View file

@ -0,0 +1,47 @@
import QtQuick
import QtQuick.Shapes
import qs.components
import qs.services
Shape {
id: root
property color color: Colours.palette.m3surfaceContainer
property int waves: 4
property real amplitude: 3
readonly property real waveHeight: amplitude * 2
preferredRendererType: Shape.CurveRenderer
asynchronous: true
ShapePath {
strokeWidth: 0
strokeColor: "transparent"
fillColor: root.color
PathSvg {
path: {
const w = root.width;
const h = root.height;
const a = root.amplitude;
const n = Math.max(1, root.waves);
const wl = w / n;
const half = wl / 2;
let d = `M 0,${a} `;
for (let i = 0; i < n; ++i) {
const x = i * wl;
d += `Q ${x + half / 2},${-a} ${x + half},${a} `;
d += `Q ${x + half + half / 2},${3 * a} ${x + wl},${a} `;
}
d += `L ${w},${h} L 0,${h} Z`;
return d;
}
}
Behavior on fillColor {
CAnim {}
}
}
}

6
modules/GSFLoader.qml Normal file
View file

@ -0,0 +1,6 @@
import QtQuick
import Quickshell
FontLoader {
source: Quickshell.shellPath("assets/google-sans-flex/GoogleSansFlex-VariableFont_GRAD,ROND,opsz,slnt,wdth,wght.ttf")
}

View file

@ -1,12 +1,12 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Effects
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import Caelestia
import qs.components
import qs.components.effects
import qs.services
MouseArea {
@ -168,17 +168,17 @@ MouseArea {
to: 0
type: Anim.StandardLarge
}
ExAnim {
Anim {
target: root
properties: "rsx,rsy"
to: 0
}
ExAnim {
Anim {
target: root
property: "sw"
to: root.screen.width
}
ExAnim {
Anim {
target: root
property: "sh"
to: root.screen.height
@ -230,12 +230,9 @@ MouseArea {
opacity: 0.3
layer.enabled: true
layer.effect: MultiEffect {
layer.effect: Mask {
maskSource: selectionWrapper
maskEnabled: true
maskInverted: true
maskSpreadAtMin: 1
maskThresholdMin: 0.5
}
}
@ -284,28 +281,24 @@ MouseArea {
Behavior on rsx {
enabled: !root.pressed
ExAnim {}
Anim {}
}
Behavior on rsy {
enabled: !root.pressed
ExAnim {}
Anim {}
}
Behavior on sw {
enabled: !root.pressed
ExAnim {}
Anim {}
}
Behavior on sh {
enabled: !root.pressed
ExAnim {}
}
component ExAnim: Anim {
type: Anim.DefaultSpatial
Anim {}
}
}

View file

@ -57,8 +57,8 @@ Variants {
asynchronous: true
active: Config.background.desktopClock.enabled
anchors.margins: Tokens.padding.large * 2
anchors.leftMargin: Tokens.padding.large * 2 + Tokens.sizes.bar.innerWidth + Math.max(Tokens.padding.smaller, Config.border.thickness)
anchors.margins: Tokens.padding.extraLargeIncreased
anchors.leftMargin: Tokens.padding.extraLargeIncreased + Tokens.sizes.bar.innerWidth + Math.max(Tokens.padding.small, Config.border.thickness)
state: Config.background.desktopClock.position
states: [

View file

@ -24,7 +24,7 @@ Item {
readonly property color safeTertiary: useLightSet ? Colours.palette.m3tertiaryContainer : Colours.palette.m3tertiary
implicitWidth: layout.implicitWidth + (Tokens.padding.large * 4 * root.clockScale)
implicitHeight: layout.implicitHeight + (Tokens.padding.large * 2 * root.clockScale)
implicitHeight: layout.implicitHeight + (Tokens.padding.extraLargeIncreased * root.clockScale)
Item {
id: clockContainer
@ -63,7 +63,7 @@ Item {
visible: root.bgEnabled
anchors.fill: parent
radius: Tokens.rounding.large * root.clockScale
radius: Tokens.rounding.extraLarge * root.clockScale
opacity: Config.background.desktopClock.background.opacity
color: Colours.palette.m3surface
@ -74,21 +74,20 @@ Item {
id: layout
anchors.centerIn: parent
spacing: Tokens.spacing.larger * root.clockScale
spacing: Tokens.spacing.large * root.clockScale
RowLayout {
spacing: Tokens.spacing.small
StyledText {
text: Time.hourStr
font.pointSize: Tokens.font.size.extraLarge * 3 * root.clockScale
font.weight: Font.Bold
font: Tokens.font.clock.size(Tokens.font.headline.medium.pointSize * 3 * root.clockScale).weight(Font.Bold).build()
color: root.safePrimary
}
StyledText {
text: ":"
font.pointSize: Tokens.font.size.extraLarge * 3 * root.clockScale
font: Tokens.font.clock.size(Tokens.font.headline.medium.pointSize * 3 * root.clockScale).build()
color: root.safeTertiary
opacity: 0.8
Layout.topMargin: -Tokens.padding.large * 1.5 * root.clockScale
@ -96,8 +95,7 @@ Item {
StyledText {
text: Time.minuteStr
font.pointSize: Tokens.font.size.extraLarge * 3 * root.clockScale
font.weight: Font.Bold
font: Tokens.font.clock.size(Tokens.font.headline.medium.pointSize * 3 * root.clockScale).weight(Font.Bold).build()
color: root.safeSecondary
}
@ -111,7 +109,7 @@ Item {
sourceComponent: StyledText {
text: Time.amPmStr
font.pointSize: Tokens.font.size.large * root.clockScale
font: Tokens.font.clock.size(Tokens.font.title.medium.pointSize * root.clockScale).build()
color: root.safeSecondary
}
}
@ -120,8 +118,8 @@ Item {
StyledRect {
Layout.fillHeight: true
Layout.preferredWidth: 4 * root.clockScale
Layout.topMargin: Tokens.spacing.larger * root.clockScale
Layout.bottomMargin: Tokens.spacing.larger * root.clockScale
Layout.topMargin: Tokens.spacing.large * root.clockScale
Layout.bottomMargin: Tokens.spacing.large * root.clockScale
radius: Tokens.rounding.full
color: root.safePrimary
opacity: 0.8
@ -132,24 +130,19 @@ Item {
StyledText {
text: Time.format("MMMM").toUpperCase()
font.pointSize: Tokens.font.size.large * root.clockScale
font.letterSpacing: 4
font.weight: Font.Bold
font: Tokens.font.clock.size(Tokens.font.title.medium.pointSize * root.clockScale).letterSpacing(4).weight(Font.Bold).build()
color: root.safeSecondary
}
StyledText {
text: Time.format("dd")
font.pointSize: Tokens.font.size.extraLarge * root.clockScale
font.letterSpacing: 2
font.weight: Font.Medium
font: Tokens.font.clock.size(Tokens.font.headline.medium.pointSize * root.clockScale).letterSpacing(2).weight(Font.Medium).build()
color: root.safePrimary
}
StyledText {
text: Time.format("dddd")
font.pointSize: Tokens.font.size.larger * root.clockScale
font.letterSpacing: 2
font: Tokens.font.clock.size(Tokens.font.body.large.pointSize * root.clockScale).letterSpacing(2).build()
color: root.safeSecondary
}
}
@ -157,9 +150,7 @@ Item {
}
Behavior on clockScale {
Anim {
type: Anim.DefaultSpatial
}
Anim {}
}
Behavior on implicitWidth {

View file

@ -65,8 +65,8 @@ Item {
values: Audio.cava.values
primaryColor: Qt.alpha(Colours.palette.m3primary, 0.7)
secondaryColor: Qt.alpha(Colours.palette.m3inversePrimary, 0.7)
rounding: Tokens.rounding.small * Config.background.visualiser.rounding
spacing: Tokens.spacing.small * Config.background.visualiser.spacing
rounding: Tokens.rounding.medium * Config.background.visualiser.rounding
spacing: Tokens.spacing.extraSmall * Config.background.visualiser.spacing
animationDuration: Tokens.anim.durations.normal
Behavior on anchors.leftMargin {
@ -87,6 +87,8 @@ Item {
}
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}

View file

@ -12,22 +12,24 @@ Item {
id: root
property string source: Wallpapers.current
property Image current: one
property CachingImage current
property bool completed
onSourceChanged: {
if (!source)
current = null;
else if (current === one)
two.update();
else
one.update();
current = imgComp.createObject(this, {
path: source
});
}
Component.onCompleted: {
if (source)
Qt.callLater(() => {
one.update();
current = imgComp.createObject(this, {
path: source
});
completed = true;
});
}
@ -43,12 +45,12 @@ Item {
Row {
anchors.centerIn: parent
spacing: Tokens.spacing.large
spacing: Tokens.spacing.largeIncreased
MaterialIcon {
text: "sentiment_stressed"
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.extraLarge * 5
fontStyle: Tokens.font.icon.builders.extraLarge.scale(5).build()
}
Column {
@ -58,13 +60,12 @@ Item {
StyledText {
text: qsTr("Wallpaper missing?")
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.extraLarge * 2
font.bold: true
font: Tokens.font.body.builders.large.size(28 * 2).weight(Font.Bold).build()
}
StyledRect {
implicitWidth: selectWallText.implicitWidth + Tokens.padding.large * 2
implicitHeight: selectWallText.implicitHeight + Tokens.padding.small * 2
implicitWidth: selectWallText.implicitWidth + Tokens.padding.extraLargeIncreased
implicitHeight: selectWallText.implicitHeight + Tokens.padding.small
radius: Tokens.rounding.full
color: Colours.palette.m3primary
@ -91,7 +92,7 @@ Item {
text: qsTr("Set it now!")
color: Colours.palette.m3onPrimary
font.pointSize: Tokens.font.size.large
font: Tokens.font.body.large
}
}
}
@ -99,48 +100,34 @@ Item {
}
}
Img {
id: one
}
Component {
id: imgComp
Img {
id: two
}
component Img: CachingImage {
CachingImage {
id: img
function update(): void {
if (path === root.source)
root.current = this;
else
path = root.source;
}
anchors.fill: parent
opacity: 0
scale: Wallpapers.showPreview ? 1 : 0.8
onStatusChanged: {
if (status === Image.Ready)
root.current = this;
anim.start();
}
states: State {
name: "visible"
when: root.current === img
Anim on opacity {
id: anim
PropertyChanges {
img.opacity: 1
img.scale: 1
}
type: Anim.SlowEffects
running: false
from: 0
to: 1
}
transitions: Transition {
Anim {
target: img
properties: "opacity,scale"
Timer {
running: root.current !== img && root.current?.status === Image.Ready
interval: anim.duration
onTriggered: img.destroy()
}
}
}

View file

@ -102,7 +102,7 @@ ColumnLayout {
}
}
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
Repeater {
id: repeater

View file

@ -18,7 +18,7 @@ Item {
readonly property bool disabled: Strings.testRegexList(Config.bar.excludedScreens, screen.name)
readonly property int clampedWidth: Math.max(Config.border.minThickness, implicitWidth)
readonly property int padding: Math.max(Tokens.padding.smaller, Config.border.thickness)
readonly property int padding: Math.max(Tokens.padding.small, Config.border.thickness)
readonly property int contentWidth: Tokens.sizes.bar.innerWidth + padding * 2
readonly property int exclusiveZone: !disabled && (Config.bar.persistent || visibilities.bar) ? contentWidth : Config.border.thickness
readonly property bool shouldBeVisible: !fullscreen && !disabled && (Config.bar.persistent || visibilities.bar || isHovered)
@ -57,7 +57,6 @@ Item {
Anim {
target: root
property: "implicitWidth"
type: Anim.DefaultSpatial
}
},
Transition {

View file

@ -86,8 +86,7 @@ Item {
id: metrics
text: root.windowTitle
font.pointSize: root.Tokens.font.size.smaller
font.family: root.Tokens.font.family.mono
font: root.Tokens.font.body.builders.small.letterSpacing(1.4).build()
elide: Qt.ElideRight
elideWidth: root.maxHeight - icon.height
@ -100,9 +99,7 @@ Item {
}
Behavior on implicitHeight {
Anim {
type: Anim.DefaultSpatial
}
Anim {}
}
component Title: StyledText {
@ -112,8 +109,7 @@ Item {
anchors.top: icon.bottom
anchors.topMargin: Tokens.spacing.small
font.pointSize: metrics.font.pointSize
font.family: metrics.font.family
font: metrics.font
color: root.colour
opacity: root.current === this ? 1 : 0
@ -132,7 +128,9 @@ Item {
height: implicitWidth
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
}

View file

@ -1,6 +1,7 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Caelestia.Config
import qs.components
import qs.services
@ -9,7 +10,8 @@ StyledRect {
id: root
readonly property color colour: Colours.palette.m3tertiary
readonly property int padding: Config.bar.clock.background ? Tokens.padding.normal : Tokens.padding.small
readonly property int padding: Config.bar.clock.background ? Tokens.padding.medium : Tokens.padding.extraSmall
readonly property var font: Tokens.font.body.builders.small.scale(1.1)
implicitWidth: Tokens.sizes.bar.innerWidth
implicitHeight: layout.implicitHeight + root.padding * 2
@ -17,16 +19,15 @@ StyledRect {
color: Qt.alpha(Colours.tPalette.m3surfaceContainer, Config.bar.clock.background ? Colours.tPalette.m3surfaceContainer.a : 0)
radius: Tokens.rounding.full
Column {
ColumnLayout {
id: layout
anchors.centerIn: parent
spacing: Tokens.spacing.small
Loader {
Layout.alignment: Qt.AlignHCenter
asynchronous: true
anchors.horizontalCenter: parent.horizontalCenter
active: Config.bar.clock.showIcon
visible: active
@ -37,35 +38,69 @@ StyledRect {
}
StyledText {
anchors.horizontalCenter: parent.horizontalCenter
Layout.alignment: Qt.AlignHCenter
visible: Config.bar.clock.showDate
horizontalAlignment: StyledText.AlignHCenter
text: Time.format("ddd\nd")
font.pointSize: Tokens.font.size.smaller
font.family: Tokens.font.family.sans
font: Tokens.font.body.small
color: root.colour
}
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
Layout.fillWidth: true
visible: Config.bar.clock.showDate
height: visible ? 1 : 0
width: parent.width * 0.8
color: root.colour
opacity: 0.2
implicitHeight: 1
color: Colours.palette.m3outlineVariant
}
StyledText {
anchors.horizontalCenter: parent.horizontalCenter
Layout.alignment: Qt.AlignHCenter
text: Time.hourStr
font: {
const scale = text === "11" ? 1.15 : Math.min(1.05, Math.max(hourMetrics.width, minMetrics.width) / hourMetrics.width);
return root.font.width(scale * 100).letterSpacing(scale).build();
}
color: root.colour
horizontalAlignment: StyledText.AlignHCenter
text: Time.format(GlobalConfig.services.useTwelveHourClock ? "hh\nmm\nA" : "hh\nmm")
font.pointSize: Tokens.font.size.smaller
font.family: Tokens.font.family.mono
TextMetrics {
id: hourMetrics
font: root.font.build()
text: Time.hourStr
}
}
StyledText {
Layout.topMargin: -parent.spacing - 4
Layout.alignment: Qt.AlignHCenter
text: Time.minuteStr
font: {
const scale = text === "11" ? 1.15 : Math.min(1.05, Math.max(hourMetrics.width, minMetrics.width) / minMetrics.width);
return root.font.width(scale * 100).letterSpacing(scale).build();
}
color: root.colour
TextMetrics {
id: minMetrics
font: root.font.build()
text: Time.minuteStr
}
}
Loader {
Layout.topMargin: -parent.spacing - 4
Layout.alignment: Qt.AlignHCenter
asynchronous: true
active: GlobalConfig.services.useTwelveHourClock
visible: active
sourceComponent: StyledText {
text: Time.amPmStr.toLowerCase()
font: Tokens.font.body.builders.small.scale(0.9).build()
color: root.colour
}
}
}
}

View file

@ -8,8 +8,8 @@ import qs.utils
Item {
id: root
implicitWidth: Math.round(Tokens.font.size.large * 1.2)
implicitHeight: Math.round(Tokens.font.size.large * 1.2)
implicitWidth: Math.round(Tokens.font.body.large.pointSize * 1.2)
implicitHeight: Math.round(Tokens.font.body.large.pointSize * 1.2)
MouseArea {
anchors.fill: parent
@ -30,8 +30,8 @@ Item {
id: caelestiaLogo
Logo {
implicitWidth: Math.round(Tokens.font.size.large * 1.6)
implicitHeight: Math.round(Tokens.font.size.large * 1.6)
implicitWidth: Math.round(Tokens.font.body.large.pointSize * 1.6)
implicitHeight: Math.round(Tokens.font.body.large.pointSize * 1.6)
}
}
@ -40,7 +40,7 @@ Item {
ColouredIcon {
source: SysInfo.osLogo
implicitSize: Math.round(Tokens.font.size.large * 1.2)
implicitSize: Math.round(Tokens.font.body.large.pointSize * 1.2)
colour: Colours.palette.m3tertiary
}
}

View file

@ -8,7 +8,7 @@ Item {
required property DrawerVisibilities visibilities
implicitWidth: icon.implicitHeight + Tokens.padding.small * 2
implicitWidth: icon.implicitHeight + Tokens.padding.small
implicitHeight: icon.implicitHeight
StateLayer {
@ -16,7 +16,7 @@ Item {
anchors.fill: undefined
anchors.centerIn: parent
implicitWidth: implicitHeight
implicitHeight: icon.implicitHeight + Tokens.padding.small * 2
implicitHeight: icon.implicitHeight + Tokens.padding.small
radius: Tokens.rounding.full
onClicked: root.visibilities.session = !root.visibilities.session
}
@ -29,7 +29,6 @@ Item {
text: "power_settings_new"
color: Colours.palette.m3error
font.bold: true
font.pointSize: Tokens.font.size.normal
fontStyle: Tokens.font.icon.builders.small.weight(Font.Bold).build()
}
}

View file

@ -21,7 +21,7 @@ StyledRect {
clip: true
implicitWidth: Tokens.sizes.bar.innerWidth
implicitHeight: iconColumn.implicitHeight + Tokens.padding.normal * 2 - (Config.bar.status.showLockStatus && !Hypr.capsLock && !Hypr.numLock ? iconColumn.spacing : 0)
implicitHeight: iconColumn.implicitHeight + Tokens.padding.medium * 2 - (Config.bar.status.showLockStatus && !Hypr.capsLock && !Hypr.numLock ? iconColumn.spacing : 0)
ColumnLayout {
id: iconColumn
@ -29,9 +29,9 @@ StyledRect {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: Tokens.padding.normal
anchors.bottomMargin: Tokens.padding.medium
spacing: Tokens.spacing.smaller / 2
spacing: Tokens.spacing.medium / 2
// Lock keys status
WrappedLoader {
@ -57,7 +57,9 @@ StyledRect {
color: root.colour
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
Behavior on scale {
@ -88,7 +90,9 @@ StyledRect {
color: root.colour
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
Behavior on scale {
@ -136,7 +140,7 @@ StyledRect {
animate: true
text: Hypr.kbLayout
color: root.colour
font.family: Tokens.font.family.mono
font: Tokens.font.mono.medium
}
}
@ -172,7 +176,7 @@ StyledRect {
active: Config.bar.status.showBluetooth
sourceComponent: ColumnLayout {
spacing: Tokens.spacing.smaller / 2
spacing: Tokens.spacing.medium / 2
// Bluetooth icon
MaterialIcon {
@ -245,15 +249,7 @@ StyledRect {
return "rocket_launch";
return "balance";
}
const perc = UPower.displayDevice.percentage;
const charging = [UPowerDeviceState.Charging, UPowerDeviceState.FullyCharged, UPowerDeviceState.PendingCharge].includes(UPower.displayDevice.state);
if (perc === 1)
return charging ? "battery_charging_full" : "battery_full";
let level = Math.floor(perc * 7);
if (charging && (level === 4 || level === 1))
level--;
return charging ? `battery_charging_${(level + 3) * 10}` : `battery_${level}_bar`;
return Icons.getBatteryIcon(UPower.displayDevice.percentage, [UPowerDeviceState.Charging, UPowerDeviceState.FullyCharged, UPowerDeviceState.PendingCharge].includes(UPower.displayDevice.state));
}
color: !UPower.onBattery || UPower.displayDevice.percentage > 0.2 ? root.colour : Colours.palette.m3error
fill: 1

View file

@ -14,7 +14,7 @@ StyledRect {
readonly property alias items: items
readonly property alias expandIcon: expandIcon
readonly property int padding: Config.bar.tray.background ? Tokens.padding.normal : Tokens.padding.small
readonly property int padding: Config.bar.tray.background ? Tokens.padding.medium : Tokens.padding.extraSmall
readonly property int spacing: Config.bar.tray.background ? Tokens.spacing.small : 0
property bool expanded
@ -75,7 +75,9 @@ StyledRect {
}
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
@ -91,16 +93,16 @@ StyledRect {
sourceComponent: Item {
implicitWidth: expandIconInner.implicitWidth
implicitHeight: expandIconInner.implicitHeight - Tokens.padding.small * 2
implicitHeight: expandIconInner.implicitHeight - Tokens.padding.small
MaterialIcon {
id: expandIconInner
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: Config.bar.tray.background ? Tokens.padding.small : -Tokens.padding.small
anchors.bottomMargin: Config.bar.tray.background ? Tokens.padding.extraSmall : -Tokens.padding.extraSmall
text: "expand_less"
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
rotation: root.expanded ? 180 : 0
Behavior on rotation {
@ -115,8 +117,6 @@ StyledRect {
}
Behavior on implicitHeight {
Anim {
type: Anim.DefaultSpatial
}
Anim {}
}
}

View file

@ -13,8 +13,8 @@ MouseArea {
required property SystemTrayItem modelData
acceptedButtons: Qt.LeftButton | Qt.RightButton
implicitWidth: Tokens.font.size.small * 2
implicitHeight: Tokens.font.size.small * 2
implicitWidth: Tokens.font.body.small.pointSize * 2
implicitHeight: Tokens.font.body.small.pointSize * 2
onClicked: event => {
if (event.button === Qt.LeftButton)

View file

@ -44,7 +44,7 @@ StyledRect {
clip: true
y: offset + mask.y
implicitWidth: Tokens.sizes.bar.innerWidth - Tokens.padding.small * 2
implicitWidth: Tokens.sizes.bar.innerWidth - Tokens.padding.small
implicitHeight: size
radius: Tokens.rounding.full
color: Colours.palette.m3primary

View file

@ -65,7 +65,7 @@ Item {
anchors.horizontalCenter: root.horizontalCenter
y: (start?.y ?? 0) - 1
implicitWidth: Tokens.sizes.bar.innerWidth - Tokens.padding.small * 2 + 2
implicitWidth: Tokens.sizes.bar.innerWidth - Tokens.padding.small + 2
implicitHeight: start && end ? end.y + end.size - start.y + 2 : 0
color: Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)

View file

@ -18,7 +18,7 @@ Item {
readonly property string activeSpecial: (GlobalConfig.bar.workspaces.perMonitorWorkspaces ? monitor : Hypr.focusedMonitor)?.lastIpcObject.specialWorkspace?.name ?? ""
layer.enabled: true
layer.effect: OpacityMask {
layer.effect: Mask {
maskSource: mask
}
@ -65,7 +65,9 @@ Item {
opacity: view.contentY > 0 ? 0 : 1
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
@ -76,10 +78,12 @@ Item {
radius: Tokens.rounding.full
implicitHeight: parent.height / 2
opacity: view.contentY < view.contentHeight - parent.height + Tokens.padding.small ? 0 : 1
opacity: view.contentY < view.contentHeight - parent.height + Tokens.padding.extraSmall ? 0 : 1
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
}
@ -88,7 +92,7 @@ Item {
id: view
anchors.fill: parent
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
interactive: false
currentIndex: model.values.findIndex(w => w.name === root.activeSpecial)
@ -213,7 +217,7 @@ Item {
drag.target: view.contentItem
drag.axis: Drag.YAxis
drag.maximumY: 0
drag.minimumY: Math.min(0, view.height - view.contentHeight - Tokens.padding.small)
drag.minimumY: Math.min(0, view.height - view.contentHeight - Tokens.padding.extraSmall)
onPressed: event => startY = event.y
@ -233,7 +237,7 @@ Item {
id: ws
required property HyprlandWorkspace modelData
readonly property int size: label.Layout.preferredHeight + (hasWindows ? windows.implicitHeight + Tokens.padding.small : 0)
readonly property int size: label.Layout.preferredHeight + (hasWindows ? windows.implicitHeight + Tokens.padding.extraSmall : 0)
property int wsId
property string icon
property bool hasWindows
@ -284,7 +288,7 @@ Item {
asynchronous: true
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
Layout.preferredHeight: Tokens.sizes.bar.innerWidth - Tokens.padding.small * 2
Layout.preferredHeight: Tokens.sizes.bar.innerWidth - Tokens.padding.small
sourceComponent: ws.icon.length === 1 ? letterComp : iconComp

View file

@ -18,7 +18,7 @@ ColumnLayout {
readonly property bool isWorkspace: true // Flag for finding workspace children
// Unanimated prop for others to use as reference
readonly property int size: implicitHeight + (hasWindows ? Tokens.padding.small : 0)
readonly property int size: implicitHeight + (hasWindows ? Tokens.padding.extraSmall : 0)
readonly property int ws: groupOffset + index + 1
readonly property bool isOccupied: occupied[ws] ?? false
@ -33,7 +33,7 @@ ColumnLayout {
id: indicator
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
Layout.preferredHeight: Tokens.sizes.bar.innerWidth - Tokens.padding.small * 2
Layout.preferredHeight: Tokens.sizes.bar.innerWidth - Tokens.padding.small
animate: true
text: {

View file

@ -28,7 +28,7 @@ StyledClippingRect {
property real blur: onSpecial ? 1 : 0
implicitWidth: Tokens.sizes.bar.innerWidth
implicitHeight: layout.implicitHeight + Tokens.padding.small * 2
implicitHeight: layout.implicitHeight + Tokens.padding.small
color: Colours.tPalette.m3surfaceContainer
radius: Tokens.rounding.full
@ -51,7 +51,7 @@ StyledClippingRect {
active: Config.bar.workspaces.occupiedBg
anchors.fill: parent
anchors.margins: Tokens.padding.small
anchors.margins: Tokens.padding.extraSmall
sourceComponent: OccupiedBg {
workspaces: workspaces
@ -64,7 +64,7 @@ StyledClippingRect {
id: layout
anchors.centerIn: parent
spacing: Math.floor(Tokens.spacing.small / 2)
spacing: Math.floor(Tokens.spacing.extraSmall)
Repeater {
id: workspaces
@ -108,7 +108,9 @@ StyledClippingRect {
}
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
@ -118,7 +120,7 @@ StyledClippingRect {
asynchronous: true
anchors.fill: parent
anchors.margins: Tokens.padding.small
anchors.margins: Tokens.padding.extraSmall
active: opacity > 0
@ -134,7 +136,9 @@ StyledClippingRect {
}
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}

View file

@ -12,21 +12,21 @@ Item {
required property PopoutState popouts
implicitWidth: Hypr.activeToplevel ? child.implicitWidth : -Tokens.padding.large * 2
implicitWidth: Hypr.activeToplevel ? child.implicitWidth : -Tokens.padding.extraLargeIncreased
implicitHeight: child.implicitHeight
Column {
id: child
anchors.centerIn: parent
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
RowLayout {
id: detailsRow
anchors.left: parent.left
anchors.right: parent.right
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
IconImage {
id: icon
@ -46,7 +46,7 @@ Item {
StyledText {
Layout.fillWidth: true
text: Hypr.activeToplevel?.title ?? ""
font.pointSize: Tokens.font.size.normal
font: Tokens.font.body.medium
elide: Text.ElideRight
}
@ -59,13 +59,13 @@ Item {
}
Item {
implicitWidth: expandIcon.implicitHeight + Tokens.padding.small * 2
implicitHeight: expandIcon.implicitHeight + Tokens.padding.small * 2
implicitWidth: expandIcon.implicitHeight + Tokens.padding.small
implicitHeight: expandIcon.implicitHeight + Tokens.padding.small
Layout.alignment: Qt.AlignVCenter
StateLayer {
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
onClicked: root.popouts.detachRequested("winfo")
}
@ -77,14 +77,14 @@ Item {
text: "chevron_right"
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
}
}
}
ClippingWrapperRectangle {
color: "transparent"
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
ScreencopyView {
id: preview

View file

@ -14,8 +14,8 @@ Item {
required property PopoutState popouts
implicitWidth: layout.implicitWidth + Tokens.padding.normal * 2
implicitHeight: layout.implicitHeight + Tokens.padding.normal * 2
implicitWidth: layout.implicitWidth + Tokens.padding.medium * 2
implicitHeight: layout.implicitHeight + Tokens.padding.medium * 2
ButtonGroup {
id: sinks
@ -30,11 +30,11 @@ Item {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
text: qsTr("Output device")
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
}
Repeater {
@ -53,9 +53,9 @@ Item {
}
StyledText {
Layout.topMargin: Tokens.spacing.smaller
Layout.topMargin: Tokens.spacing.medium
text: qsTr("Input device")
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
}
Repeater {
@ -72,15 +72,14 @@ Item {
}
StyledText {
Layout.topMargin: Tokens.spacing.smaller
Layout.bottomMargin: -Tokens.spacing.small / 2
Layout.topMargin: Tokens.spacing.medium
text: qsTr("Volume (%1)").arg(Audio.muted ? qsTr("Muted") : `${Math.round(Audio.volume * 100)}%`)
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
}
CustomMouseArea {
Layout.fillWidth: true
implicitHeight: Tokens.padding.normal * 3
implicitHeight: Tokens.padding.medium * 3
onWheel: event => {
if (event.angleDelta.y > 0)
@ -95,20 +94,16 @@ Item {
implicitHeight: parent.implicitHeight
value: Audio.volume
onMoved: Audio.setVolume(value)
Behavior on value {
Anim {}
}
onInteraction: value => Audio.setVolume(value)
}
}
IconTextButton {
Layout.fillWidth: true
Layout.topMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.spacing.medium
inactiveColour: Colours.palette.m3primaryContainer
inactiveOnColour: Colours.palette.m3onPrimaryContainer
verticalPadding: Tokens.padding.small
verticalPadding: Tokens.padding.extraSmall
text: qsTr("Open settings")
icon: "settings"

View file

@ -9,7 +9,7 @@ import qs.services
Column {
id: root
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
width: Tokens.sizes.bar.batteryWidth
StyledText {
@ -45,11 +45,11 @@ Column {
height: active ? ((item as Item)?.implicitHeight ?? 0) : 0
sourceComponent: StyledRect {
implicitWidth: child.implicitWidth + Tokens.padding.normal * 2
implicitHeight: child.implicitHeight + Tokens.padding.smaller * 2
implicitWidth: child.implicitWidth + Tokens.padding.medium * 2
implicitHeight: child.implicitHeight + Tokens.padding.large
color: Colours.palette.m3error
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
Column {
id: child
@ -72,8 +72,7 @@ Column {
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Performance Degraded")
color: Colours.palette.m3onError
font.family: Tokens.font.family.mono
font.weight: 500
font: Tokens.font.mono.builders.medium.weight(Font.Medium).build()
}
MaterialIcon {
@ -109,8 +108,8 @@ Column {
anchors.horizontalCenter: parent.horizontalCenter
implicitWidth: saver.implicitHeight + balance.implicitHeight + perf.implicitHeight + Tokens.padding.normal * 2 + Tokens.spacing.large * 2
implicitHeight: Math.max(saver.implicitHeight, balance.implicitHeight, perf.implicitHeight) + Tokens.padding.small * 2
implicitWidth: saver.implicitHeight + balance.implicitHeight + perf.implicitHeight + Tokens.padding.medium * 2 + Tokens.spacing.largeIncreased * 2
implicitHeight: Math.max(saver.implicitHeight, balance.implicitHeight, perf.implicitHeight) + Tokens.padding.small
color: Colours.tPalette.m3surfaceContainer
radius: Tokens.rounding.full
@ -147,9 +146,7 @@ Column {
]
transitions: Transition {
AnchorAnim {
type: AnchorAnim.Emphasized
}
AnchorAnim {}
}
}
@ -158,7 +155,7 @@ Column {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.extraSmall
profile: PowerProfile.PowerSaver
icon: "energy_savings_leaf"
@ -178,7 +175,7 @@ Column {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: Tokens.padding.small
anchors.rightMargin: Tokens.padding.extraSmall
profile: PowerProfile.Performance
icon: "rocket_launch"
@ -199,8 +196,8 @@ Column {
required property string icon
required property int profile
implicitWidth: icon.implicitHeight + Tokens.padding.small * 2
implicitHeight: icon.implicitHeight + Tokens.padding.small * 2
implicitWidth: icon.implicitHeight + Tokens.padding.small
implicitHeight: icon.implicitHeight + Tokens.padding.small
StateLayer {
radius: Tokens.rounding.full
@ -214,12 +211,14 @@ Column {
anchors.centerIn: parent
text: parent.icon
font.pointSize: Tokens.font.size.large
color: profiles.current === text ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
fontStyle: Tokens.font.icon.large
color: profiles.current === text ? Colours.palette.m3onPrimary : Colours.palette.m3onSurfaceVariant
fill: profiles.current === text ? 1 : 0
Behavior on fill {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
}

View file

@ -19,10 +19,10 @@ ColumnLayout {
spacing: Tokens.spacing.small
StyledText {
Layout.topMargin: Tokens.padding.normal
Layout.rightMargin: Tokens.padding.small
Layout.topMargin: Tokens.padding.medium
Layout.rightMargin: Tokens.padding.extraSmall
text: qsTr("Bluetooth")
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
}
Toggle {
@ -47,7 +47,7 @@ ColumnLayout {
StyledText {
Layout.topMargin: Tokens.spacing.small
Layout.rightMargin: Tokens.padding.small
Layout.rightMargin: Tokens.padding.extraSmall
text: {
const devices = Bluetooth.devices.values; // qmllint disable unresolved-type
let available = qsTr("%1 device%2 available").arg(devices.length).arg(devices.length === 1 ? "" : "s");
@ -57,7 +57,7 @@ ColumnLayout {
return available;
}
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
Repeater {
@ -72,7 +72,7 @@ ColumnLayout {
readonly property bool loading: modelData.state === BluetoothDeviceState.Connecting || modelData.state === BluetoothDeviceState.Disconnecting // qmllint disable unresolved-type
Layout.fillWidth: true
Layout.rightMargin: Tokens.padding.small
Layout.rightMargin: Tokens.padding.extraSmall
spacing: Tokens.spacing.small
opacity: 0
@ -84,7 +84,9 @@ ColumnLayout {
}
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
Behavior on scale {
@ -96,8 +98,8 @@ ColumnLayout {
}
StyledText {
Layout.leftMargin: Tokens.spacing.small / 2
Layout.rightMargin: Tokens.spacing.small / 2
Layout.leftMargin: Tokens.spacing.extraSmall
Layout.rightMargin: Tokens.spacing.extraSmall
Layout.fillWidth: true
text: device.modelData.name
elide: Text.ElideRight
@ -105,15 +107,15 @@ ColumnLayout {
MaterialIcon {
visible: device.modelData.state === BluetoothDeviceState.Connected // qmllint disable unresolved-type
text: Icons.getBatteryIcon(device.modelData.batteryAvailable ? device.modelData.battery * 100 : -1)
color: device.modelData.battery < 0.2 ? Colours.palette.m3error : Colours.palette.m3onSurfaceVariant
text: device.modelData.batteryAvailable ? Icons.getBatteryIcon(device.modelData.battery) : "battery_alert"
color: device.modelData.batteryAvailable && device.modelData.battery < 0.2 ? Colours.palette.m3error : Colours.palette.m3onSurfaceVariant
}
StyledRect {
id: connectBtn
implicitWidth: implicitHeight
implicitHeight: connectIcon.implicitHeight + Tokens.padding.small
implicitHeight: connectIcon.implicitHeight + Tokens.padding.extraSmall
radius: Tokens.rounding.full
color: Qt.alpha(Colours.palette.m3primary, device.modelData.state === BluetoothDeviceState.Connected ? 1 : 0) // qmllint disable unresolved-type
@ -140,7 +142,9 @@ ColumnLayout {
opacity: device.loading ? 0 : 1
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
}
@ -169,10 +173,10 @@ ColumnLayout {
IconTextButton {
Layout.fillWidth: true
Layout.topMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.spacing.medium
inactiveColour: Colours.palette.m3primaryContainer
inactiveOnColour: Colours.palette.m3onPrimaryContainer
verticalPadding: Tokens.padding.small
verticalPadding: Tokens.padding.extraSmall
text: qsTr("Open settings")
icon: "settings"
@ -185,8 +189,8 @@ ColumnLayout {
property alias toggle: toggle
Layout.fillWidth: true
Layout.rightMargin: Tokens.padding.small
spacing: Tokens.spacing.normal
Layout.rightMargin: Tokens.padding.extraSmall
spacing: Tokens.spacing.medium
StyledText {
Layout.fillWidth: true

View file

@ -33,9 +33,7 @@ Item {
}
Behavior on offsetScale {
Anim {
type: Anim.DefaultSpatial
}
Anim {}
}
Behavior on x {

View file

@ -14,8 +14,8 @@ Item {
readonly property Popout currentPopout: content.children.find(c => c.shouldBeActive) ?? null
readonly property Item current: currentPopout?.item ?? null
implicitWidth: (currentPopout?.implicitWidth ?? 0) + Tokens.padding.large * 2
implicitHeight: (currentPopout?.implicitHeight ?? 0) + Tokens.padding.large * 2
implicitWidth: (currentPopout?.implicitWidth ?? 0) + Tokens.padding.extraLargeIncreased
implicitHeight: (currentPopout?.implicitHeight ?? 0) + Tokens.padding.extraLargeIncreased
Item {
id: content
@ -172,7 +172,6 @@ Item {
anchors.centerIn: parent
opacity: 0
scale: 0.8
active: false
states: State {
@ -182,7 +181,6 @@ Item {
PropertyChanges {
popout.active: true
popout.opacity: 1
popout.scale: 1
}
}
@ -193,11 +191,10 @@ Item {
SequentialAnimation {
Anim {
properties: "opacity,scale"
type: Anim.StandardSmall
property: "opacity"
type: Anim.DefaultEffects
}
PropertyAction {
target: popout
property: "active"
}
}
@ -208,11 +205,11 @@ Item {
SequentialAnimation {
PropertyAction {
target: popout
property: "active"
}
Anim {
properties: "opacity,scale"
property: "opacity"
type: Anim.SlowEffects
}
}
}

View file

@ -26,10 +26,10 @@ ColumnLayout {
StyledText {
visible: root.view === "wireless"
Layout.preferredHeight: visible ? implicitHeight : 0
Layout.topMargin: visible ? Tokens.padding.normal : 0
Layout.rightMargin: Tokens.padding.small
Layout.topMargin: visible ? Tokens.padding.medium : 0
Layout.rightMargin: Tokens.padding.extraSmall
text: qsTr("Wireless")
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
}
Toggle {
@ -44,10 +44,10 @@ ColumnLayout {
visible: root.view === "wireless"
Layout.preferredHeight: visible ? implicitHeight : 0
Layout.topMargin: visible ? Tokens.spacing.small : 0
Layout.rightMargin: Tokens.padding.small
Layout.rightMargin: Tokens.padding.extraSmall
text: qsTr("%1 networks available").arg(Nmcli.networks.length) // qmllint disable missing-property
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
Repeater {
@ -70,7 +70,7 @@ ColumnLayout {
visible: root.view === "wireless"
Layout.preferredHeight: visible ? implicitHeight : 0
Layout.fillWidth: true
Layout.rightMargin: Tokens.padding.small
Layout.rightMargin: Tokens.padding.extraSmall
spacing: Tokens.spacing.small
opacity: 0
@ -82,7 +82,9 @@ ColumnLayout {
}
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
Behavior on scale {
@ -97,22 +99,22 @@ ColumnLayout {
MaterialIcon {
visible: networkItem.modelData.isSecure
text: "lock"
font.pointSize: Tokens.font.size.small
fontStyle: Tokens.font.icon.small
}
StyledText {
Layout.leftMargin: Tokens.spacing.small / 2
Layout.rightMargin: Tokens.spacing.small / 2
Layout.leftMargin: Tokens.spacing.extraSmall
Layout.rightMargin: Tokens.spacing.extraSmall
Layout.fillWidth: true
text: networkItem.modelData.ssid
elide: Text.ElideRight
font.weight: networkItem.modelData.active ? 500 : 400
font: Tokens.font.body.builders.medium.weight(networkItem.modelData.active ? Font.Medium : Font.Normal).build()
color: networkItem.modelData.active ? Colours.palette.m3primary : Colours.palette.m3onSurface
}
StyledRect {
implicitWidth: implicitHeight
implicitHeight: wirelessConnectIcon.implicitHeight + Tokens.padding.small
implicitHeight: wirelessConnectIcon.implicitHeight + Tokens.padding.extraSmall
radius: Tokens.rounding.full
color: Qt.alpha(Colours.palette.m3primary, networkItem.modelData.active ? 1 : 0)
@ -155,7 +157,9 @@ ColumnLayout {
opacity: networkItem.loading ? 0 : 1
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
}
@ -167,7 +171,7 @@ ColumnLayout {
Layout.preferredHeight: visible ? implicitHeight : 0
Layout.topMargin: visible ? Tokens.spacing.small : 0
Layout.fillWidth: true
implicitHeight: rescanBtn.implicitHeight + Tokens.padding.small * 2
implicitHeight: rescanBtn.implicitHeight + Tokens.padding.small
radius: Tokens.rounding.full
color: Colours.palette.m3primaryContainer
@ -201,15 +205,17 @@ ColumnLayout {
}
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
CircularIndicator {
anchors.centerIn: parent
strokeWidth: Tokens.padding.small / 2
strokeWidth: Tokens.padding.extraSmall / 2
bgColour: "transparent"
implicitSize: parent.implicitHeight - Tokens.padding.smaller * 2
implicitSize: parent.implicitHeight - Tokens.padding.large
running: Nmcli.scanning
}
}
@ -218,20 +224,20 @@ ColumnLayout {
StyledText {
visible: root.view === "ethernet"
Layout.preferredHeight: visible ? implicitHeight : 0
Layout.topMargin: visible ? Tokens.padding.normal : 0
Layout.rightMargin: Tokens.padding.small
Layout.topMargin: visible ? Tokens.padding.medium : 0
Layout.rightMargin: Tokens.padding.extraSmall
text: qsTr("Ethernet")
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
}
StyledText {
visible: root.view === "ethernet"
Layout.preferredHeight: visible ? implicitHeight : 0
Layout.topMargin: visible ? Tokens.spacing.small : 0
Layout.rightMargin: Tokens.padding.small
Layout.rightMargin: Tokens.padding.extraSmall
text: qsTr("%1 devices available").arg(Nmcli.ethernetDevices.length)
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
Repeater {
@ -253,7 +259,7 @@ ColumnLayout {
visible: root.view === "ethernet"
Layout.preferredHeight: visible ? implicitHeight : 0
Layout.fillWidth: true
Layout.rightMargin: Tokens.padding.small
Layout.rightMargin: Tokens.padding.extraSmall
spacing: Tokens.spacing.small
opacity: 0
@ -265,7 +271,9 @@ ColumnLayout {
}
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
Behavior on scale {
@ -278,18 +286,18 @@ ColumnLayout {
}
StyledText {
Layout.leftMargin: Tokens.spacing.small / 2
Layout.rightMargin: Tokens.spacing.small / 2
Layout.leftMargin: Tokens.spacing.extraSmall
Layout.rightMargin: Tokens.spacing.extraSmall
Layout.fillWidth: true
text: ethernetItem.modelData.interface || qsTr("Unknown")
elide: Text.ElideRight
font.weight: ethernetItem.modelData.connected ? 500 : 400
font: Tokens.font.body.builders.medium.weight(ethernetItem.modelData.connected ? Font.Medium : Font.Normal).build()
color: ethernetItem.modelData.connected ? Colours.palette.m3primary : Colours.palette.m3onSurface
}
StyledRect {
implicitWidth: implicitHeight
implicitHeight: connectIcon.implicitHeight + Tokens.padding.small
implicitHeight: connectIcon.implicitHeight + Tokens.padding.extraSmall
radius: Tokens.rounding.full
color: Qt.alpha(Colours.palette.m3primary, ethernetItem.modelData.connected ? 1 : 0)
@ -323,7 +331,9 @@ ColumnLayout {
opacity: ethernetItem.loading ? 0 : 1
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
}
@ -371,8 +381,8 @@ ColumnLayout {
property alias toggle: toggle
Layout.fillWidth: true
Layout.rightMargin: Tokens.padding.small
spacing: Tokens.spacing.normal
Layout.rightMargin: Tokens.padding.extraSmall
spacing: Tokens.spacing.medium
StyledText {
Layout.fillWidth: true

View file

@ -45,7 +45,7 @@ StackView {
property bool isSubMenu
property bool shown
padding: Tokens.padding.smaller
padding: Tokens.padding.small
spacing: Tokens.spacing.small
opacity: shown ? 1 : 0
@ -57,7 +57,9 @@ StackView {
StackView.onRemoved: destroy()
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
Behavior on scale {
@ -97,9 +99,9 @@ StackView {
implicitHeight: label.implicitHeight
StateLayer {
anchors.margins: -Tokens.padding.small / 2
anchors.leftMargin: -Tokens.padding.smaller
anchors.rightMargin: -Tokens.padding.smaller
anchors.margins: -Tokens.padding.extraSmall / 2
anchors.leftMargin: -Tokens.padding.small
anchors.rightMargin: -Tokens.padding.small
radius: item.radius
disabled: !item.modelData.enabled
@ -138,7 +140,7 @@ StackView {
id: label
anchors.left: icon.right
anchors.leftMargin: icon.active ? Tokens.spacing.smaller : 0
anchors.leftMargin: icon.active ? Tokens.spacing.medium : 0
text: labelMetrics.elidedText
color: item.modelData.enabled ? Colours.palette.m3onSurface : Colours.palette.m3outline
@ -148,11 +150,10 @@ StackView {
id: labelMetrics
text: item.modelData.text
font.pointSize: label.font.pointSize
font.family: label.font.family
font: label.font
elide: Text.ElideRight
elideWidth: root.Tokens.sizes.bar.trayMenuWidth - (icon.active ? icon.implicitWidth + label.anchors.leftMargin : 0) - (expand.active ? expand.implicitWidth + root.Tokens.spacing.normal : 0)
elideWidth: root.Tokens.sizes.bar.trayMenuWidth - (icon.active ? icon.implicitWidth + label.anchors.leftMargin : 0) - (expand.active ? expand.implicitWidth + root.Tokens.spacing.medium : 0)
}
Loader {
@ -180,7 +181,7 @@ StackView {
sourceComponent: Item {
implicitWidth: back.implicitWidth
implicitHeight: back.implicitHeight + Tokens.spacing.small / 2
implicitHeight: back.implicitHeight + Tokens.spacing.extraSmall
Item {
anchors.bottom: parent.bottom
@ -189,9 +190,9 @@ StackView {
StyledRect {
anchors.fill: parent
anchors.margins: -Tokens.padding.small / 2
anchors.leftMargin: -Tokens.padding.smaller
anchors.rightMargin: -Tokens.padding.smaller * 2
anchors.margins: -Tokens.padding.extraSmall / 2
anchors.leftMargin: -Tokens.padding.small
anchors.rightMargin: -Tokens.padding.large
radius: Tokens.rounding.full
color: Colours.palette.m3secondaryContainer

View file

@ -69,9 +69,9 @@ ColumnLayout {
}
}
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
implicitWidth: 400
implicitHeight: content.implicitHeight + Tokens.padding.large * 2
implicitHeight: content.implicitHeight + Tokens.padding.extraLargeIncreased
visible: shouldBeVisible || isClosing
enabled: shouldBeVisible && !isClosing
focus: enabled
@ -128,8 +128,8 @@ ColumnLayout {
StyledRect {
Layout.fillWidth: true
Layout.preferredWidth: 400
implicitHeight: content.implicitHeight + Tokens.padding.large * 2
radius: Tokens.rounding.normal
implicitHeight: content.implicitHeight + Tokens.padding.extraLargeIncreased
radius: Tokens.rounding.large
color: Colours.tPalette.m3surfaceContainer
visible: root.shouldBeVisible || root.isClosing
opacity: root.shouldBeVisible && !root.isClosing ? 1 : 0
@ -137,7 +137,9 @@ ColumnLayout {
Keys.onEscapePressed: root.closeDialog()
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
Behavior on scale {
@ -153,6 +155,7 @@ ColumnLayout {
}
Anim {
type: Anim.DefaultEffects
target: parent
property: "opacity"
to: 0
@ -172,19 +175,18 @@ ColumnLayout {
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
MaterialIcon {
Layout.alignment: Qt.AlignHCenter
text: "lock"
font.pointSize: Tokens.font.size.extraLarge * 2
fontStyle: Tokens.font.icon.builders.extraLarge.scale(2).build()
}
StyledText {
Layout.alignment: Qt.AlignHCenter
text: qsTr("Enter password")
font.pointSize: Tokens.font.size.large
font.weight: 500
font: Tokens.font.body.builders.large.weight(Font.Medium).build()
}
StyledText {
@ -201,7 +203,7 @@ ColumnLayout {
return qsTr("Network: Unknown");
}
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
Timer {
@ -249,10 +251,9 @@ ColumnLayout {
return "";
}
color: connectButton.hasError ? Colours.palette.m3error : Colours.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.small
font.weight: 400
font: Tokens.font.body.builders.small.weight(Font.Normal).build()
wrapMode: Text.WordWrap
Layout.maximumWidth: parent.width - Tokens.padding.large * 2
Layout.maximumWidth: parent.width - Tokens.padding.extraLargeIncreased
}
FocusScope {
@ -261,9 +262,9 @@ ColumnLayout {
property string passwordBuffer: ""
objectName: "passwordContainer"
Layout.topMargin: Tokens.spacing.large
Layout.topMargin: Tokens.spacing.largeIncreased
Layout.fillWidth: true
implicitHeight: Math.max(48, charList.implicitHeight + Tokens.padding.normal * 2)
implicitHeight: Math.max(48, charList.implicitHeight + Tokens.padding.medium * 2)
focus: true
activeFocusOnTab: true
@ -336,7 +337,7 @@ ColumnLayout {
StyledRect {
anchors.fill: parent
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
color: passwordContainer.activeFocus ? Qt.lighter(Colours.tPalette.m3surfaceContainer, 1.05) : Colours.tPalette.m3surfaceContainer
border.width: passwordContainer.activeFocus || connectButton.hasError ? 4 : (root.shouldBeVisible ? 1 : 0)
border.color: {
@ -365,7 +366,7 @@ ColumnLayout {
StateLayer {
hoverEnabled: false
cursorShape: Qt.IBeamCursor
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
onClicked: passwordContainer.forceActiveFocus()
}
@ -375,12 +376,13 @@ ColumnLayout {
anchors.centerIn: parent
text: qsTr("Password")
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.normal
font.family: Tokens.font.family.mono
font: Tokens.font.mono.medium
opacity: passwordContainer.passwordBuffer ? 0 : 1
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
@ -391,10 +393,10 @@ ColumnLayout {
anchors.centerIn: parent
implicitWidth: fullWidth
implicitHeight: Tokens.font.size.normal
implicitHeight: Tokens.font.body.medium.pointSize
orientation: Qt.Horizontal
spacing: Tokens.spacing.small / 2
spacing: Tokens.spacing.extraSmall
interactive: false
model: ScriptModel {
@ -408,7 +410,7 @@ ColumnLayout {
implicitHeight: charList.implicitHeight
color: Colours.palette.m3onSurface
radius: Tokens.rounding.small / 2
radius: Tokens.rounding.medium / 2
opacity: 0
scale: 0
@ -428,6 +430,7 @@ ColumnLayout {
}
ParallelAnimation {
Anim {
type: Anim.DefaultEffects
target: ch
property: "opacity"
to: 0
@ -446,7 +449,9 @@ ColumnLayout {
}
Behavior on opacity {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
Behavior on scale {
@ -463,15 +468,15 @@ ColumnLayout {
}
RowLayout {
Layout.topMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.spacing.medium
Layout.fillWidth: true
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
TextButton {
id: cancelButton
Layout.fillWidth: true
Layout.minimumHeight: Tokens.font.size.normal + Tokens.padding.normal * 2
Layout.minimumHeight: Tokens.font.body.medium.pointSize + Tokens.padding.medium * 2
inactiveColour: Colours.palette.m3secondaryContainer
inactiveOnColour: Colours.palette.m3onSecondaryContainer
text: qsTr("Cancel")
@ -486,7 +491,7 @@ ColumnLayout {
property bool hasError: false
Layout.fillWidth: true
Layout.minimumHeight: Tokens.font.size.normal + Tokens.padding.normal * 2
Layout.minimumHeight: Tokens.font.body.medium.pointSize + Tokens.padding.medium * 2
inactiveColour: Colours.palette.m3primary
inactiveOnColour: Colours.palette.m3onPrimary
text: qsTr("Connect")

View file

@ -185,6 +185,7 @@ Item {
property: "active"
}
Anim {
type: Anim.DefaultEffects
property: "opacity"
}
}
@ -195,6 +196,7 @@ Item {
SequentialAnimation {
Anim {
type: Anim.DefaultEffects
property: "opacity"
}
PropertyAction {

View file

@ -24,10 +24,10 @@ ColumnLayout {
}
StyledText {
Layout.topMargin: Tokens.padding.normal
Layout.rightMargin: Tokens.padding.small
Layout.topMargin: Tokens.padding.medium
Layout.rightMargin: Tokens.padding.extraSmall
text: qsTr("Keyboard Layouts")
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
}
ListView {
@ -36,7 +36,7 @@ ColumnLayout {
model: kb.visibleModel
Layout.fillWidth: true
Layout.rightMargin: Tokens.padding.small
Layout.rightMargin: Tokens.padding.extraSmall
Layout.topMargin: Tokens.spacing.small
clip: true
@ -88,7 +88,7 @@ ColumnLayout {
readonly property bool isDisabled: layoutIndex > 3
width: list.width
height: Math.max(36, rowText.implicitHeight + Tokens.padding.small * 2)
height: Math.max(36, rowText.implicitHeight + Tokens.padding.small)
ToolTip.visible: isDisabled && layer.containsMouse
ToolTip.text: "XKB limitation: maximum 4 layouts allowed"
@ -114,8 +114,8 @@ ColumnLayout {
anchors.verticalCenter: layer.verticalCenter
anchors.left: layer.left
anchors.right: layer.right
anchors.leftMargin: Tokens.padding.small
anchors.rightMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.extraSmall
anchors.rightMargin: Tokens.padding.extraSmall
text: kbDelegate.label
elide: Text.ElideRight
opacity: kbDelegate.isDisabled ? 0.4 : 1.0
@ -126,7 +126,7 @@ ColumnLayout {
Rectangle {
visible: kb.activeLabel.length > 0
Layout.fillWidth: true
Layout.rightMargin: Tokens.padding.small
Layout.rightMargin: Tokens.padding.extraSmall
Layout.topMargin: Tokens.spacing.small
implicitHeight: 1
@ -139,7 +139,7 @@ ColumnLayout {
visible: kb.activeLabel.length > 0
Layout.fillWidth: true
Layout.rightMargin: Tokens.padding.small
Layout.rightMargin: Tokens.padding.extraSmall
Layout.topMargin: Tokens.spacing.small
spacing: Tokens.spacing.small
@ -155,7 +155,7 @@ ColumnLayout {
Layout.fillWidth: true
text: kb.activeLabel
elide: Text.ElideRight
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
color: Colours.palette.m3primary
}

View file

@ -12,7 +12,7 @@ Item {
id: root
required property ShellScreen screen
readonly property int rounding: floating ? 0 : Tokens.rounding.large
readonly property int rounding: floating ? 0 : Tokens.rounding.extraLarge
property alias floating: session.floating
property alias active: session.active

View file

@ -15,16 +15,16 @@ Item {
required property Session session
required property bool initialOpeningComplete
implicitWidth: layout.implicitWidth + Tokens.padding.larger * 4
implicitHeight: layout.implicitHeight + Tokens.padding.large * 2
implicitWidth: layout.implicitWidth + Tokens.padding.extraExtraLarge
implicitHeight: layout.implicitHeight + Tokens.padding.extraLargeIncreased
ColumnLayout {
id: layout
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Tokens.padding.larger * 2
spacing: Tokens.spacing.normal
anchors.leftMargin: Tokens.padding.medium * 2
spacing: Tokens.spacing.medium
states: State {
name: "expanded"
@ -42,7 +42,7 @@ Item {
}
Loader {
Layout.topMargin: Tokens.spacing.large
Layout.topMargin: Tokens.spacing.largeIncreased
asynchronous: true
active: !root.session.floating
visible: active
@ -51,10 +51,10 @@ Item {
readonly property int nonAnimWidth: normalWinIcon.implicitWidth + (root.session.navExpanded ? normalWinLabel.anchors.leftMargin + normalWinLabel.implicitWidth : 0) + normalWinIcon.anchors.leftMargin * 2
implicitWidth: nonAnimWidth
implicitHeight: root.session.navExpanded ? normalWinIcon.implicitHeight + Tokens.padding.normal * 2 : nonAnimWidth
implicitHeight: root.session.navExpanded ? normalWinIcon.implicitHeight + Tokens.padding.medium * 2 : nonAnimWidth
color: Colours.palette.m3primaryContainer
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
StateLayer {
id: normalWinState
@ -79,7 +79,7 @@ Item {
text: "select_window"
color: Colours.palette.m3onPrimaryContainer
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
fill: 1
}
@ -88,7 +88,7 @@ Item {
anchors.left: normalWinIcon.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Tokens.spacing.normal
anchors.leftMargin: Tokens.spacing.medium
text: qsTr("Float window")
color: Colours.palette.m3onPrimaryContainer
@ -102,15 +102,11 @@ Item {
}
Behavior on implicitWidth {
Anim {
type: Anim.DefaultSpatial
}
Anim {}
}
Behavior on implicitHeight {
Anim {
type: Anim.DefaultSpatial
}
Anim {}
}
}
}
@ -121,7 +117,7 @@ Item {
NavItem {
required property int index
Layout.topMargin: index === 0 ? Tokens.spacing.large * 2 : 0
Layout.topMargin: index === 0 ? Tokens.spacing.largeIncreased * 2 : 0
icon: PaneRegistry.getByIndex(index).icon
label: PaneRegistry.getByIndex(index).label
}
@ -146,7 +142,7 @@ Item {
expandedLabel.opacity: 1
smallLabel.opacity: 0
background.implicitWidth: icon.implicitWidth + icon.anchors.leftMargin * 2 + expandedLabel.anchors.leftMargin + expandedLabel.implicitWidth
background.implicitHeight: icon.implicitHeight + root.Tokens.padding.normal * 2
background.implicitHeight: icon.implicitHeight + root.Tokens.padding.medium * 2
item.implicitHeight: background.implicitHeight
}
}
@ -159,7 +155,6 @@ Item {
Anim {
properties: "implicitWidth,implicitHeight"
type: Anim.DefaultSpatial
}
}
@ -170,7 +165,7 @@ Item {
color: Qt.alpha(Colours.palette.m3secondaryContainer, item.active ? 1 : 0)
implicitWidth: icon.implicitWidth + icon.anchors.leftMargin * 2
implicitHeight: icon.implicitHeight + Tokens.padding.small
implicitHeight: icon.implicitHeight + Tokens.padding.extraSmall
StateLayer {
onClicked: {
@ -193,11 +188,13 @@ Item {
text: item.icon
color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
fill: item.active ? 1 : 0
Behavior on fill {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}
@ -206,12 +203,12 @@ Item {
anchors.left: icon.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Tokens.spacing.normal
anchors.leftMargin: Tokens.spacing.medium
opacity: 0
text: item.label
color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
font.capitalization: Font.Capitalize
font: Tokens.font.label.builders.medium.capitalisation(Font.Capitalize).build()
}
StyledText {
@ -219,11 +216,10 @@ Item {
anchors.horizontalCenter: icon.horizontalCenter
anchors.top: icon.bottom
anchors.topMargin: Tokens.spacing.small / 2
anchors.topMargin: Tokens.spacing.extraSmall
text: item.label
font.pointSize: Tokens.font.size.small
font.capitalization: Font.Capitalize
font: Tokens.font.label.builders.small.capitalisation(Font.Capitalize).build()
}
}
}

View file

@ -10,7 +10,7 @@ StyledRect {
required property ShellScreen screen
required property Session session
implicitHeight: text.implicitHeight + Tokens.padding.normal
implicitHeight: text.implicitHeight + Tokens.padding.medium
color: Colours.tPalette.m3surfaceContainer
StyledText {
@ -20,18 +20,16 @@ StyledRect {
anchors.bottom: parent.bottom
text: qsTr("Caelestia Settings - %1").arg(root.session.active)
font.capitalization: Font.Capitalize
font.pointSize: Tokens.font.size.larger
font.weight: 500
font: Tokens.font.title.builders.medium.capitalisation(Font.Capitalize).weight(Font.Medium).build()
}
Item {
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
implicitWidth: implicitHeight
implicitHeight: closeIcon.implicitHeight + Tokens.padding.small
implicitHeight: closeIcon.implicitHeight + Tokens.padding.extraSmall
StateLayer {
onClicked: {

View file

@ -109,10 +109,9 @@ Item {
StyledText {
Layout.alignment: Qt.AlignHCenter
Layout.bottomMargin: Tokens.spacing.normal
Layout.bottomMargin: Tokens.spacing.medium
text: qsTr("Wallpaper")
font.pointSize: Tokens.font.size.extraLarge
font.weight: 600
font: Tokens.font.body.builders.large.size(28).weight(Font.DemiBold).build()
}
Loader {
@ -120,7 +119,7 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.bottomMargin: -Tokens.padding.large * 2
Layout.bottomMargin: -Tokens.padding.extraLargeIncreased
asynchronous: true
active: {
@ -173,12 +172,11 @@ Item {
spacing: Tokens.spacing.small
RowLayout {
spacing: Tokens.spacing.smaller
spacing: Tokens.spacing.medium
StyledText {
text: qsTr("Appearance")
font.pointSize: Tokens.font.size.large
font.weight: 500
font: Tokens.font.body.builders.large.weight(Font.Medium).build()
}
Item {

View file

@ -19,7 +19,7 @@ CollapsibleSection {
showBackground: true
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true

View file

@ -37,10 +37,9 @@ CollapsibleSection {
}
StyledText {
Layout.topMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.spacing.medium
text: qsTr("Desktop Clock")
font.pointSize: Tokens.font.size.larger
font.weight: 500
font: Tokens.font.body.builders.large.weight(Font.Medium).build()
}
SwitchRow {
@ -69,8 +68,7 @@ CollapsibleSection {
StyledText {
text: qsTr("Positioning")
font.pointSize: Tokens.font.size.larger
font.weight: 500
font: Tokens.font.body.builders.large.weight(Font.Medium).build()
}
SplitButtonRow {
@ -160,8 +158,7 @@ CollapsibleSection {
StyledText {
text: qsTr("Shadow")
font.pointSize: Tokens.font.size.larger
font.weight: 500
font: Tokens.font.body.builders.large.weight(Font.Medium).build()
}
SwitchRow {
@ -174,7 +171,7 @@ CollapsibleSection {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true
@ -199,7 +196,7 @@ CollapsibleSection {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true
@ -229,8 +226,7 @@ CollapsibleSection {
StyledText {
text: qsTr("Background")
font.pointSize: Tokens.font.size.larger
font.weight: 500
font: Tokens.font.body.builders.large.weight(Font.Medium).build()
}
SwitchRow {
@ -252,7 +248,7 @@ CollapsibleSection {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true
@ -278,10 +274,9 @@ CollapsibleSection {
}
StyledText {
Layout.topMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.spacing.medium
text: qsTr("Visualiser")
font.pointSize: Tokens.font.size.larger
font.weight: 500
font: Tokens.font.body.builders.large.weight(Font.Medium).build()
}
SwitchRow {
@ -303,7 +298,7 @@ CollapsibleSection {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true
@ -328,7 +323,7 @@ CollapsibleSection {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true

View file

@ -19,7 +19,7 @@ CollapsibleSection {
showBackground: true
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true
@ -43,7 +43,7 @@ CollapsibleSection {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true

View file

@ -18,7 +18,7 @@ CollapsibleSection {
ColumnLayout {
Layout.fillWidth: true
spacing: Tokens.spacing.small / 2
spacing: Tokens.spacing.extraSmall
Repeater {
model: Schemes.list
@ -32,10 +32,10 @@ CollapsibleSection {
readonly property bool isCurrent: schemeKey === Schemes.currentScheme
color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
border.width: isCurrent ? 1 : 0
border.color: Colours.palette.m3primary
implicitHeight: schemeRow.implicitHeight + Tokens.padding.normal * 2
implicitHeight: schemeRow.implicitHeight + Tokens.padding.medium * 2
StateLayer {
onClicked: {
@ -65,9 +65,9 @@ CollapsibleSection {
id: schemeRow
anchors.fill: parent
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledRect {
id: preview
@ -87,7 +87,7 @@ CollapsibleSection {
visible: false
text: "circle"
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
}
Item {
@ -116,12 +116,12 @@ CollapsibleSection {
StyledText {
text: modelData.flavour ?? ""
font.pointSize: Tokens.font.size.normal
font: Tokens.font.body.medium
}
StyledText {
text: modelData.name ?? ""
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
color: Colours.palette.m3outline
elide: Text.ElideRight
@ -137,7 +137,7 @@ CollapsibleSection {
sourceComponent: MaterialIcon {
text: "check"
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
}
}
}

View file

@ -18,7 +18,7 @@ CollapsibleSection {
ColumnLayout {
Layout.fillWidth: true
spacing: Tokens.spacing.small / 2
spacing: Tokens.spacing.extraSmall
Repeater {
model: M3Variants.list
@ -29,10 +29,10 @@ CollapsibleSection {
Layout.fillWidth: true
color: Qt.alpha(Colours.tPalette.m3surfaceContainer, modelData.variant === Schemes.currentVariant ? Colours.tPalette.m3surfaceContainer.a : 0)
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
border.width: modelData.variant === Schemes.currentVariant ? 1 : 0
border.color: Colours.palette.m3primary
implicitHeight: variantRow.implicitHeight + Tokens.padding.normal * 2
implicitHeight: variantRow.implicitHeight + Tokens.padding.medium * 2
StateLayer {
onClicked: {
@ -62,27 +62,27 @@ CollapsibleSection {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
MaterialIcon {
text: modelData.icon
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
fill: modelData.variant === Schemes.currentVariant ? 1 : 0
}
StyledText {
Layout.fillWidth: true
text: modelData.name
font.weight: modelData.variant === Schemes.currentVariant ? 500 : 400
font: modelData.variant === Schemes.currentVariant ? Tokens.font.body.builders.small.weight(Font.Medium).build() : Tokens.font.body.builders.small.weight(Font.Normal).build()
}
MaterialIcon {
visible: modelData.variant === Schemes.currentVariant
text: "check"
color: Colours.palette.m3primary
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
}
}
}

View file

@ -38,7 +38,7 @@ CollapsibleSection {
property alias contentHeight: sansFontList.contentHeight
clip: true
spacing: Tokens.spacing.small / 2
spacing: Tokens.spacing.extraSmall
model: Qt.fontFamilies()
StyledScrollBar.vertical: StyledScrollBar {
@ -52,10 +52,10 @@ CollapsibleSection {
width: ListView.view.width
color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
border.width: isCurrent ? 1 : 0
border.color: Colours.palette.m3primary
implicitHeight: fontFamilySansRow.implicitHeight + Tokens.padding.normal * 2
implicitHeight: fontFamilySansRow.implicitHeight + Tokens.padding.medium * 2
StateLayer {
onClicked: {
@ -70,13 +70,13 @@ CollapsibleSection {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
text: modelData
font.pointSize: Tokens.font.size.normal
font: Tokens.font.body.medium
}
Item {
@ -90,7 +90,7 @@ CollapsibleSection {
sourceComponent: MaterialIcon {
text: "check"
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
}
}
}
@ -119,7 +119,7 @@ CollapsibleSection {
property alias contentHeight: monoFontList.contentHeight
clip: true
spacing: Tokens.spacing.small / 2
spacing: Tokens.spacing.extraSmall
model: Qt.fontFamilies()
StyledScrollBar.vertical: StyledScrollBar {
@ -133,10 +133,10 @@ CollapsibleSection {
width: ListView.view.width
color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
border.width: isCurrent ? 1 : 0
border.color: Colours.palette.m3primary
implicitHeight: fontFamilyMonoRow.implicitHeight + Tokens.padding.normal * 2
implicitHeight: fontFamilyMonoRow.implicitHeight + Tokens.padding.medium * 2
StateLayer {
onClicked: {
@ -151,13 +151,13 @@ CollapsibleSection {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
text: modelData
font.pointSize: Tokens.font.size.normal
font: Tokens.font.body.medium
}
Item {
@ -171,7 +171,7 @@ CollapsibleSection {
sourceComponent: MaterialIcon {
text: "check"
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
}
}
}
@ -202,7 +202,7 @@ CollapsibleSection {
property alias contentHeight: materialFontList.contentHeight
clip: true
spacing: Tokens.spacing.small / 2
spacing: Tokens.spacing.extraSmall
model: Qt.fontFamilies().filter(f => f.startsWith("Material Symbols"))
StyledScrollBar.vertical: StyledScrollBar {
@ -216,10 +216,10 @@ CollapsibleSection {
width: ListView.view.width
color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
border.width: isCurrent ? 1 : 0
border.color: Colours.palette.m3primary
implicitHeight: fontFamilyMaterialRow.implicitHeight + Tokens.padding.normal * 2
implicitHeight: fontFamilyMaterialRow.implicitHeight + Tokens.padding.medium * 2
StateLayer {
onClicked: {
@ -234,13 +234,13 @@ CollapsibleSection {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
text: modelData
font.pointSize: Tokens.font.size.normal
font: Tokens.font.body.medium
}
Item {
@ -254,7 +254,7 @@ CollapsibleSection {
sourceComponent: MaterialIcon {
text: "check"
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
}
}
}
@ -264,7 +264,7 @@ CollapsibleSection {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true

View file

@ -19,7 +19,7 @@ CollapsibleSection {
showBackground: true
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true
@ -43,7 +43,7 @@ CollapsibleSection {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true
@ -67,7 +67,7 @@ CollapsibleSection {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true

View file

@ -28,7 +28,7 @@ CollapsibleSection {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true
@ -53,7 +53,7 @@ CollapsibleSection {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
SliderInput {
Layout.fillWidth: true

View file

@ -38,16 +38,15 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
RowLayout {
Layout.fillWidth: true
spacing: Tokens.spacing.smaller
spacing: Tokens.spacing.medium
StyledText {
text: qsTr("Audio")
font.pointSize: Tokens.font.size.large
font.weight: 500
font: Tokens.font.body.builders.large.weight(Font.Medium).build()
}
Item {
@ -72,8 +71,7 @@ Item {
StyledText {
text: qsTr("Devices (%1)").arg(Audio.sinks.length)
font.pointSize: Tokens.font.size.normal
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
}
}
@ -93,8 +91,8 @@ Item {
Layout.fillWidth: true
color: Audio.sink?.id === modelData.id ? Colours.layer(Colours.palette.m3surfaceContainer, 2) : "transparent"
radius: Tokens.rounding.normal
implicitHeight: outputRowLayout.implicitHeight + Tokens.padding.normal * 2
radius: Tokens.rounding.large
implicitHeight: outputRowLayout.implicitHeight + Tokens.padding.medium * 2
StateLayer {
onClicked: {
@ -108,13 +106,13 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
MaterialIcon {
text: Audio.sink?.id === modelData.id ? "speaker" : "speaker_group"
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
fill: Audio.sink?.id === modelData.id ? 1 : 0
}
@ -124,7 +122,7 @@ Item {
maximumLineCount: 1
text: modelData.description || qsTr("Unknown")
font.weight: Audio.sink?.id === modelData.id ? 500 : 400
font: Audio.sink?.id === modelData.id ? Tokens.font.body.builders.small.weight(Font.Medium).build() : Tokens.font.body.builders.small.weight(Font.Normal).build()
}
}
}
@ -149,8 +147,7 @@ Item {
StyledText {
text: qsTr("Devices (%1)").arg(Audio.sources.length)
font.pointSize: Tokens.font.size.normal
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
}
}
@ -170,8 +167,8 @@ Item {
Layout.fillWidth: true
color: Audio.source?.id === modelData.id ? Colours.layer(Colours.palette.m3surfaceContainer, 2) : "transparent"
radius: Tokens.rounding.normal
implicitHeight: inputRowLayout.implicitHeight + Tokens.padding.normal * 2
radius: Tokens.rounding.large
implicitHeight: inputRowLayout.implicitHeight + Tokens.padding.medium * 2
StateLayer {
onClicked: {
@ -185,13 +182,13 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Tokens.padding.normal
anchors.margins: Tokens.padding.medium
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
MaterialIcon {
text: "mic"
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
fill: Audio.source?.id === modelData.id ? 1 : 0
}
@ -201,7 +198,7 @@ Item {
maximumLineCount: 1
text: modelData.description || qsTr("Unknown")
font.weight: Audio.source?.id === modelData.id ? 500 : 400
font: Audio.source?.id === modelData.id ? Tokens.font.body.builders.small.weight(Font.Medium).build() : Tokens.font.body.builders.small.weight(Font.Normal).build()
}
}
}
@ -229,7 +226,7 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
SettingsHeader {
icon: "volume_up"
@ -242,7 +239,7 @@ Item {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
ColumnLayout {
Layout.fillWidth: true
@ -250,12 +247,11 @@ Item {
RowLayout {
Layout.fillWidth: true
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
text: qsTr("Volume")
font.pointSize: Tokens.font.size.normal
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
}
Item {
@ -306,15 +302,15 @@ Item {
StyledText {
text: "%"
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.normal
font: Tokens.font.body.medium
opacity: Audio.muted ? 0.5 : 1
}
StyledRect {
implicitWidth: implicitHeight
implicitHeight: muteIcon.implicitHeight + Tokens.padding.normal * 2
implicitHeight: muteIcon.implicitHeight + Tokens.padding.medium * 2
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
color: Audio.muted ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
StateLayer {
@ -339,7 +335,7 @@ Item {
id: outputVolumeSlider
Layout.fillWidth: true
implicitHeight: Tokens.padding.normal * 3
implicitHeight: Tokens.padding.medium * 3
value: Audio.volume
enabled: !Audio.muted
@ -360,7 +356,7 @@ Item {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
ColumnLayout {
Layout.fillWidth: true
@ -368,12 +364,11 @@ Item {
RowLayout {
Layout.fillWidth: true
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
text: qsTr("Volume")
font.pointSize: Tokens.font.size.normal
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
}
Item {
@ -424,15 +419,15 @@ Item {
StyledText {
text: "%"
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.normal
font: Tokens.font.body.medium
opacity: Audio.sourceMuted ? 0.5 : 1
}
StyledRect {
implicitWidth: implicitHeight
implicitHeight: muteInputIcon.implicitHeight + Tokens.padding.normal * 2
implicitHeight: muteInputIcon.implicitHeight + Tokens.padding.medium * 2
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
color: Audio.sourceMuted ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
StateLayer {
@ -457,7 +452,7 @@ Item {
id: inputVolumeSlider
Layout.fillWidth: true
implicitHeight: Tokens.padding.normal * 3
implicitHeight: Tokens.padding.medium * 3
value: Audio.sourceVolume
enabled: !Audio.sourceMuted
@ -478,7 +473,7 @@ Item {
}
SectionContainer {
contentSpacing: Tokens.spacing.normal
contentSpacing: Tokens.spacing.medium
ColumnLayout {
Layout.fillWidth: true
@ -493,15 +488,15 @@ Item {
required property int index
Layout.fillWidth: true
spacing: Tokens.spacing.smaller
spacing: Tokens.spacing.medium
RowLayout {
Layout.fillWidth: true
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
MaterialIcon {
text: "apps"
font.pointSize: Tokens.font.size.normal
fontStyle: Tokens.font.icon.medium
fill: 0
}
@ -510,8 +505,7 @@ Item {
elide: Text.ElideRight
maximumLineCount: 1
text: Audio.getStreamName(modelData)
font.pointSize: Tokens.font.size.normal
font.weight: 500
font: Tokens.font.body.builders.medium.weight(Font.Medium).build()
}
StyledInputField {
@ -558,15 +552,15 @@ Item {
StyledText {
text: "%"
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.normal
font: Tokens.font.body.medium
opacity: Audio.getStreamMuted(modelData) ? 0.5 : 1
}
StyledRect {
implicitWidth: implicitHeight
implicitHeight: streamMuteIcon.implicitHeight + Tokens.padding.normal * 2
implicitHeight: streamMuteIcon.implicitHeight + Tokens.padding.medium * 2
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
color: Audio.getStreamMuted(modelData) ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
StateLayer {
@ -587,7 +581,7 @@ Item {
StyledSlider {
Layout.fillWidth: true
implicitHeight: Tokens.padding.normal * 3
implicitHeight: Tokens.padding.medium * 3
value: Audio.getStreamVolume(modelData)
enabled: !Audio.getStreamMuted(modelData)
@ -617,7 +611,7 @@ Item {
visible: Audio.streams.length === 0
text: qsTr("No applications currently playing audio")
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
horizontalAlignment: Text.AlignHCenter
}
}

View file

@ -54,13 +54,12 @@ StyledFlickable {
sections: [
Component {
ColumnLayout {
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
Layout.topMargin: Tokens.spacing.large
Layout.topMargin: Tokens.spacing.largeIncreased
text: qsTr("Connection status")
font.pointSize: Tokens.font.size.larger
font.weight: 500
font: Tokens.font.body.builders.large.weight(Font.Medium).build()
}
StyledText {
@ -70,9 +69,9 @@ StyledFlickable {
StyledRect {
Layout.fillWidth: true
implicitHeight: deviceStatus.implicitHeight + Tokens.padding.large * 2
implicitHeight: deviceStatus.implicitHeight + Tokens.padding.extraLargeIncreased
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
color: Colours.tPalette.m3surfaceContainer
ColumnLayout {
@ -83,7 +82,7 @@ StyledFlickable {
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.larger
spacing: Tokens.spacing.large
Toggle {
label: qsTr("Connected")
@ -113,13 +112,12 @@ StyledFlickable {
},
Component {
ColumnLayout {
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
Layout.topMargin: Tokens.spacing.large
Layout.topMargin: Tokens.spacing.largeIncreased
text: qsTr("Device properties")
font.pointSize: Tokens.font.size.larger
font.weight: 500
font: Tokens.font.body.builders.large.weight(Font.Medium).build()
}
StyledText {
@ -129,9 +127,9 @@ StyledFlickable {
StyledRect {
Layout.fillWidth: true
implicitHeight: deviceProps.implicitHeight + Tokens.padding.large * 2
implicitHeight: deviceProps.implicitHeight + Tokens.padding.extraLargeIncreased
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
color: Colours.tPalette.m3surfaceContainer
ColumnLayout {
@ -142,7 +140,7 @@ StyledFlickable {
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.larger
spacing: Tokens.spacing.large
RowLayout {
Layout.fillWidth: true
@ -167,7 +165,7 @@ StyledFlickable {
PropertyChanges {
renameDevice.implicitHeight: deviceNameEdit.implicitHeight
renameLabel.opacity: 0
deviceNameEdit.padding: root.Tokens.padding.normal
deviceNameEdit.padding: root.Tokens.padding.medium
}
}
@ -187,7 +185,7 @@ StyledFlickable {
text: qsTr("Device name")
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.small
font: Tokens.font.label.small
}
StyledTextField {
@ -196,7 +194,7 @@ StyledFlickable {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: renameLabel.bottom
anchors.leftMargin: root.session.bt.editingDeviceName ? 0 : -Tokens.padding.normal
anchors.leftMargin: root.session.bt.editingDeviceName ? 0 : -Tokens.padding.medium
text: root.device?.name ?? ""
readOnly: !root.session.bt.editingDeviceName
@ -205,11 +203,11 @@ StyledFlickable {
root.device.name = text;
}
leftPadding: Tokens.padding.normal
rightPadding: Tokens.padding.normal
leftPadding: Tokens.padding.medium
rightPadding: Tokens.padding.medium
background: StyledRect {
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
border.width: 2
border.color: Colours.palette.m3primary
opacity: root.session.bt.editingDeviceName ? 1 : 0
@ -231,9 +229,9 @@ StyledFlickable {
StyledRect {
implicitWidth: implicitHeight
implicitHeight: cancelEditIcon.implicitHeight + Tokens.padding.smaller * 2
implicitHeight: cancelEditIcon.implicitHeight + Tokens.padding.large
radius: Tokens.rounding.small
radius: Tokens.rounding.medium
color: Colours.palette.m3secondaryContainer
opacity: root.session.bt.editingDeviceName ? 1 : 0
scale: root.session.bt.editingDeviceName ? 1 : 0.5
@ -270,9 +268,9 @@ StyledFlickable {
StyledRect {
implicitWidth: implicitHeight
implicitHeight: editIcon.implicitHeight + Tokens.padding.smaller * 2
implicitHeight: editIcon.implicitHeight + Tokens.padding.large
radius: root.session.bt.editingDeviceName ? Tokens.rounding.small : implicitHeight / 2 * Math.min(1, Tokens.rounding.scale)
radius: root.session.bt.editingDeviceName ? Tokens.rounding.medium : implicitHeight / 2 * Math.min(1, Tokens.rounding.scale)
color: Qt.alpha(Colours.palette.m3primary, root.session.bt.editingDeviceName ? 1 : 0)
StateLayer {
@ -319,13 +317,12 @@ StyledFlickable {
},
Component {
ColumnLayout {
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
Layout.topMargin: Tokens.spacing.large
Layout.topMargin: Tokens.spacing.largeIncreased
text: qsTr("Device information")
font.pointSize: Tokens.font.size.larger
font.weight: 500
font: Tokens.font.body.builders.large.weight(Font.Medium).build()
}
StyledText {
@ -335,9 +332,9 @@ StyledFlickable {
StyledRect {
Layout.fillWidth: true
implicitHeight: deviceInfo.implicitHeight + Tokens.padding.large * 2
implicitHeight: deviceInfo.implicitHeight + Tokens.padding.extraLargeIncreased
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
color: Colours.tPalette.m3surfaceContainer
ColumnLayout {
@ -348,7 +345,7 @@ StyledFlickable {
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.small / 2
spacing: Tokens.spacing.extraSmall
StyledText {
text: root.device?.batteryAvailable ? qsTr("Device battery (%1%)").arg(root.device.battery * 100) : qsTr("Battery unavailable")
@ -357,10 +354,10 @@ StyledFlickable {
RowLayout {
id: batteryPercent
Layout.topMargin: Tokens.spacing.small / 2
Layout.topMargin: Tokens.spacing.extraSmall
Layout.fillWidth: true
Layout.preferredHeight: Tokens.padding.smaller
spacing: Tokens.spacing.small / 2
Layout.preferredHeight: Tokens.padding.small
spacing: Tokens.spacing.extraSmall
StyledRect {
Layout.fillWidth: true
@ -382,47 +379,47 @@ StyledFlickable {
}
StyledText {
Layout.topMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.spacing.medium
text: qsTr("Dbus path")
}
StyledText {
text: root.device?.dbusPath ?? ""
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
StyledText {
Layout.topMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.spacing.medium
text: qsTr("MAC address")
}
StyledText {
text: root.device?.address ?? ""
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
StyledText {
Layout.topMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.spacing.medium
text: qsTr("Bonded")
}
StyledText {
text: root.device?.bonded ? qsTr("Yes") : qsTr("No")
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
StyledText {
Layout.topMargin: Tokens.spacing.normal
Layout.topMargin: Tokens.spacing.medium
text: qsTr("System name")
}
StyledText {
text: root.device?.deviceName ?? ""
color: Colours.palette.m3outline
font.pointSize: Tokens.font.size.small
font: Tokens.font.body.small
}
}
}
@ -435,7 +432,7 @@ StyledFlickable {
ColumnLayout {
anchors.right: fabRoot.right
anchors.bottom: fabRoot.top
anchors.bottomMargin: Tokens.padding.normal
anchors.bottomMargin: Tokens.padding.medium
Repeater {
id: fabMenu
@ -467,7 +464,7 @@ StyledFlickable {
Layout.alignment: Qt.AlignRight
implicitHeight: fabMenuItemInner.implicitHeight + Tokens.padding.larger * 2
implicitHeight: fabMenuItemInner.implicitHeight + Tokens.padding.medium * 2
radius: Tokens.rounding.full
color: Colours.palette.m3primaryContainer
@ -479,7 +476,7 @@ StyledFlickable {
when: root.session.bt.fabMenuOpen
PropertyChanges {
fabMenuItem.implicitWidth: fabMenuItemInner.implicitWidth + root.Tokens.padding.large * 2
fabMenuItem.implicitWidth: fabMenuItemInner.implicitWidth + root.Tokens.padding.extraLargeIncreased
fabMenuItem.opacity: 1
fabMenuItemInner.opacity: 1
}
@ -544,7 +541,7 @@ StyledFlickable {
id: fabMenuItemInner
anchors.centerIn: parent
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
opacity: 0
MaterialIcon {
@ -557,7 +554,7 @@ StyledFlickable {
animate: true
text: (root.device && root.device[`${fabMenuItem.modelData.name}ed`] ? fabMenuItem.modelData.name === "connect" ? "dis" : "un" : "") + fabMenuItem.modelData.name
color: Colours.palette.m3onPrimaryContainer
font.capitalization: Font.Capitalize
font: Tokens.font.body.builders.small.capitalisation(Font.Capitalize).build()
Layout.preferredWidth: implicitWidth
Behavior on Layout.preferredWidth {
@ -589,7 +586,7 @@ StyledFlickable {
implicitWidth: 64
implicitHeight: 64
radius: Tokens.rounding.normal
radius: Tokens.rounding.large
color: root.session.bt.fabMenuOpen ? Colours.palette.m3primary : Colours.palette.m3primaryContainer
states: State {
@ -600,7 +597,7 @@ StyledFlickable {
fabBg.implicitWidth: 48
fabBg.implicitHeight: 48
fabBg.radius: 48 / 2
fab.font.pointSize: Tokens.font.size.larger
fab.fontStyle: Tokens.font.icon.large
}
}
@ -638,7 +635,7 @@ StyledFlickable {
animate: true
text: root.session.bt.fabMenuOpen ? "close" : "settings"
color: root.session.bt.fabMenuOpen ? Colours.palette.m3onPrimary : Colours.palette.m3onPrimaryContainer
font.pointSize: Tokens.font.size.large
fontStyle: Tokens.font.icon.large
fill: 1
}
}
@ -650,7 +647,7 @@ StyledFlickable {
property alias toggle: toggle
Layout.fillWidth: true
spacing: Tokens.spacing.normal
spacing: Tokens.spacing.medium
StyledText {
Layout.fillWidth: true

Some files were not shown because too many files have changed in this diff Show more