@vestra-player/sdk 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.5.0
4
+
5
+ **Own visual identity: the Aurora palettes and the V-Line icons** (player 0.4.0). Additive; `apiVersion` stays `vestra/1`. Plugins that use the additions set `"minPlayerVersion": "0.4.0"`.
6
+
7
+ - **`ThemeId` gains `"vestra-light"`**, a light palette whose video area stays dark. `plugin.appearance.set("vestra-light")` switches every view; `TestHost` accepts it like the player. A player older than 0.4.0 answers it with `vestra` (an id it does not have).
8
+ - **New colours for `vestra`.** The palette is now Aurora, drawn from the logo's full spectrum: magenta accent (`#f72aa6`), cyan for what is playing (`Theme.playing`, `#2bb6ff`, violet before), `Theme.accent-fill` from amber through magenta and violet to cyan, and a visible `Theme.line` (`#2b2734`; it was near-black). Token names are unchanged; code that reads `Theme` follows.
9
+ - **Rounder corners**: `Theme.radius-control` 4px (was 3px), `Theme.radius-panel` 8px (was 6px). Sizes are otherwise unchanged.
10
+ - **`@vestra/icons.slint`** (new library file, `slint/vestra/icons.slint`): `Icon { name: "play"; color: Theme.text; }` draws one icon of the player's own set (round-capped 1.5px lines), and `Icons.commands(name)` / `box-width` / `box-height` / `line` give its path data. The names are listed in **Windows, panels, settings pages, dialogs and the OSD**.
11
+ - **`@vestra/widgets.slint`**: the bar slider's thumb is a white core in a 2px accent ring; the panel slider's track is `Theme.line`; stroked icon buttons use round caps and joins; tooltips have rounded corners. Geometry and API are unchanged.
12
+ - **std-widgets in a light palette**: the player still compiles plugin files with `fluent-dark` and switches the std-widgets colour scheme (`Palette.color-scheme`) to light for `vestra-light`, so `CheckBox`, `ComboBox`, `LineEdit`, `ScrollView` and the other std-widgets controls follow. The player's palette file (`slint/palette.slint`, not part of the library) now imports `std-widgets.slint` for that.
13
+
14
+ ## 1.4.1
15
+
16
+ Documentation only; no code or type changes.
17
+
18
+ - **Built-in menus keep their place** (player 0.3.0). `CommandOptions` and `CommandOptions.order` document the player's menu rule: the seven built-in top-level menus (`@open` … `@settings`) sit at fixed orders (Open 110, Playback 200, Subtitles 300, Video 400, Audio 500, Screen 710, Settings 830), whether a path names them by id or by title, so a plugin's item never moves them. Directly inside a built-in menu, `order` 0 (the default) sorts after every other order, so an item without `order` goes at the end. Players before 0.3.0 move the whole menu to the top for such an item; give it an order in the menu's range there.
19
+ - The Blur walkthrough explains `order` inside the Video menu accordingly.
20
+
3
21
  ## 1.4.0
4
22
 
5
23
  **One palette.** `ThemeId` is now `"vestra"` only: the second palette that earlier versions listed is gone from the player. This is a minor version although a type narrows, because the only plugins it affects compare `plugin.appearance.theme` with, or `set` the removed id:
