117 lines
3.3 KiB
Plaintext
117 lines
3.3 KiB
Plaintext
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
|
||
}
|
||
}
|