Basic TextMenu
99
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
›
⌄
⌄
⌄
⌄
import { html, atom, renderApp } from 'mates';
import { TextMenu, Text } from 'mates-ui';
import { CloseIcon, ContentCopyIcon, ContentCutIcon, ContentPasteIcon, FolderOpenIcon, FitScreenIcon, FullscreenIcon, NoteAddIcon, RedoIcon, SaveIcon, UndoIcon, ZoomInIcon, ZoomOutIcon } from 'mates-icons';
const App = () => {
const lastFile = atom("—"); const lastEdit = atom("—"); const lastView = atom("—");
return () => html`
<x-row gap="var(--md-space-4)" align="center">
${TextMenu({ label: "File", list: { items: [
{ id: "new", label: "New", icon: NoteAddIcon() },
{ id: "open", label: "Open…", icon: FolderOpenIcon() },
{ id: "save", label: "Save", icon: SaveIcon() },
{ type: "divider", label: "" },
{ id: "close", label: "Close", icon: CloseIcon() },
], onSelect: (_ids, item) => lastFile.set(item?.id ?? "—") }, popup: { position: "bottom-start" } })}
${TextMenu({ label: "Edit", list: { items: [
{ id: "undo", label: "Undo", icon: UndoIcon() },
{ id: "redo", label: "Redo", icon: RedoIcon() },
{ type: "divider", label: "" },
{ id: "cut", label: "Cut", icon: ContentCutIcon() },
{ id: "copy", label: "Copy", icon: ContentCopyIcon() },
{ id: "paste", label: "Paste", icon: ContentPasteIcon() },
], onSelect: (_ids, item) => lastEdit.set(item?.id ?? "—") }, popup: { position: "bottom-start" } })}
${TextMenu({ label: "View", list: { items: [
{ id: "zoom-in", label: "Zoom In", icon: ZoomInIcon() },
{ id: "zoom-out", label: "Zoom Out", icon: ZoomOutIcon() },
{ id: "fit", label: "Fit Page", icon: FitScreenIcon() },
{ type: "divider", label: "" },
{ id: "fullscreen", label: "Full Screen", icon: FullscreenIcon() },
], onSelect: (_ids, item) => lastView.set(item?.id ?? "—") }, popup: { position: "bottom-start" } })}
</x-row>
`;
};
renderApp(App, document.getElementById('app'));
Sizes
99
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
›
⌄
import { html, atom, renderApp } from 'mates';
import { TextMenu, Text } from 'mates-ui';
import { StarIcon } from 'mates-icons';
const ITEMS = [{ id: "a", label: "Alpha", icon: StarIcon() }, { id: "b", label: "Beta", icon: StarIcon() }, { id: "c", label: "Gamma", icon: StarIcon() }];
const App = () => {
const last = atom("—");
return () => html`
<x-row gap="var(--md-space-6)" align="center">
${TextMenu({ label: "Small", size: "sm", list: { items: ITEMS, onSelect: (_ids, item) => last.set("sm → " + (item?.id ?? "—")) }, popup: { position: "bottom-start" } })}
${TextMenu({ label: "Medium", size: "md", list: { items: ITEMS, onSelect: (_ids, item) => last.set("md → " + (item?.id ?? "—")) }, popup: { position: "bottom-start" } })}
${TextMenu({ label: "Large", size: "lg", list: { items: ITEMS, onSelect: (_ids, item) => last.set("lg → " + (item?.id ?? "—")) }, popup: { position: "bottom-start" } })}
</x-row>
`;
};
renderApp(App, document.getElementById('app'));
In a toolbar / menu-bar style
99
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
›
⌄
⌄
⌄
⌄
import { html, atom, renderApp } from 'mates';
import { TextMenu, Text } from 'mates-ui';
import { FolderOpenIcon, InfoIcon, NoteAddIcon, RedoIcon, SaveIcon, SearchIcon, UndoIcon } from 'mates-icons';
const App = () => {
const last = atom("—");
const sel = (_ids, item) => last.set(item?.id ?? "—");
return () => html`
<x-col gap="var(--md-space-3)">
<div style="display:inline-flex;align-items:center;gap:0;border-bottom:1px solid var(--md-color-border);padding:var(--md-space-1) var(--md-space-2);border-radius:var(--md-radius-sm) var(--md-radius-sm) 0 0;background:var(--md-color-surface-raised);">
${TextMenu({ label: "File", size: "sm", list: { items: [
{ id: "new", label: "New File", icon: NoteAddIcon() },
{ id: "open", label: "Open…", icon: FolderOpenIcon() },
{ type: "divider", label: "" },
{ id: "save", label: "Save", icon: SaveIcon() },
], onSelect: sel }, popup: { position: "bottom-start" } })}
${TextMenu({ label: "Edit", size: "sm", list: { items: [
{ id: "undo", label: "Undo", icon: UndoIcon() },
{ id: "redo", label: "Redo", icon: RedoIcon() },
{ type: "divider", label: "" },
{ id: "find", label: "Find", icon: SearchIcon() },
], onSelect: sel }, popup: { position: "bottom-start" } })}
${TextMenu({ label: "Help", size: "sm", list: { items: [
{ id: "about", label: "About", icon: InfoIcon() },
], onSelect: sel }, popup: { position: "bottom-start" } })}
</div>
${Text("Last action: " + last(), { type: "body-sm", color: "muted" })}
</x-col>
`;
};
renderApp(App, document.getElementById('app'));
With groups and icons
99
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
›
⌄
⌄
⌄
import { html, atom, renderApp } from 'mates';
import { TextMenu, Text } from 'mates-ui';
import { CodeIcon, FormatAlignCenterIcon, FormatAlignJustifyIcon, FormatAlignLeftIcon, FormatAlignRightIcon, FormatBoldIcon, FormatItalicIcon, FormatListBulletedIcon, FormatUnderlinedIcon, HorizontalRuleIcon, ImageIcon, LinkIcon, MoodIcon, MusicNoteIcon, TableChartIcon } from 'mates-icons';
const App = () => {
const last = atom("—");
return () => html`
<x-row gap="var(--md-space-6)" align="flex-start">
${TextMenu({ label: "Insert", list: { groups: [
{ label: "Content", items: [{ id: "img", label: "Image", icon: ImageIcon() }, { id: "audio", label: "Audio", icon: MusicNoteIcon() }] },
{ label: "Structure", items: [{ id: "table", label: "Table", icon: TableChartIcon() }, { id: "list", label: "List", icon: FormatListBulletedIcon() }, { id: "code", label: "Code Block", icon: CodeIcon() }] },
{ label: "Extras", items: [{ id: "link", label: "Link", icon: LinkIcon() }, { id: "emoji", label: "Emoji", icon: MoodIcon() }, { id: "hr", label: "Divider", icon: HorizontalRuleIcon() }] },
], onSelect: (_ids, item) => last.set(item?.id ?? "—") }, popup: { position: "bottom-start", matchAnchorWidth: false } })}
${TextMenu({ label: "Format", list: { groups: [
{ label: "Text", items: [{ id: "bold", label: "Bold", icon: FormatBoldIcon() }, { id: "italic", label: "Italic", icon: FormatItalicIcon() }, { id: "underline", label: "Underline", icon: FormatUnderlinedIcon() }] },
{ label: "Alignment", items: [{ id: "left", label: "Left", icon: FormatAlignLeftIcon() }, { id: "center", label: "Center", icon: FormatAlignCenterIcon() }, { id: "right", label: "Right", icon: FormatAlignRightIcon() }, { id: "justify", label: "Justify", icon: FormatAlignJustifyIcon() }] },
], onSelect: (_ids, item) => last.set(item?.id ?? "—") }, popup: { position: "bottom-start", matchAnchorWidth: false } })}
${Text("Last: " + last(), { type: "body-sm", color: "muted" })}
</x-row>
`;
};
renderApp(App, document.getElementById('app'));
Cascading (nested sub-panels)
99
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
›
⌄
⌄
⌄
⌄
⌄
⌄
⌄
import { html, atom, renderApp } from 'mates';
import { CascadingPopupList, TextMenu, Text } from 'mates-ui';
import { DockToBottomIcon, DockToLeftIcon, ExpandIcon, FitScreenIcon, FullscreenIcon, ZoomInIcon, ZoomOutIcon } from 'mates-icons';
const App = () => {
const last = atom("—");
return () => html`
<x-col gap="var(--md-space-3)">
${TextMenu({
label: "View",
panel: CascadingPopupList({
items: [
{ id: "zoom", label: "Zoom", icon: ZoomInIcon(), children: [
{ id: "zoom-in", label: "Zoom In", icon: ZoomInIcon() },
{ id: "zoom-out", label: "Zoom Out", icon: ZoomOutIcon() },
{ id: "zoom-fit", label: "Fit Screen", icon: FitScreenIcon() },
],
},
{ id: "layout", label: "Layout", children: [
{ id: "dock-left", label: "Dock Left", icon: DockToLeftIcon() },
{ id: "dock-bottom", label: "Dock Bottom", icon: DockToBottomIcon() },
{ id: "expand", label: "Expand", icon: ExpandIcon() },
],
},
{ type: "divider", label: "" },
{ id: "fullscreen", label: "Full Screen", icon: FullscreenIcon() },
],
onSelect: (_ids, item) => {
last.set(item?.label ?? "—");
requestAnimationFrame(() => document.dispatchEvent(new MouseEvent("click", { bubbles: true })));
},
onEscape: () => { requestAnimationFrame(() => document.dispatchEvent(new MouseEvent("click", { bubbles: true }))); },
}),
popup: { position: "bottom-start", matchAnchorWidth: false },
})}
${Text("Last selected: " + last(), { type: "body-sm", color: "muted" })}