-
This commit is contained in:
116
ui/components/accordion.slint
Normal file
116
ui/components/accordion.slint
Normal file
@@ -0,0 +1,116 @@
|
||||
import { Theme, SpacingSystem, Typography, Animations } from "../theme/theme.slint";
|
||||
|
||||
export struct AccordionItemData {
|
||||
title: string,
|
||||
expanded: bool,
|
||||
}
|
||||
|
||||
export component Accordion {
|
||||
in-out property <[AccordionItemData]> items: [];
|
||||
in property <bool> allow-multiple: false;
|
||||
|
||||
callback item-toggled(int, bool);
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 0;
|
||||
|
||||
for item[index] in root.items: AccordionItem {
|
||||
title: item.title;
|
||||
expanded: item.expanded;
|
||||
is-last: index == root.items.length - 1;
|
||||
|
||||
toggled => {
|
||||
root.item-toggled(index, !item.expanded);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component AccordionItem {
|
||||
in property <string> title: "";
|
||||
in property <bool> expanded: false;
|
||||
in property <bool> is-last: false;
|
||||
|
||||
callback toggled();
|
||||
|
||||
private property <bool> hovered: false;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 0;
|
||||
|
||||
// Header
|
||||
header := Rectangle {
|
||||
height: 48px;
|
||||
background: root.hovered ? Theme.colors.muted : transparent;
|
||||
|
||||
animate background { duration: Animations.durations.fast; }
|
||||
|
||||
HorizontalLayout {
|
||||
padding-left: SpacingSystem.spacing.s4;
|
||||
padding-right: SpacingSystem.spacing.s4;
|
||||
spacing: SpacingSystem.spacing.s4;
|
||||
alignment: space-between;
|
||||
|
||||
Text {
|
||||
text: root.title;
|
||||
color: Theme.colors.foreground;
|
||||
font-size: Typography.sizes.sm;
|
||||
font-weight: Typography.weights.medium;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
|
||||
chevron := Text {
|
||||
text: "›";
|
||||
color: Theme.colors.muted-foreground;
|
||||
font-size: Typography.sizes.lg;
|
||||
font-weight: Typography.weights.bold;
|
||||
vertical-alignment: center;
|
||||
width: 20px;
|
||||
horizontal-alignment: center;
|
||||
|
||||
rotation-angle: root.expanded ? 90deg : 0deg;
|
||||
rotation-origin-x: self.width / 2;
|
||||
rotation-origin-y: self.height / 2;
|
||||
|
||||
animate rotation-angle { duration: Animations.durations.normal; easing: Animations.ease-out; }
|
||||
}
|
||||
}
|
||||
|
||||
touch := TouchArea {
|
||||
clicked => {
|
||||
root.toggled();
|
||||
}
|
||||
|
||||
moved => {
|
||||
root.hovered = self.has-hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Content
|
||||
if root.expanded: content-wrapper := Rectangle {
|
||||
background: transparent;
|
||||
|
||||
VerticalLayout {
|
||||
padding: SpacingSystem.spacing.s4;
|
||||
padding-top: 0;
|
||||
padding-bottom: SpacingSystem.spacing.s4;
|
||||
|
||||
@children
|
||||
}
|
||||
}
|
||||
|
||||
// Border
|
||||
if !root.is-last: Rectangle {
|
||||
height: 1px;
|
||||
background: Theme.colors.border;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper for accordion content
|
||||
export component AccordionContent {
|
||||
VerticalLayout {
|
||||
@children
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user