* Components: added Menu
* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

Imported from 599653f7ce
This commit is contained in:
FloVanGH 2025-08-21 07:46:30 +00:00 committed by Olivier Goffart
parent f14d04c798
commit 971bff4434
8 changed files with 199 additions and 1 deletions

View file

@ -0,0 +1,42 @@
---
<!-- Copyright © SixtyFPS GmbH <info@slint.dev> ; SPDX-License-Identifier: MIT -->
title: Menu
description: Menu API.
---
import CodeSnippetMD from '/src/components/CodeSnippetMD.astro';
import SlintProperty from '/src/components/SlintProperty.astro';
<CodeSnippetMD imagePath="/src/assets/generated/menu.png" scale="3" imageWidth="300" imageHeight="200" imageAlt="">
```slint
import { Menu } from "material.slint";
export component Example inherits Window {
width: 400px;
height: 300px;
background: transparent;
Menu {
width: 280px;
height: parent.height;
items: [
{ text: "Copy" },
{ text: "Cut" },
{ text: "Paste" },
];
}
}
```
</CodeSnippetMD>
A `Menu` display a list of choices on a temporary surface.
## Properties
### items
<SlintProperty propName="items" typeName="[struct]" structName="MenuItem">
An array of menu items, each containing an icon, a text, and a trailing text.
</SlintProperty>
## Callbacks
### item_clicked(index: int)
Invoked when a menu item is clicked

View file

@ -30,7 +30,8 @@ import {
Switch,
Slider,
TextField,
RadioButtonTile
RadioButtonTile,
Menu
} from "../../../../material.slint";
import { Group } from "../components/group.slint";
@ -419,6 +420,34 @@ export component NavigationView {
}
}
ComponentCard {
title: "Menus";
Horizontal {
alignment: center;
menu_button := TextButton {
text: "Show menu";
clicked => {
menu.show();
}
}
menu := Menu {
x: menu_button.x + menu_button.width / 2;
y: menu_button.y + menu_button.height / 2;
items: [
{ icon: OutlinedIcons.account_box, text: "Inbox", enabled: true },
{ icon: OutlinedIcons.outbox, text: "Outbox", enabled: true, trailing_text: "Ctrl C" },
{ icon: OutlinedIcons.favorite, text: "Fravorites", enabled: true },
{ icon: OutlinedIcons.delete, text: "Trash", enabled: false },
];
}
}
}
ComponentCard {
title: "Time picker";

View file

@ -28,6 +28,7 @@ export { Avatar, ListTile } from "./ui/components/list.slint";
export { ListView } from "./ui/components/list_view.slint";
export { MaterialText } from "./ui/components/material_text.slint";
export { MaterialWindow, MaterialWindowAdapter } from "./ui/components/material_window.slint";
export { Menu } from "./ui/components/menu.slint";
export { NavigationBar } from "./ui/components/navigation_bar.slint";
export { NavigationDrawer, ModalNavigationDrawer } from "./ui/components/navigation_drawer.slint";
export { NavigationRail } from "./ui/components/navigation_rail.slint";
@ -53,6 +54,7 @@ export { Modal } from "./ui/components/modal.slint";
// items
export { ListItem } from "./ui/items/list_item.slint";
export { NavigationItem, NavigationGroup } from "./ui/items/navigation_item.slint";
export { MenuItem } from "./ui/items/menu_item.slint";
// styles
export { Animations } from "./ui/styling/animations.slint";

View file

@ -0,0 +1,113 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: MIT
import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint";
import { MaterialPalette } from "../styling/material_palette.slint";
import { Elevation } from "elevation.slint";
import { StateLayerArea } from "./state_layer.slint";
import { Typography } from "../styling/typography.slint";
import { Icon } from "./icon.slint";
import { MenuItem } from "../items/menu_item.slint";
import { MaterialText } from "./material_text.slint";
import { Icons } from "../icons/icons.slint";
component MenuItemTemplate {
in property <image> icon;
in property <string> text;
in property <string> trailing_text;
in property <bool> enabled <=> state_area.enabled;
callback clicked();
property <bool> has_icon: root.icon.width > 0 && root.icon.height > 0;
property <color> color: MaterialPalette.on_surface;
property <color> color_variant: MaterialPalette.on_surface_variant;
min_height: max(MaterialStyleMetrics.size_56, layout.min_height);
state_area := StateLayerArea {
color: root.color;
layout := HorizontalLayout {
padding_left: MaterialStyleMetrics.padding_12;
padding_right: self.padding_left;
padding_top: MaterialStyleMetrics.padding_8;
padding_bottom: self.padding_top;
spacing: MaterialStyleMetrics.spacing_12;
if root.has_icon : VerticalLayout {
alignment: center;
Icon {
source: root.icon;
colorize: root.color;
}
}
MaterialText {
horizontal_stretch: 1;
text: root.text;
style: Typography.body_large;
color: root.color;
vertical_alignment: center;
}
if root.trailing_text != "" : MaterialText {
text: root.trailing_text;
style: Typography.body_large;
color: root.color_variant;
vertical_alignment: center;
}
}
clicked => {
root.clicked();
}
}
states [
disabled when !root.enabled : {
state_area.opacity: MaterialPalette.disable_opacity;
}
]
}
export component Menu inherits PopupWindow {
in property <[MenuItem]> items;
callback item_clicked(index: int);
// used to fix clipping of shadows
property <int> elevation: 2;
width: MaterialStyleMetrics.size_200;
close_policy: close_on_click_outside;
wrapper := VerticalLayout {
padding: root.elevation * 1px;
menu := Elevation {
level: root.elevation;
height: layout.min_height + root.elevation * 1px;
border_radius: MaterialStyleMetrics.border_radius_4;
background: MaterialPalette.surface_container;
layout := VerticalLayout {
width: root.width;
padding_top: MaterialStyleMetrics.padding_8;
padding_bottom: self.padding_top;
for item[index] in root.items : MenuItemTemplate {
icon: item.icon;
text: item.text;
trailing_text: item.trailing_text;
enabled: item.enabled;
clicked => {
root.item_clicked(index);
}
}
}
}
}
}

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 17l5-5l-5-5v10z"/></svg>

After

Width:  |  Height:  |  Size: 121 B

View file

@ -6,6 +6,7 @@ export global Icons {
out property <image> close: @image-url("close.svg");
out property <image> menu: @image-url("menu.svg");
out property <image> arrow_back: @image-url("arrow_back.svg");
out property <image> arrow_right: @image-url("arrow_right.svg");
out property <image> remove: @image-url("remove.svg");
out property <image> schedule: @image-url("schedule.svg");
out property <image> keyboard: @image-url("keyboard.svg");

View file

@ -0,0 +1,9 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: MIT
export struct MenuItem {
icon: image,
text: string,
trailing_text: string,
enabled: bool
}

View file

@ -26,6 +26,7 @@ export global MaterialStyleMetrics {
out property <length> size_72: 72px;
out property <length> size_80: 80px;
out property <length> size_90: 96px;
out property <length> size_200: 200px;
out property <length> size_256: 256px;
out property <length> size_344: 344px;
out property <length> size_360: 360px;