package/README.md CHANGED
@@ -82,6 +82,7 @@ Complete, tested plugins in [`examples/`](https://github.com/vestrasys/vestra-pl
82
82
  | 1.2 | `vestra/1` | 0.2 or newer | 26 (shipped with the player) |
83
83
  | 1.3 | `vestra/1` | 0.2 or newer; 0.3 for the 1.3 additions (menu ids, `Theme.danger`, empty video chains) | 26 (shipped with the player) |
84
84
  | 1.4 | `vestra/1` | 0.2 or newer; 0.3 for the 1.3 additions. `ThemeId` is `"vestra"` only (see the CHANGELOG) | 26 (shipped with the player) |
85
+ | 1.5 | `vestra/1` | 0.2 or newer; 0.3 for the 1.3 additions; 0.4 for the 1.5 additions (`vestra-light`, `@vestra/icons.slint`) | 26 (shipped with the player) |
85
86
 
86
87
  Minor releases only add backwards-compatible API; a breaking change gets a new `apiVersion` and a new major version. `@vestra-player/sdk/runtime` is for the player only and not covered by semver.
87
88
 
@@ -54,7 +54,7 @@ export type CommandDeclaration = {
54
54
  title: string;
55
55
  /** Complete primary menu path INCLUDING its leaf; empty = not in the main menu. */
56
56
  path: string[];
57
- /** Sibling order, ascending; a submenu takes its first command's order. */
57
+ /** Sibling order, ascending; a submenu takes its first command's order (a built-in menu keeps a fixed one). */
58
58
  order: number;
59
59
  /** Separator label: adjacent siblings of different groups get a line. */
60
60
  group: string;
@@ -2,7 +2,7 @@
2
2
  import { failure } from "./runtime.js";
3
3
  import { windowOf } from "./window.js";
4
4
  /** The palettes this SDK knows, the default first. */
5
- export const THEMES = ["vestra"];
5
+ export const THEMES = ["vestra", "vestra-light"];
6
6
  /**
7
7
  * One per plugin: the value comes with the `window.state` read before
8
8
  * activation; with `events`, `appearance.changed` keeps it current once
@@ -376,6 +376,21 @@ export type MenuId = "open" | "playback" | "subtitles" | "video" | "audio" | "sc
376
376
  * ranges: `open` 100–199, `domain` 200–699 (playback, subtitles, video,
377
377
  * audio…), `screen` 700–799, `windows` 800–899, `exit` 900–999.
378
378
  *
379
+ * Built-in menus keep their place. The seven built-in top-level menus
380
+ * ({@link MenuId}) sit at fixed orders, whatever is inside them: Open 110,
381
+ * Playback 200, Subtitles 300, Video 400, Audio 500, Screen 710, Settings
382
+ * 830 (player 0.3.0). This holds whether the path names the menu by id
383
+ * (`["@video", "Blur"]`) or by its title (`["视频", "Blur"]`), so a plugin's
384
+ * item never moves the player's menu. Directly inside a built-in menu,
385
+ * `order` 0 (the default) sorts after every other order: an item without
386
+ * `order` goes at the end, after the player's own items (which all use 100
387
+ * or more). Give a positive order to sit between them (the player's orders
388
+ * are listed in its menu table, doc/product/menus.md), or a negative one to
389
+ * come first. Deeper levels (a plugin's own submenu) have no such rule.
390
+ * Players before 0.3.0 place every submenu at its smallest order, so there
391
+ * an item without `order` moves the whole menu to the top; to avoid that,
392
+ * give it an order in the menu's range (Video: 400–499).
393
+ *
379
394
  * {@link Commands.add} throws `invalid` synchronously for a bad path,
380
395
  * order, group or binding. The same path registered twice, or a path that
381
396
  * is both an item and a submenu, fails with `conflict` (through `ready`).
@@ -406,8 +421,10 @@ export interface CommandOptions {
406
421
  title?: string;
407
422
  /**
408
423
  * Sibling order in the menu, ascending (integer, default 0). A submenu sits
409
- * where its first command sits. Equal orders: plugin id, then declaration order.
410
- * Range ±1,000,000.
424
+ * where its first command sits, except a built-in menu, which keeps its
425
+ * fixed place. Directly inside a built-in menu, 0 (the default) sorts last.
426
+ * Equal orders: plugin id, then declaration order. Range ±1,000,000. See
427
+ * {@link CommandOptions} for the menu order rules.
411
428
  */
412
429
  order?: number;
413
430
  /** Separator label: a line is drawn between adjacent items of different groups. Default `"domain"`. */
@@ -1562,19 +1579,20 @@ export interface Drops {
1562
1579
  provide(handler: DropHandler): Disposable;
1563
1580
  }
1564
1581
  /**
1565
- * The player's palettes. Today there is one, `vestra` (the default); a later
1566
- * version may add more (a light palette, for example), so read colours from
1567
- * `Theme` instead of branching on the id.
1582
+ * The player's palettes: `vestra`, the dark default, and `vestra-light`
1583
+ * (player 0.4.0, SDK 1.5.0), a light palette whose video area stays dark.
1584
+ * Both draw on the logo's colours. Read colours from `Theme` instead of
1585
+ * branching on the id: a later version may add palettes.
1568
1586
  *
1569
1587
  * @remarks
1570
- * SDK 1.4.0 removed a second palette that earlier versions listed. The player
1571
- * treats an id it does not have as `vestra`, so plugins built with an older
1572
- * SDK that still ask for it keep working.
1588
+ * The player treats an id it does not have as `vestra`: plugins built with an
1589
+ * older SDK that still ask for a palette removed in SDK 1.4.0 keep working,
1590
+ * and a player older than 0.4.0 answers `vestra-light` with `vestra`.
1573
1591
  *
1574
1592
  * @since 1.0.0
1575
1593
  * @category UI
1576
1594
  */
1577
- export type ThemeId = "vestra";
1595
+ export type ThemeId = "vestra" | "vestra-light";
1578
1596
  /**
1579
1597
  * The player's palette, which every view uses. `plugin.appearance`.
1580
1598
  *
@@ -1584,7 +1602,9 @@ export type ThemeId = "vestra";
1584
1602
  * and again when the palette changes. Slint code that reads its colours from
1585
1603
  * `Theme` (`import { Theme } from "@vestra/theme.slint"`) follows it with no
1586
1604
  * plugin code; hard-coded colours do not. Only colours change: corner radii,
1587
- * font sizes and control sizes are the same in every palette.
1605
+ * font sizes and control sizes are the same in every palette. A light palette
1606
+ * also switches the std-widgets controls (`std-widgets.slint`) to their light
1607
+ * colours, and keeps the video area dark.
1588
1608
  *
1589
1609
  * The player saves the choice; it stays after the plugin that set it stops.
1590
1610
  * Tell the user about a change yourself (for example with
@@ -1593,14 +1613,14 @@ export type ThemeId = "vestra";
1593
1613
  * @capability None to read `theme`; `events` to follow changes; `ui.theme`
1594
1614
  * to change it.
1595
1615
  *
1596
- * @example A menu item that selects the palette
1616
+ * @example A menu item that selects the light palette
1597
1617
  * ```ts
1598
1618
  * plugin.commands.add({
1599
- * id: "vestra-colours",
1600
- * path: ["@settings", "Vestra colours"],
1619
+ * id: "light-colours",
1620
+ * path: ["@settings", "Light colours"],
1601
1621
  * radio: true,
1602
- * checked: () => plugin.appearance.theme === "vestra",
1603
- * run: () => plugin.appearance.set("vestra"),
1622
+ * checked: () => plugin.appearance.theme === "vestra-light",
1623
+ * run: () => plugin.appearance.set("vestra-light"),
1604
1624
  * });
1605
1625
  * ```
1606
1626
  *
@@ -1657,7 +1677,7 @@ export interface Appearance {
1657
1677
  *
1658
1678
  * @example
1659
1679
  * ```ts
1660
- * await plugin.appearance.set("vestra");
1680
+ * await plugin.appearance.set("vestra-light");
1661
1681
  * ```
1662
1682
  *
1663
1683
  * @since 1.0.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vestra-player/sdk",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Plugin API types, test host and plugin CLI for Vestra Player (apiVersion vestra/1)",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -1,32 +1,42 @@
1
1
  // The player's colour palette (R-H6) and per-system fonts. Not part of the
2
2
  // plugin library: the player sets these `in` properties on every view;
3
3
  // `Theme` in @vestra/theme.slint reads them as `out` properties. Defaults:
4
- // Vestra colours, the macOS fonts.
4
+ // the Aurora colours of the `vestra` palette, the macOS fonts.
5
+ import { Palette } from "std-widgets.slint";
6
+
5
7
  export global VestraPalette {
6
- in property <color> bg-bar: #17141c;
7
- in property <color> bg-video: #0b0a0f;
8
- in property <color> bg-list: #1c1922;
9
- in property <color> bg-panel: #221e29;
10
- in property <color> line: #07060a;
11
- in property <color> hover-bg: #2a2533;
12
- in property <color> press-bg: #120f16;
13
- in property <color> selected-bg: #2f2938;
14
- in property <color> text: #f2eff7;
15
- in property <color> text-dim: #8a8496;
16
- in property <color> text-list: #b8b2c4;
17
- in property <color> text-played: #6f6a7a;
18
- in property <color> accent: #fa139c;
19
- in property <color> accent-press: #c40f7a;
20
- in property <color> accent-disabled: #5c1a42;
21
- in property <color> icon-disabled: #3a3542;
22
- in property <color> playing: #a24bff;
23
- in property <color> button-bg: #322c3b;
24
- in property <color> button-hover: #3d3648;
25
- in property <color> button-press: #26212e;
26
- in property <color> button-disabled: #1d1a23;
8
+ in property <color> bg-bar: #16141c;
9
+ in property <color> bg-video: #0a090e;
10
+ in property <color> bg-list: #1a1821;
11
+ in property <color> bg-panel: #201d28;
12
+ in property <color> line: #2b2734;
13
+ in property <color> hover-bg: #28232f;
14
+ in property <color> press-bg: #110f16;
15
+ in property <color> selected-bg: #2f2840;
16
+ in property <color> text: #f5f3fa;
17
+ in property <color> text-dim: #8e88a0;
18
+ in property <color> text-list: #bdb8cb;
19
+ in property <color> text-played: #6e6980;
20
+ in property <color> accent: #f72aa6;
21
+ in property <color> accent-press: #c41a83;
22
+ in property <color> accent-disabled: #5a1d48;
23
+ in property <color> icon-disabled: #3b3646;
24
+ in property <color> playing: #2bb6ff;
25
+ in property <color> button-bg: #2f2a3b;
26
+ in property <color> button-hover: #3a3448;
27
+ in property <color> button-press: #25202e;
28
+ in property <color> button-disabled: #1b1922;
27
29
  // Errors and destructive actions (failed status, delete).
28
- in property <color> danger: #ff5a4a;
30
+ in property <color> danger: #ff5a5f;
29
31
  // The system's monospace family (platform::monospace_font).
30
32
  in property <string> font-mono: "Menlo";
31
- in property <brush> accent-fill: @linear-gradient(90deg, #fdb506 0%, #fc6f3b 25%, #fa139c 60%, #911efc 100%);
33
+ // Each palette's progress gradient, logo amber → magenta → violet → cyan.
34
+ // The player copies one into `accent-fill` (Slint's Rust API cannot
35
+ // build gradients).
36
+ out property <brush> fill-vestra: @linear-gradient(90deg, #fcc402 0%, #fb5a35 20%, #fa0aa8 45%, #7a0afa 72%, #10a8fc 100%);
37
+ out property <brush> fill-vestra-light: @linear-gradient(90deg, #f5a700 0%, #f0442f 20%, #e0089a 45%, #6a08e8 72%, #0a95e6 100%);
38
+ in property <brush> accent-fill: self.fill-vestra;
39
+ // The std-widgets (fluent) controls follow the palette: the player sets
40
+ // `light` for a light palette.
41
+ in-out property <ColorScheme> color-scheme <=> Palette.color-scheme;
32
42
  }
@@ -0,0 +1,99 @@
1
+ // The V-Line icon set (doc/product/ui-spec.md §2.4): round-capped, round-joined
2
+ // lines, 1.5px (1.25px for the small glyphs), never filled. The V of the
3
+ // logo recurs: « » for back and forward, ∧ ∨ for moving rows, a small V for
4
+ // every menu, list and scroll arrow.
5
+ // import { Icon } from "@vestra/icons.slint";
6
+ // Icon { name: "play"; color: Theme.text; }
7
+ // Each icon is drawn in its own box (`Icons.box-width` × `Icons.box-height`),
8
+ // which is also the Icon's default size; an unknown name draws nothing.
9
+ import { Theme } from "theme.slint";
10
+
11
+ export global Icons {
12
+ // Path data in the icon's box.
13
+ public pure function commands(name: string) -> string {
14
+ if name == "play" { return "M 2.2 2.0 L 10.9 7 L 2.2 12.0 Z"; }
15
+ if name == "pause" { return "M 1.75 1.75 H 4.5 V 12.25 H 1.75 Z M 7.5 1.75 H 10.25 V 12.25 H 7.5 Z"; }
16
+ if name == "stop" { return "M 3.6 1.5 H 8.4 Q 10.5 1.5 10.5 3.6 V 8.4 Q 10.5 10.5 8.4 10.5 H 3.6 Q 1.5 10.5 1.5 8.4 V 3.6 Q 1.5 1.5 3.6 1.5 Z"; }
17
+ if name == "back" { return "M 6.5 1.25 L 2.5 5 L 6.5 8.75 M 12 1.25 L 8 5 L 12 8.75"; }
18
+ if name == "forward" { return "M 2 1.25 L 6 5 L 2 8.75 M 7.5 1.25 L 11.5 5 L 7.5 8.75"; }
19
+ if name == "open" { return "M 1.5 3.2 Q 1.5 1.5 3.2 1.5 H 5.2 L 6.8 3.2 H 10.8 Q 12.5 3.2 12.5 4.9 V 8.8 Q 12.5 10.5 10.8 10.5 H 3.2 Q 1.5 10.5 1.5 8.8 Z"; }
20
+ if name == "volume" { return "M 1 3.6 H 3 L 6 1.2 V 8.8 L 3 6.4 H 1 Z M 8.6 3.4 Q 9.7 5 8.6 6.6 M 10.6 1.6 Q 12.6 5 10.6 8.4"; }
21
+ if name == "mute" { return "M 1 3.6 H 3 L 6 1.2 V 8.8 L 3 6.4 H 1 Z M 8.8 3.4 L 12 6.6 M 12 3.4 L 8.8 6.6"; }
22
+ if name == "playlist" { return "M 1.25 1.5 H 11.75 M 1.25 5 H 11.75 M 1.25 8.5 H 6.5 M 9.2 7.2 L 10.5 8.5 L 11.8 7.2"; }
23
+ if name == "detach" { return "M 5.5 1.5 H 3.3 Q 1.5 1.5 1.5 3.3 V 8.7 Q 1.5 10.5 3.3 10.5 H 8.7 Q 10.5 10.5 10.5 8.7 V 6.5 M 8.5 1.5 H 12.5 V 5.5 M 12.5 1.5 L 6.5 7.5"; }
24
+ if name == "attach" { return "M 5.5 1.5 H 3.3 Q 1.5 1.5 1.5 3.3 V 8.7 Q 1.5 10.5 3.3 10.5 H 8.7 Q 10.5 10.5 10.5 8.7 V 6.5 M 12.5 1.5 L 7 7 M 7 3.5 V 7 H 10.5"; }
25
+ if name == "close" { return "M 3.5 3 L 10.5 10 M 10.5 3 L 3.5 10"; }
26
+ if name == "failed" { return "M 5 1.3 L 9.1 8.7 H 0.9 Z M 5 4.1 V 5.8 M 5 7.3 V 7.35"; }
27
+ if name == "move-top" { return "M 2.5 1.75 H 11.5 M 3 9.75 L 7 5.75 L 11 9.75"; }
28
+ if name == "move-up" { return "M 3 8 L 7 4 L 11 8"; }
29
+ if name == "move-down" { return "M 3 4 L 7 8 L 11 4"; }
30
+ if name == "move-bottom" { return "M 3 2.25 L 7 6.25 L 11 2.25 M 2.5 10.25 H 11.5"; }
31
+ if name == "search" { return "M 9 5.25 A 3.75 3.75 0 1 1 1.5 5.25 A 3.75 3.75 0 1 1 9 5.25 Z M 8 8 L 11.25 10.75"; }
32
+ if name == "chapter" { return "M 2.5 11 V 1.2 M 2.5 1.6 H 9.6 L 7.9 4.1 L 9.6 6.6 H 2.5"; }
33
+ if name == "bookmark" { return "M 3.2 1.2 H 8.8 V 10.6 L 6 8.3 L 3.2 10.6 Z"; }
34
+ if name == "check-task" { return "M 2.75 5.75 L 4.75 7.75 L 8.25 3.25"; }
35
+ if name == "check-box" { return "M 1.5 4.75 L 3.6 6.75 L 7.5 2.25"; }
36
+ if name == "menu-check" { return "M 4 7.25 L 6.25 9.5 L 10 4.75"; }
37
+ if name == "submenu" { return "M 1.25 1.25 L 3.75 4 L 1.25 6.75"; }
38
+ if name == "scroll-up" { return "M 1.25 3.75 L 4 1.25 L 6.75 3.75"; }
39
+ if name == "scroll-down" { return "M 1.25 1.25 L 4 3.75 L 6.75 1.25"; }
40
+ if name == "caret-down" { return "M 1.25 1.25 L 4 3.75 L 6.75 1.25"; }
41
+ if name == "sort-asc" { return "M 1 3.25 L 3.5 0.75 L 6 3.25"; }
42
+ if name == "sort-desc" { return "M 1 0.75 L 3.5 3.25 L 6 0.75"; }
43
+ if name == "tag-remove" { return "M 1.5 1.5 L 5.5 5.5 M 5.5 1.5 L 1.5 5.5"; }
44
+ if name == "preview-play" { return "M 1.5 1.3 L 6.9 4.5 L 1.5 7.7 Z"; }
45
+ if name == "add" { return "M 5 1.5 V 8.5 M 1.5 5 H 8.5"; }
46
+ if name == "remove" { return "M 1.5 5 H 8.5"; }
47
+ if name == "sort" { return "M 3 1.5 V 8.5 M 1.2 6.7 L 3 8.5 L 4.8 6.7 M 7 8.5 V 1.5 M 5.2 3.3 L 7 1.5 L 8.8 3.3"; }
48
+ return "";
49
+ }
50
+ // Line width.
51
+ public pure function line(name: string) -> length {
52
+ if name == "failed" || name == "chapter" || name == "bookmark" || name == "submenu" || name == "scroll-up" || name == "scroll-down" || name == "caret-down" || name == "tag-remove" || name == "preview-play" { return 1.25px; }
53
+ if name == "sort-asc" || name == "sort-desc" { return 1.1px; }
54
+ return 1.5px;
55
+ }
56
+ // The box the commands are drawn in.
57
+ public pure function box-width(name: string) -> length {
58
+ if name == "play" || name == "pause" || name == "stop" || name == "chapter" || name == "bookmark" { return 12px; }
59
+ if name == "failed" || name == "add" || name == "remove" || name == "sort" { return 10px; }
60
+ if name == "scroll-up" || name == "scroll-down" || name == "caret-down" || name == "preview-play" { return 8px; }
61
+ if name == "volume" || name == "mute" || name == "playlist" { return 13px; }
62
+ if name == "sort-asc" || name == "sort-desc" || name == "tag-remove" { return 7px; }
63
+ if name == "check-task" { return 11px; }
64
+ if name == "check-box" { return 9px; }
65
+ if name == "submenu" { return 5px; }
66
+ return 14px;
67
+ }
68
+ public pure function box-height(name: string) -> length {
69
+ if name == "back" || name == "forward" || name == "volume" || name == "mute" || name == "playlist" || name == "failed" || name == "add" || name == "remove" || name == "sort" { return 10px; }
70
+ if name == "play" || name == "pause" || name == "menu-check" { return 14px; }
71
+ if name == "scroll-up" || name == "scroll-down" || name == "caret-down" { return 5px; }
72
+ if name == "check-box" || name == "preview-play" { return 9px; }
73
+ if name == "sort-asc" || name == "sort-desc" { return 4px; }
74
+ if name == "close" { return 13px; }
75
+ if name == "check-task" { return 11px; }
76
+ if name == "submenu" { return 8px; }
77
+ if name == "tag-remove" { return 7px; }
78
+ return 12px;
79
+ }
80
+ }
81
+
82
+ // One icon, stroked in `color`; scaled when the caller sets another size.
83
+ export component Icon {
84
+ in property <string> name;
85
+ in property <brush> color: Theme.text;
86
+ width: Icons.box-width(root.name);
87
+ height: Icons.box-height(root.name);
88
+ Path {
89
+ width: 100%;
90
+ height: 100%;
91
+ viewbox-width: Icons.box-width(root.name) / 1px;
92
+ viewbox-height: Icons.box-height(root.name) / 1px;
93
+ commands: Icons.commands(root.name);
94
+ stroke: root.color;
95
+ stroke-width: Icons.line(root.name);
96
+ stroke-line-cap: round;
97
+ stroke-line-join: round;
98
+ }
99
+ }
@@ -6,6 +6,7 @@
6
6
  // open (usually `plugin.system.openUrl`).
7
7
  import { ScrollView } from "std-widgets.slint";
8
8
  import { Theme } from "theme.slint";
9
+ import { Icon } from "icons.slint";
9
10
 
10
11
  // One table row (cells are plain text).
11
12
  export struct MarkdownRow {
@@ -86,18 +87,15 @@ component MarkdownBlockView {
86
87
  y: 3px;
87
88
  width: 11px;
88
89
  height: 11px;
89
- border-width: 1px;
90
- border-radius: 2px;
90
+ border-width: block.task == 2 ? 0px : 1px;
91
+ border-radius: 3px;
91
92
  border-color: Theme.text-dim;
92
93
  background: block.task == 2 ? Theme.accent : transparent;
93
- if block.task == 2: Path {
94
+ if block.task == 2: Icon {
94
95
  width: 100%;
95
96
  height: 100%;
96
- viewbox-width: 11;
97
- viewbox-height: 11;
98
- commands: "M 2.5 5.5 L 4.5 7.5 L 8.5 3";
99
- stroke: Theme.text;
100
- stroke-width: 1.5px;
97
+ name: "check-task";
98
+ color: #ffffff;
101
99
  }
102
100
  }
103
101
  }
@@ -1,7 +1,8 @@
1
1
  // Vestra theme tokens (doc/product/ui-spec.md §2.1–2.3). Import from any
2
2
  // plugin or host Slint file: import { Theme } from "@vestra/theme.slint";
3
- // Colours follow the player's palette (R-H6: Vestra, set on every
4
- // view through ../palette.slint, which is not part of this library). They are
3
+ // Colours follow the player's palette (R-H6: `vestra`, the dark default, or
4
+ // `vestra-light`, set on every view through ../palette.slint, which is not
5
+ // part of this library). They are
5
6
  // `out` properties: Slint code reads them but cannot assign them. So is
6
7
  // font-mono (set per system). Corner radii, font sizes and control sizes
7
8
  // stay constants.
@@ -9,8 +10,10 @@
9
10
  import { VestraPalette } from "../palette.slint";
10
11
 
11
12
  export global Theme {
12
- // Colours: Vestra identity drawn from the logo (amber → magenta → violet on a
13
- // violet-tinted near-black). Sizes below are the player's control geometry
13
+ // Colours: the Aurora palette drawn from the logo's full spectrum (magenta
14
+ // accent, cyan for what is playing, amber → magenta → violet → cyan fills;
15
+ // violet-tinted near-black, or near-white in vestra-light, whose video area
16
+ // stays dark). Sizes below are the player's control geometry
14
17
  // (doc/product/ui-spec.md §2.3), the same whatever the palette.
15
18
  out property <color> bg-bar: VestraPalette.bg-bar;
16
19
  out property <color> bg-video: VestraPalette.bg-video;
@@ -35,11 +38,12 @@ export global Theme {
35
38
  out property <color> button-disabled: VestraPalette.button-disabled;
36
39
  // Errors and destructive actions: a failed status line, a Delete button.
37
40
  out property <color> danger: VestraPalette.danger;
38
- // Brand gradient for "progress" fills (seek bar, volume, sliders).
41
+ // Brand gradient for "progress" fills (seek bar, volume, sliders, accents).
39
42
  out property <brush> accent-fill: VestraPalette.accent-fill;
40
- // Soft corners echo the logo.
41
- out property <length> radius-control: 3px;
42
- out property <length> radius-panel: 6px;
43
+ // Soft corners echo the logo: controls, menu rows and hover plates use
44
+ // radius-control; menus, panels and the OSD radius-panel.
45
+ out property <length> radius-control: 4px;
46
+ out property <length> radius-panel: 8px;
43
47
  // §2.2 fonts. No default family: every window uses the system UI font,
44
48
  // and Slint falls back per character for scripts a font lacks (CJK in
45
49
  // font-mono included). font-mono is the system's own monospace family,
@@ -1,6 +1,7 @@
1
1
  // Compact controls built on the Vestra theme (core-ui-design.md §2.1):
2
2
  // import { Button, Slider, ToolTipArea, UrlInputRow } from "@vestra/widgets.slint";
3
- // Other controls come from std-widgets, which the host compiles as fluent-dark.
3
+ // Icons: @vestra/icons.slint. Other controls come from std-widgets, which the
4
+ // host compiles as fluent-dark and switches to light for a light palette.
4
5
  import { TextEdit } from "std-widgets.slint";
5
6
  import { Theme } from "theme.slint";
6
7
 
@@ -49,6 +50,7 @@ export component ToolTipArea {
49
50
  background: Theme.bg-panel;
50
51
  border-color: Theme.line;
51
52
  border-width: 1px;
53
+ border-radius: Theme.radius-control;
52
54
  HorizontalLayout {
53
55
  padding-left: 5px; padding-right: 5px; padding-top: 2px; padding-bottom: 2px;
54
56
  Text { text: root.text; color: Theme.text; font-size: Theme.font-body; }
@@ -59,7 +61,8 @@ export component ToolTipArea {
59
61
 
60
62
  // Dialog button: text (21px, or 18px when `small`), or an icon button when
61
63
  // `text` is empty and `icon` holds Path data drawn in an icon-width × icon-height
62
- // viewbox (filled, or 1.5px lines when `stroked`). The caller sizes icon buttons.
64
+ // viewbox (filled, or 1.5px round-capped lines when `stroked`, as the
65
+ // @vestra/icons.slint set). The caller sizes icon buttons.
63
66
  export component Button {
64
67
  in property <string> text;
65
68
  in property <string> icon;
@@ -112,6 +115,8 @@ export component Button {
112
115
  fill: root.stroked ? transparent : root.tint;
113
116
  stroke: root.stroked ? root.tint : transparent;
114
117
  stroke-width: root.stroked ? 1.5px : 0px;
118
+ stroke-line-cap: round;
119
+ stroke-line-join: round;
115
120
  }
116
121
  touch := TouchArea {
117
122
  enabled: root.enabled;
@@ -119,8 +124,9 @@ export component Button {
119
124
  }
120
125
  }
121
126
 
122
- // 2px line slider. Bar style (default): 8px round thumb, accent fill.
123
- // Panel style (`panel: true`): 14×12 thumb, blue fill on a dark track.
127
+ // 2px line slider. Bar style (default): 8px round thumb, a white core in a
128
+ // 2px accent ring, gradient fill. Panel style (`panel: true`): 14×12 thumb,
129
+ // gradient fill. The track is `Theme.line` in both.
124
130
  export component Slider {
125
131
  in-out property <float> value;
126
132
  in property <float> minimum: 0;
@@ -146,7 +152,8 @@ export component Slider {
146
152
  Rectangle {
147
153
  y: (parent.height - 2px) / 2;
148
154
  height: 2px;
149
- background: root.panel ? Theme.bg-bar : Theme.line;
155
+ border-radius: 1px;
156
+ background: Theme.line;
150
157
  }
151
158
  Rectangle {
152
159
  y: (parent.height - 2px) / 2;
@@ -162,10 +169,9 @@ export component Slider {
162
169
  width: root.thumb-width;
163
170
  height: root.thumb-height;
164
171
  border-radius: root.panel ? Theme.radius-control : self.height / 2;
165
- background: !root.enabled ? Theme.icon-disabled
166
- : root.panel ? Theme.text
167
- : touch.pressed ? Theme.accent-press
168
- : touch.has-hover ? Theme.accent : Theme.text;
172
+ background: !root.enabled ? Theme.icon-disabled : root.panel ? Theme.text : #ffffff;
173
+ border-width: root.panel || !root.enabled ? 0px : 2px;
174
+ border-color: touch.pressed ? Theme.accent-press : Theme.accent;
169
175
  }
170
176
  touch := TouchArea {
171
177
  enabled: root.enabled;