feat: complete Material Design 3 QML branding rework + antergos-lsb-release

Complete rewrite of the Calamares QML branding with a pure Material
Design 3 (Material You) dark theme. No longer KaOS-derived — all QML
written from scratch for Antergos NeXT.

calamares-sidebar.qml:
  — M3 CenterAlignedTopAppBar at 64dp height with #20252B surface
  — Left: 34dp product logo + "Antergos NeXT" wordmark (17dp Medium,
    0.3 letter-spacing)
  — Right: step indicator dots (7dp circles, active 10dp pill #4A9EFF)
  — Bottom: 3dp animated linear progress bar (400ms OutCubic easing)
  — Subtle level-1 drop shadow (4dp radius, rgba(0,0,0,0.4))

calamares-navigation.qml:
  — M3 Navigation Bar at 68dp height
  — Buttons at 42dp height, 21dp pill radius (per M3 Label Large)
  — Sentence case text ("Back", "Next", "Cancel") in Roboto Medium 14px
  — Back: text button with ← arrow, on-surface hover rgba(0.89,0.89,0.90,0.06)
  — Cancel: text button in error #FFB4AB, error hover rgba(1.0,0.71,0.67,0.07)
  — Next: filled pill 120x42dp in primary #4A9EFF, hover #3B8BDE
  — 120ms ColorAnimation on all button backgrounds
  — Inline Unicode arrows (← →) instead of missing SVG icon files

show.qml:
  — Full-bleed background image with 55% dark overlay + vertical
    gradient (top 15% → transparent → bottom 30%)
  — M3 Elevated Card: 460x380dp, 12dp corner (M3 CornerMedium),
    #2B2930 fill (M3 Surface Container High), 32dp content padding
  — Card shadow: 40dp blur, 56 samples, rgba(0,0,0,0.5)
  — Subtle 1px border at rgba(255,255,255,0.04) for edge definition
  — Title: 26dp Roboto Medium #FFFFFF
  — Body: 14dp Roboto Normal #C4C6D0, 1.55 line-height
  — Footer: 12dp Roboto Medium #8E9099 (M3 Outline)
  — 5 slides with auto-advance every 12s
  — Crossfade transition: 100ms out + 160ms in with OutQuad/InQuad
  — Bottom-left: 140dp wordmark logo at 45% opacity
  — Center-bottom: animated dot indicators matching sidebar style

Slider.qml:
  — Crossfade between Dia slides using SequentialAnimation
  — Removed Animator types (Qt6 render-thread safe)
  — Clean Column layout with centered content

Dia.qml:
  — Unchanged data model (title, body, footer, image)

antergos-lsb-release:
  — New package replacing lsb-release with Antergos NeXT branding
  — /etc/lsb-release shows DISTRIB_ID="Antergos"
  — Added to packages.yaml for CI builds
This commit is contained in:
2026-07-03 23:43:02 +02:00
parent afb154c7d2
commit 09bff48d8b
6 changed files with 375 additions and 388 deletions
+1
View File
@@ -1,4 +1,5 @@
packages: packages:
- antergos-lsb-release
- antergos-release - antergos-release
- antergos-wallpapers - antergos-wallpapers
- yay - yay
+22
View File
@@ -0,0 +1,22 @@
# Maintainer: Antergos NeXT <antergos-next@github>
pkgname=antergos-lsb-release
pkgver=2.0
pkgrel=1
pkgdesc='Antergos NeXT LSB release file'
arch=('any')
url="https://github.com/Antergos-NeXT"
license=('GPL2')
conflicts=('lsb-release')
replaces=('lsb-release')
provides=('lsb-release')
package() {
install -dm755 "$pkgdir/etc"
cat > "$pkgdir/etc/lsb-release" << EOF
DISTRIB_ID="Antergos"
DISTRIB_RELEASE="rolling"
DISTRIB_DESCRIPTION="Antergos NeXT"
DISTRIB_CODENAME=antergos
EOF
}
@@ -2,172 +2,84 @@ import QtQuick 2.15
Item { Item {
property list<Dia> slides property list<Dia> slides
property list<Dia> img
property int currentSlideIndex: 0 property int currentSlideIndex: 0
property int _currentSlideIndex: 0 property int _currentSlideIndex: 0
property int slidesSize: slides.length
property bool firstIteration: true
function reset() { function reset() {
currentSlideIndex = 0; currentSlideIndex = 0
firstIteration = true; _currentSlideIndex = 0
wrapper.opacity = 1
} }
onCurrentSlideIndexChanged: { onCurrentSlideIndexChanged: {
if (currentSlideIndex >= slidesSize) { if (currentSlideIndex >= slides.length) {
firstIteration = false; currentSlideIndex = 0
currentSlideIndex = 0; }
if (_currentSlideIndex !== currentSlideIndex) {
slideOut.start()
}
} }
transitionAnimation.start(); Item {
} id: wrapper
anchors.fill: parent
Column { Column {
anchors.fill: parent anchors.centerIn: parent
spacing: 10 width: parent.width
spacing: 0
Text { Text {
id: titleText id: titleText
font { font {
family: "Raleway" family: "Roboto"
capitalization: Font.AllUppercase weight: Font.Medium
weight: Font.DemiBold pixelSize: 26
pointSize: 16
} }
color: "white" color: "#FFFFFF"
text: slides[_currentSlideIndex].title text: slides[_currentSlideIndex].title
wrapMode: Text.WordWrap
width: parent.width
lineHeight: 1.25
bottomPadding: 20
} }
Text { Text {
id: bodyText id: bodyText
width: parent.width
font { font {
family: "Raleway" family: "Roboto"
pointSize: 12 weight: Font.Normal
weight: Font.DemiBold pixelSize: 14
} }
width: 400 color: "#C4C6D0"
color: "white"
text: slides[_currentSlideIndex].body text: slides[_currentSlideIndex].body
wrapMode: Text.Wrap wrapMode: Text.WordWrap
lineHeight: 1.55
bottomPadding: 20
} }
Text { Text {
id: footerText id: footerText
font { font {
family: "Raleway" family: "Roboto"
weight: Font.Light weight: Font.Medium
pointSize: 12 pixelSize: 12
} }
width: 400 color: "#8E9099"
color: "white"
text: slides[_currentSlideIndex].footer ?? "" text: slides[_currentSlideIndex].footer ?? ""
wrapMode: Text.Wrap wrapMode: Text.WordWrap
width: parent.width
lineHeight: 1.4
} }
Image {
id: icon
source: slides[_currentSlideIndex].image
width: 250
height: 250
} }
} }
SequentialAnimation { SequentialAnimation {
id: transitionAnimation id: slideOut
property int duration: 700 NumberAnimation { target: wrapper; property: "opacity"; to: 0; duration: 100; easing.type: Easing.OutQuad }
PropertyAction { target: wrapper; property: "opacity"; value: 0 }
ParallelAnimation { ScriptAction { script: _currentSlideIndex = currentSlideIndex }
OpacityAnimator { NumberAnimation { target: wrapper; property: "opacity"; to: 1; duration: 160; easing.type: Easing.InQuad }
target: titleText
from: 1.0
to: 0.0
duration: transitionAnimation.duration
}
OpacityAnimator {
target: bodyText
from: 1.0
to: 0.0
duration: transitionAnimation.duration
}
OpacityAnimator {
target: footerText
from: 1.0
to: 0.0
duration: transitionAnimation.duration
}
OpacityAnimator {
target: icon
from: 1.0
to: 0.0
duration: 2000
}
XAnimator {
target: titleText
from: 0
to: -30
duration: transitionAnimation.duration
}
XAnimator {
target: bodyText
from: 0
to: -25
duration: transitionAnimation.duration
}
XAnimator {
target: footerText
from: 0
to: -25
duration: transitionAnimation.duration
}
}
ScriptAction {
script: _currentSlideIndex = currentSlideIndex
}
ParallelAnimation {
OpacityAnimator {
target: titleText
from: 0.0
to: 1.0
duration: transitionAnimation.duration
}
OpacityAnimator {
target: bodyText
from: 0.0
to: 1.0
duration: transitionAnimation.duration
}
OpacityAnimator {
target: footerText
from: 0.0
to: 1.0
duration: transitionAnimation.duration
}
OpacityAnimator {
target: icon
from: 0.0
to: 1.0
duration: 2000
}
XAnimator {
target: titleText
from: 30
to: 0
duration: transitionAnimation.duration
}
XAnimator {
target: bodyText
from: 25
to: 0
duration: transitionAnimation.duration
}
XAnimator {
target: footerText
from: 25
to: 0
duration: transitionAnimation.duration
}
}
} }
} }
@@ -1,166 +1,119 @@
import io.calamares.ui 1.0 import io.calamares.ui 1.0
import io.calamares.core 1.0 import io.calamares.core 1.0
import QtQuick 2.3 import QtQuick 2.15
import QtQuick.Controls 2.10 import QtQuick.Layouts 1.15
import QtQuick.Layouts 1.3 import QtQuick.Controls 2.15
import Qt5Compat.GraphicalEffects
Rectangle { Rectangle {
id: navigationBar; id: bottomBar
color: Branding.styleString( Branding.SidebarBackground ); color: "#20252B"
height: parent.height; height: 68
width: 64; width: parent ? parent.width : 1024
ColumnLayout { layer.enabled: true
id: buttonBar layer.effect: DropShadow {
anchors.fill: parent; transparentBorder: true
spacing: 1 radius: 4
samples: 8
Image { color: Qt.rgba(0, 0, 0, 0.4)
Layout.topMargin: 1;
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
id: logo;
width: 62;
height: width;
source: "file:/" + Branding.imagePath(Branding.ProductLogo);
sourceSize.width: width;
sourceSize.height: height;
} }
Rectangle { RowLayout {
id: debugArea anchors.fill: parent
Layout.fillWidth: true; anchors.leftMargin: 12
height: 35 anchors.rightMargin: 20
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop spacing: 8
Layout.topMargin: 40
color: Branding.styleString( mouseAreaDebug.containsMouse ? Branding.SidebarBackgroundCurrent : Branding.SidebarBackground);
visible: debug.enabled
MouseArea { Button {
id: mouseAreaDebug id: backButton
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
Text {
anchors.centerIn: parent
text: qsTr("Debug")
color: Branding.styleString( mouseAreaDebug.containsMouse ? Branding.SidebarTextCurrent : Branding.SidebarBackground );
font.pointSize : 8
}
onClicked: debug.toggle()
}
}
Item {
Layout.fillHeight: true;
}
Rectangle {
id: backArea
Layout.fillWidth: true;
Layout.preferredHeight: parent.height / 7;
color: mouseBack.containsMouse ? "#2C3E50" : "#1E2935";
enabled: ViewManager.backEnabled;
visible: ViewManager.backAndNextVisible;
MouseArea {
id: mouseBack
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
Text {
anchors.centerIn: parent
text: qsTr("Back") text: qsTr("Back")
color: Branding.styleString( !backArea.enabled ? Branding.SidebarBackground : (mouseBack.containsMouse ? Branding.SidebarTextCurrent : Branding.SidebarText )); flat: true
font.pointSize : 8 enabled: ViewManager.backEnabled
implicitHeight: 42
font {
family: "Roboto"
weight: Font.Medium
pixelSize: 14
} }
Image { contentItem: Text {
source: "pan-start-symbolic.svg" text: "← " + parent.text
anchors.centerIn: parent font: parent.font
anchors.verticalCenterOffset : 18 color: parent.enabled ? "#E3E2E6" : Qt.rgba(0.89, 0.89, 0.90, 0.35)
fillMode: Image.PreserveAspectFit horizontalAlignment: Text.AlignHCenter
height: 32 verticalAlignment: Text.AlignVCenter
opacity: backArea.enabled ? 1 : 0.2 leftPadding: 16
rightPadding: 16
}
background: Rectangle {
color: parent.hovered && parent.enabled
? Qt.rgba(0.89, 0.89, 0.90, 0.06)
: "transparent"
radius: 21
Behavior on color { ColorAnimation { duration: 120 } }
}
onClicked: ViewManager.back()
} }
onClicked: { ViewManager.back(); } Item { Layout.fillWidth: true }
}
}
Rectangle { Button {
id: nextArea id: cancelButton
Layout.preferredHeight: parent.height / 7;
Layout.fillWidth: true
color: mouseNext.containsMouse ? "#2C3E50" : "#1E2935";
enabled: ViewManager.nextEnabled;
visible: ViewManager.backAndNextVisible;
MouseArea {
id: mouseNext
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
Text {
anchors.centerIn: parent
text: qsTr("Next")
color: Branding.styleString( !nextArea.enabled ? Branding.SidebarBackground : (mouseNext.containsMouse ? Branding.SidebarTextCurrent : Branding.SidebarText ));
font.pointSize : 8
}
Image {
source: "pan-end-symbolic.svg"
anchors.centerIn: parent
anchors.verticalCenterOffset : 18
fillMode: Image.PreserveAspectFit
height: 32
opacity: nextArea.enabled ? 1 : 0.2
}
onClicked: { ViewManager.next(); }
}
}
Rectangle {
id: cancelArea
height: parent.height / 7;
Layout.fillWidth: true;
Layout.bottomMargin: 48;
color: mouseCancel.containsMouse ? "#2C3E50" : "#1E2935";
enabled: ViewManager.quitEnabled;
visible: ViewManager.quitVisible && ( ViewManager.currentStepIndex < ViewManager.rowCount()-1);
ToolTip {
width: 59
visible: mouseCancel.containsMouse
timeout: 5000
delay: 1000
text: ViewManager.quitTooltip;
}
MouseArea {
id: mouseCancel
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
Text {
anchors.centerIn: parent
text: qsTr("Cancel") text: qsTr("Cancel")
color: Branding.styleString( !cancelArea.enabled ? Branding.SidebarBackground : (mouseCancel.containsMouse ? Branding.SidebarTextCurrent : Branding.SidebarText )); flat: true
font.pointSize : 8 enabled: ViewManager.quitEnabled
implicitHeight: 42
font {
family: "Roboto"
weight: Font.Medium
pixelSize: 14
} }
Image { contentItem: Text {
source: "draw-rectangle.svg" text: parent.text
anchors.centerIn: parent font: parent.font
anchors.verticalCenterOffset : 18 color: parent.enabled ? "#FFB4AB" : Qt.rgba(1.0, 0.71, 0.67, 0.35)
fillMode: Image.PreserveAspectFit horizontalAlignment: Text.AlignHCenter
height: 9 verticalAlignment: Text.AlignVCenter
opacity: cancelArea.enabled ? 1 : 0.2 leftPadding: 14
rightPadding: 14
}
background: Rectangle {
color: parent.hovered && parent.enabled
? Qt.rgba(1.0, 0.71, 0.67, 0.07)
: "transparent"
radius: 21
Behavior on color { ColorAnimation { duration: 120 } }
}
onClicked: ViewManager.quit()
} }
onClicked: { ViewManager.quit(); } Button {
id: nextButton
text: qsTr("Next")
enabled: ViewManager.nextEnabled
implicitWidth: 120
implicitHeight: 42
font {
family: "Roboto"
weight: Font.Medium
pixelSize: 14
} }
contentItem: Text {
text: parent.text + " →"
font: parent.font
color: "#FFFFFF"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
color: parent.enabled
? (parent.hovered ? "#3B8BDE" : "#4A9EFF")
: Qt.rgba(0.29, 0.62, 1.0, 0.35)
radius: 21
Behavior on color { ColorAnimation { duration: 120 } }
}
onClicked: ViewManager.next()
} }
} }
} }
@@ -1,62 +1,90 @@
import io.calamares.ui 1.0 import io.calamares.ui 1.0
import io.calamares.core 1.0 import io.calamares.core 1.0
import QtQuick 2.3 import QtQuick 2.15
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import Qt5Compat.GraphicalEffects
Rectangle { Rectangle {
id: sideBar; id: topBar
color: Branding.styleString( Branding.SidebarBackground ); color: "#20252B"
height: 48; height: 64
width: parent.width width: parent ? parent.width : 1024
layer.enabled: true
layer.effect: DropShadow {
transparentBorder: true
radius: 4
samples: 8
color: Qt.rgba(0, 0, 0, 0.4)
}
RowLayout { RowLayout {
anchors.fill: parent; anchors.fill: parent
spacing: 0; anchors.leftMargin: 20
anchors.rightMargin: 20
Item { spacing: 14
Layout.fillHeight: true;
}
Repeater {
model: ViewManager
Rectangle {
Layout.leftMargin: 0;
Layout.fillWidth: true;
Layout.alignment: Qt.AlignTop;
height: 42;
radius: 0;
color: Branding.styleString( index == ViewManager.currentStepIndex ? Branding.SidebarBackgroundCurrent : Branding.SidebarBackground );
Text {
anchors.verticalCenter: parent.verticalCenter;
anchors.horizontalCenter: parent.horizontalCenter
x: parent.x + 12;
color: Branding.styleString( index == ViewManager.currentStepIndex ? Branding.SidebarTextCurrent : Branding.SidebarText );
text: qsTr(display);
font.pointSize : index == ViewManager.currentStepIndex ? 10 : 9
}
Rectangle {
height: 2
width: 800
anchors.bottom: parent.bottom;
border.color: Branding.styleString(ViewManager.currentStepIndex === index ? Branding.SidebarTextCurrent : (ViewManager.currentStepIndex >= index ? Branding.SidebarTextCurrent : Branding.SidebarBackgroundCurrent))
border.width: 3
Image { Image {
source: "pan-up-symbolic.svg" id: logo
id: image sourceSize.width: 34
anchors.verticalCenter: parent.verticalCenter; sourceSize.height: 34
anchors.verticalCenterOffset : -3
x: parent.x + 35;
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
height: 32 source: Branding.imagePath(Branding.ProductLogo)
visible: index == ViewManager.currentStepIndex ? true : false Layout.alignment: Qt.AlignVCenter
}
Text {
text: "Antergos NeXT"
color: "#E3E2E6"
font {
family: "Roboto"
weight: Font.Medium
pixelSize: 17
letterSpacing: 0.3
}
Layout.alignment: Qt.AlignVCenter
}
Item { Layout.fillWidth: true }
Row {
spacing: 8
Layout.alignment: Qt.AlignVCenter
Repeater {
id: dotRepeater
model: ViewManager
Rectangle {
width: index === ViewManager.currentStepIndex ? 10 : 7
height: 7
radius: 3.5
color: index === ViewManager.currentStepIndex
? "#4A9EFF" : "#8E9099"
opacity: index === ViewManager.currentStepIndex ? 1 : 0.35
Behavior on width { NumberAnimation { duration: 200 } }
Behavior on color { ColorAnimation { duration: 200 } }
} }
} }
} }
} }
Rectangle {
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
}
height: 3
color: Qt.rgba(0.56, 0.57, 0.60, 0.2)
Rectangle {
height: parent.height
width: parent.width * ((ViewManager.currentStepIndex + 1) / Math.max(dotRepeater.count, 1))
color: "#4A9EFF"
Behavior on width { NumberAnimation { duration: 400; easing.type: Easing.OutCubic } }
}
} }
} }
@@ -1,24 +1,22 @@
import QtQuick 2.15; import QtQuick 2.15
import Qt5Compat.GraphicalEffects
Item { Item {
id: root id: root
width: 920
height: 630
function onActivate() { function onActivate() {
console.log("Slideshow) activated"); timer.restart()
timer.restart(); slider.reset()
slider.reset();
} }
function onLeave() { function onLeave() {
console.log("Slideshow) deactivated");
} }
width: 940
height: 600
Timer { Timer {
id: timer id: timer
interval: 10000 interval: 12000
running: true running: true
repeat: true repeat: true
onTriggered: slider.currentSlideIndex++ onTriggered: slider.currentSlideIndex++
@@ -26,9 +24,10 @@ Item {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
timer.restart(); timer.restart()
slider.currentSlideIndex++; slider.currentSlideIndex++
} }
} }
@@ -36,52 +35,124 @@ Item {
id: background id: background
anchors.fill: parent anchors.fill: parent
source: "background.jpg" source: "background.jpg"
sourceSize.width: parent.width
sourceSize.height: parent.height
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
} }
Rectangle { Rectangle {
anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.55)
}
Rectangle {
anchors.fill: parent
gradient: Gradient {
GradientStop { position: 0.0; color: Qt.rgba(0, 0, 0, 0.15) }
GradientStop { position: 0.5; color: "transparent" }
GradientStop { position: 1.0; color: Qt.rgba(0, 0, 0, 0.3) }
}
}
Rectangle {
id: card
width: 460
height: 380
radius: 12
anchors.centerIn: parent
anchors.horizontalCenterOffset: 40
color: "#2B2930"
layer.enabled: true
layer.effect: DropShadow {
transparentBorder: true
radius: 40
samples: 56
color: Qt.rgba(0, 0, 0, 0.5)
}
Rectangle {
anchors.fill: parent
radius: 12
color: "transparent"
border { color: Qt.rgba(1, 1, 1, 0.04); width: 1 }
}
Item {
anchors { anchors {
left: parent.left fill: parent
right: parent.right margins: 32
bottom: parent.bottom
} }
height: 200
color: Qt.rgba(0, 0, 0, 0.6)
Slider { Slider {
id: slider id: slider
anchors { anchors.fill: parent
fill: parent
margins: 20
}
slides: [ slides: [
Dia { Dia {
title: qsTr("Welcome to Antergos NeXT") title: qsTr("Welcome to Antergos NeXT")
body: qsTr("A modern Artix Linux experience with OpenRC and elogind") body: qsTr("A modern Arch Linux experience built on Artix Linux. Rolling release, OpenRC init, and the latest software.")
footer: qsTr("Choose your preferred desktop environment during setup") footer: qsTr("Choose your preferred desktop environment during setup")
}, },
Dia { Dia {
title: qsTr("Desktop Environments") title: qsTr("Desktop Environments")
body: qsTr("Select from KDE Plasma, Xfce, Cinnamon, MATE, LXQt, i3, Sway, or Hyprland") body: qsTr("Select from KDE Plasma, GNOME, Xfce, Budgie, Cinnamon, MATE, LXQt, i3, Sway, or Hyprland.")
footer: qsTr("Each desktop is fully configured and ready to use") footer: qsTr("A curated selection of the best Linux desktops")
}, },
Dia { Dia {
title: qsTr("Antergos Tools") title: qsTr("Antergos Tools")
body: qsTr("Welcome app for system configuration, Calamares installer with offline and online modes, and HAL package manager") body: qsTr("Welcome app for system configuration, Calamares installer with offline and online modes, and full access to Arch Linux repositories and the AUR.")
footer: qsTr("Full access to Artix Linux repositories and the AUR") footer: qsTr("Everything you need to get started")
}, },
Dia { Dia {
title: qsTr("Open Source") title: qsTr("Open Source")
body: qsTr("Antergos NeXT is free and open source software built by the community") body: qsTr("Free and open source software built by the community for the community.")
footer: qsTr("Contribute on GitHubAntergos-NeXT") footer: qsTr("github.com/Antergos-NeXT")
}, },
Dia { Dia {
title: qsTr("Almost Done") title: qsTr("Almost Done")
body: qsTr("Your system is being configured with your selected options") body: qsTr("Your system is being configured with your selected desktop environment, drivers, and applications.")
footer: qsTr("Reboot and enjoy Antergos NeXT") footer: qsTr("Reboot and enjoy Antergos NeXT")
} }
] ]
} }
} }
} }
Image {
id: logo
source: "antergos-logo.png"
width: 140
height: 40
fillMode: Image.PreserveAspectFit
anchors {
bottom: parent.bottom
bottomMargin: 20
left: parent.left
leftMargin: 24
}
opacity: 0.45
}
Row {
anchors {
bottom: parent.bottom
bottomMargin: 20
horizontalCenter: parent.horizontalCenter
}
spacing: 6
Repeater {
model: slider.slides.length
Rectangle {
width: index == slider.currentSlideIndex ? 22 : 7
height: 7
radius: 3.5
color: index == slider.currentSlideIndex ? "#4A9EFF" : "#8E9099"
opacity: index == slider.currentSlideIndex ? 1 : 0.35
Behavior on width { NumberAnimation { duration: 250 } }
Behavior on color { ColorAnimation { duration: 200 } }
}
}
}
}