ags: better separator properties, add more separators on widgets

This commit is contained in:
retrozinndev
2025-04-27 08:19:26 -03:00
parent 4a2733d884
commit a0cf72ae8a
10 changed files with 100 additions and 91 deletions
+3 -9
View File
@@ -58,7 +58,7 @@
& button { & button {
border-radius: 16px; border-radius: 16px;
transition: 80ms linear; transition: 80ms linear;
min-width: 12px; min-width: 15px;
padding: 0 6px; padding: 0 6px;
background: colors.$bg-tertiary; background: colors.$bg-tertiary;
margin: 3px 0; margin: 3px 0;
@@ -144,14 +144,13 @@
box-shadow: inset 0 0 0 300px rgba(colors.$fg-primary, .2); box-shadow: inset 0 0 0 300px rgba(colors.$fg-primary, .2);
} }
& .nf { & .icon {
margin-right: 4px;
font-size: 14px; font-size: 14px;
} }
& .media-controls { & .media-controls {
transition: none; transition: none;
padding: 0 6px; margin-left: 6px;
border-top-right-radius: 12px; border-top-right-radius: 12px;
border-bottom-right-radius: 12px; border-bottom-right-radius: 12px;
@@ -169,13 +168,8 @@
& .media > box { & .media > box {
border-top-right-radius: 0; border-top-right-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
padding: 0 6px;
} }
& .media {
padding-left: 0;
padding-right: 0;
}
} }
} }
+1 -1
View File
@@ -68,7 +68,7 @@
} }
} }
& .left .top { & .left .datetime {
padding-bottom: 10px; padding-bottom: 10px;
& .time { & .time {
+16 -6
View File
@@ -7,40 +7,50 @@ export interface SeparatorProps {
cssColor?: string; cssColor?: string;
orientation?: Gtk.Orientation; orientation?: Gtk.Orientation;
size?: number; size?: number;
spacing?: number;
margin?: number;
visible?: boolean | Binding<boolean>; visible?: boolean | Binding<boolean>;
} }
export function Separator(props: SeparatorProps) { export function Separator(props: SeparatorProps = {
orientation: Gtk.Orientation.HORIZONTAL
}) {
props.alpha = props.alpha ? props.alpha = props.alpha ?
(props.alpha > 1 ? (props.alpha > 1 ?
props.alpha / 100 props.alpha / 100
: props.alpha) : props.alpha)
: 1; : 1;
props.orientation = props.orientation ?? Gtk.Orientation.HORIZONTAL;
return new Widget.Box({ return new Widget.Box({
name: "separator", name: "separator",
...(props.orientation === Gtk.Orientation.HORIZONTAL ?
{ vexpand: true } : { hexpand: true }),
className: `separator ${ props.orientation === Gtk.Orientation.VERTICAL ? className: `separator ${ props.orientation === Gtk.Orientation.VERTICAL ?
"vertical" : "horizontal" }`, "vertical" : "horizontal" }`,
visible: props.visible, visible: props.visible,
css: `.vertical { css: `.vertical {
padding: 7px 7px; padding: ${props.spacing ?? 0}px ${props.margin ?? 7}px;
} }
.horizontal { .horizontal {
padding: 4px 4px; padding: ${props.margin ?? 4}px ${props.spacing ?? 0}px;
}`, }`,
child: new Widget.Box({ child: new Widget.Box({
className: `${ props.orientation === Gtk.Orientation.VERTICAL ? className: `${ props.orientation === Gtk.Orientation.VERTICAL ?
"vertical" : "horizontal" } ${ props.class ? props.class : "" }`, "vertical" : "horizontal" } ${ props.class ? props.class : "" }`,
...(props.orientation === Gtk.Orientation.HORIZONTAL ?
{ vexpand: true } : { hexpand: true }),
css: `* { css: `* {
background: ${ props.cssColor || "lightgray" }; background: ${ props.cssColor ?? "lightgray" };
opacity: ${props.alpha}; opacity: ${props.alpha};
} }
.horizontal { .horizontal {
min-width: ${ props.size || 1 }px; min-width: ${ props.size ?? 1 }px;
} }
.vertical { .vertical {
min-height: ${ props.size || 1 }px; min-height: ${ props.size ?? 1 }px;
}` }`
} as Widget.BoxProps) } as Widget.BoxProps)
} as Widget.BoxProps); } as Widget.BoxProps);
+6 -8
View File
@@ -9,21 +9,20 @@ export function FocusedClient(): Gtk.Widget {
return new Widget.Box({ return new Widget.Box({
className: "focused-client", className: "focused-client",
visible: bind(hyprland, "focusedClient").as(Boolean), visible: bind(hyprland, "focusedClient").as(Boolean),
children: [ children: bind(hyprland, "focusedClient").as(focusedClient => focusedClient ? [
new Widget.Icon({ new Widget.Icon({
className: "icon", className: "icon",
vexpand: true, vexpand: true,
css: ".icon { font-size: 18px; }", css: ".icon { font-size: 18px; }",
icon: bind(hyprland, "focusedClient").as((client: AstalHyprland.Client) => icon: bind(focusedClient, "class").as(clss =>
client ? getAppIcon(client.initialClass) : "image-missing") getAppIcon(clss) ?? "application-x-executable-symbolic")
}), }),
new Widget.Box({ new Widget.Box({
className: "text-content", className: "text-content",
orientation: Gtk.Orientation.VERTICAL, orientation: Gtk.Orientation.VERTICAL,
homogeneous: false, homogeneous: false,
valign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER,
children: bind(hyprland, "focusedClient").as((focusedClient: AstalHyprland.Client) => children: [
focusedClient ? [
new Widget.Label({ new Widget.Label({
className: "class", className: "class",
xalign: 0, xalign: 0,
@@ -44,9 +43,8 @@ export function FocusedClient(): Gtk.Widget {
clientTitle.length > 55 ? clientTitle : ""), clientTitle.length > 55 ? clientTitle : ""),
label: bind(focusedClient, "title") label: bind(focusedClient, "title")
} as Widget.LabelProps) } as Widget.LabelProps)
] : []
)
})
] ]
})
]: [])
} as Widget.BoxProps); } as Widget.BoxProps);
} }
+17 -22
View File
@@ -2,10 +2,8 @@ import { bind, execAsync, GLib } from "astal";
import { Gtk, Widget } from "astal/gtk3"; import { Gtk, Widget } from "astal/gtk3";
import AstalMpris from "gi://AstalMpris"; import AstalMpris from "gi://AstalMpris";
import { Separator, SeparatorProps } from "../Separator"; import { Separator, SeparatorProps } from "../Separator";
import { CenterWindow } from "../../window/CenterWindow";
import { Windows } from "../../windows"; import { Windows } from "../../windows";
const mpris: AstalMpris.Mpris = AstalMpris.get_default();
const playerIcons = { const playerIcons = {
spotify: '󰓇', spotify: '󰓇',
@@ -16,8 +14,8 @@ const playerIcons = {
} }
export function Media(): Gtk.Widget { export function Media(): Gtk.Widget {
let hoverConnectionId: number;
let hoverLostConnectionId: number; const connections: Array<number> = [];
const mediaControlsRevealer: Widget.Revealer = new Widget.Revealer({ const mediaControlsRevealer: Widget.Revealer = new Widget.Revealer({
transitionType: Gtk.RevealerTransitionType.SLIDE_RIGHT, transitionType: Gtk.RevealerTransitionType.SLIDE_RIGHT,
@@ -27,7 +25,7 @@ export function Media(): Gtk.Widget {
className: "media-controls button-row", className: "media-controls button-row",
expand: false, expand: false,
homogeneous: false, homogeneous: false,
children: bind(mpris, "players").as((players: Array<AstalMpris.Player>) => children: bind(AstalMpris.get_default(), "players").as((players: Array<AstalMpris.Player>) =>
players[0] ? [ players[0] ? [
new Widget.Button({ new Widget.Button({
className: "link nf", className: "link nf",
@@ -71,21 +69,16 @@ export function Media(): Gtk.Widget {
const mediaWidget = new Widget.EventBox({ const mediaWidget = new Widget.EventBox({
className: "media-eventbox", className: "media-eventbox",
visible: bind(mpris, "players").as((players: Array<AstalMpris.Player>) => visible: bind(AstalMpris.get_default(), "players").as((players: Array<AstalMpris.Player>) =>
players[0] && players[0].get_available()), players[0] && players[0].get_available()),
onDestroy: (_) => { onDestroy: (_) => connections.map(id => _.disconnect(id)),
hoverConnectionId !== undefined &&
_.disconnect(hoverConnectionId);
hoverLostConnectionId !== undefined &&
_.disconnect(hoverLostConnectionId);
},
onClick: () => Windows.toggle("center-window"), onClick: () => Windows.toggle("center-window"),
child: new Widget.Box({ child: new Widget.Box({
className: "media", className: "media",
children: [ children: [
new Widget.Box({ new Widget.Box({
children: bind(mpris, "players").as((players: Array<AstalMpris.Player>) => spacing: 4,
children: bind(AstalMpris.get_default(), "players").as((players: Array<AstalMpris.Player>) =>
players[0] ? [ players[0] ? [
new Widget.Label({ new Widget.Label({
className: "icon nf", className: "icon nf",
@@ -102,9 +95,10 @@ export function Media(): Gtk.Widget {
} as Widget.LabelProps), } as Widget.LabelProps),
Separator({ Separator({
orientation: Gtk.Orientation.HORIZONTAL, orientation: Gtk.Orientation.HORIZONTAL,
size: 2, size: 1,
cssColor: `rgb(180, 180, 180)`, margin: 5,
alpha: 0.3 //cssColor: `rgb(180, 180, 180)`,
alpha: .3
} as SeparatorProps), } as SeparatorProps),
new Widget.Label({ new Widget.Label({
className: "artist", className: "artist",
@@ -122,15 +116,16 @@ export function Media(): Gtk.Widget {
} as Widget.BoxProps) } as Widget.BoxProps)
} as Widget.EventBoxProps); } as Widget.EventBoxProps);
hoverConnectionId = mediaWidget.connect("hover", () => { connections.push(
mediaWidget.connect("hover", () => {
mediaControlsRevealer.set_reveal_child(true); mediaControlsRevealer.set_reveal_child(true);
mediaWidget.className = mediaWidget.className + " reveal"; mediaWidget.className = mediaWidget.className + " reveal";
}); }),
mediaWidget.connect("hover-lost", (_) => {
hoverLostConnectionId = mediaWidget.connect("hover-lost", (_) => {
mediaControlsRevealer.set_reveal_child(false); mediaControlsRevealer.set_reveal_child(false);
_.className = mediaWidget.className.replaceAll(" reveal", ""); _.className = mediaWidget.className.replaceAll(" reveal", "");
}); })
);
return mediaWidget; return mediaWidget;
} }
+12 -12
View File
@@ -41,7 +41,8 @@ export function Workspaces(): Gtk.Widget {
: "" : ""
} ${lastClient.title}` : "" }`)(), } ${lastClient.title}` : "" }`)(),
child: new Widget.Box({ child: new Widget.Box({
children: [ visible: bind(workspace, "lastClient").as(Boolean),
children: bind(workspace, "lastClient").as((lastClient) => [
new Widget.Revealer({ new Widget.Revealer({
transitionDuration: 200, transitionDuration: 200,
transitionType: Gtk.RevealerTransitionType.SLIDE_LEFT, transitionType: Gtk.RevealerTransitionType.SLIDE_LEFT,
@@ -55,17 +56,16 @@ export function Workspaces(): Gtk.Widget {
} as Widget.RevealerProps), } as Widget.RevealerProps),
new Widget.Icon({ new Widget.Icon({
className: "last-app-icon", className: "last-app-icon",
visible: Variable.derive([ visible: bind(hyprland, "focusedWorkspace").as(focusedWorkspace =>
bind(workspace, "lastClient"), workspace.id === focusedWorkspace.id ?
bind(hyprland, "focusedWorkspace") false
], (lastClient, focusedWorkspace) => focusedWorkspace?.id === workspace.id ? : Boolean(lastClient)),
false : Boolean(lastClient))(), icon: lastClient ?
icon: bind(workspace, "lastClient").as((lastClient) => bind(lastClient, "class").as((clss) =>
lastClient ? getAppIcon(clss) ?? "application-x-executable-symbolic")
getAppIcon(lastClient.initialClass) || "image-missing" : undefined
: "image-missing") } as Widget.IconProps)
} as Widget.IconProps), ])
]
} as Widget.BoxProps), } as Widget.BoxProps),
onClicked: () => workspace.focus() onClicked: () => workspace.focus()
} as Widget.ButtonProps) } as Widget.ButtonProps)
@@ -35,11 +35,13 @@ export const BluetoothPage: (() => Page) = () => new Page({
} as Widget.ButtonProps) } as Widget.ButtonProps)
], ],
onClose: () => stopBluetoothDevicesWatch(), onClose: () => stopBluetoothDevicesWatch(),
spacing: 2,
children: [ children: [
new Widget.Box({ new Widget.Box({
className: "adapters", className: "adapters",
visible: bind(AstalBluetooth.get_default(), "adapters").as((adapters) => visible: bind(AstalBluetooth.get_default(), "adapters").as((adapters) =>
adapters.length > 1), adapters.length > 1),
spacing: 2,
children: bind(AstalBluetooth.get_default(), "adapters").as((adapters) => [ children: bind(AstalBluetooth.get_default(), "adapters").as((adapters) => [
new Widget.Label({ new Widget.Label({
className: "sub-header", className: "sub-header",
@@ -59,6 +61,7 @@ export const BluetoothPage: (() => Page) = () => new Page({
className: "connections", className: "connections",
orientation: Gtk.Orientation.VERTICAL, orientation: Gtk.Orientation.VERTICAL,
hexpand: true, hexpand: true,
spacing: 2,
children: [ children: [
new Widget.Box({ new Widget.Box({
className: "paired", className: "paired",
+2
View File
@@ -11,6 +11,7 @@ export type PageProps = {
description?: string | Binding<string>; description?: string | Binding<string>;
headerButtons?: Array<Gtk.Button> | Binding<Array<Gtk.Button>>; headerButtons?: Array<Gtk.Button> | Binding<Array<Gtk.Button>>;
orientation?: Gtk.Orientation | Binding<Gtk.Orientation>; orientation?: Gtk.Orientation | Binding<Gtk.Orientation>;
spacing?: number;
child?: Gtk.Widget | Binding<Gtk.Widget>; child?: Gtk.Widget | Binding<Gtk.Widget>;
children?: Array<Gtk.Widget> | Binding<Array<Gtk.Widget>>; children?: Array<Gtk.Widget> | Binding<Array<Gtk.Widget>>;
}; };
@@ -76,6 +77,7 @@ class Page extends Widget.Box {
} as Widget.BoxProps), } as Widget.BoxProps),
new Widget.Box({ new Widget.Box({
className: "content", className: "content",
spacing: props.spacing ?? 4,
orientation: props.orientation ?? Gtk.Orientation.VERTICAL, orientation: props.orientation ?? Gtk.Orientation.VERTICAL,
expand: true, expand: true,
setup: props.setup, setup: props.setup,
+10
View File
@@ -8,6 +8,9 @@ import { Apps } from "../widget/bar/Apps";
import { Clock } from "../widget/bar/Clock"; import { Clock } from "../widget/bar/Clock";
import { Status } from "../widget/bar/Status"; import { Status } from "../widget/bar/Status";
import { SpecialWorkspaces } from "../widget/bar/SpecialWorkspaces"; import { SpecialWorkspaces } from "../widget/bar/SpecialWorkspaces";
import { Separator, SeparatorProps } from "../widget/Separator";
import AstalHyprland from "gi://AstalHyprland?version=0.1";
import { bind } from "astal";
export const Bar = (mon: number) => { export const Bar = (mon: number) => {
const widgetSpacing = 4; const widgetSpacing = 4;
@@ -34,6 +37,13 @@ export const Bar = (mon: number) => {
children: [ children: [
Apps(), Apps(),
SpecialWorkspaces(), SpecialWorkspaces(),
Separator({
alpha: .2,
orientation: Gtk.Orientation.HORIZONTAL,
margin: 14,
visible: bind(AstalHyprland.get_default(), "workspaces").as(wss =>
wss.filter(ws => ws.id < 0).length > 0)
} as SeparatorProps),
Workspaces(), Workspaces(),
FocusedClient() FocusedClient()
] ]
+6 -9
View File
@@ -14,13 +14,14 @@ export const CenterWindow = (mon: number) => PopupWindow({
monitor: mon, monitor: mon,
child: new Widget.Box({ child: new Widget.Box({
className: "center-window-container", className: "center-window-container",
spacing: 6,
children: [ children: [
new Widget.Box({ new Widget.Box({
className: "vertical left", className: "left",
orientation: Gtk.Orientation.VERTICAL, orientation: Gtk.Orientation.VERTICAL,
children: [ children: [
new Widget.Box({ new Widget.Box({
className: "top", className: "datetime",
orientation: Gtk.Orientation.VERTICAL, orientation: Gtk.Orientation.VERTICAL,
valign: Gtk.Align.START, valign: Gtk.Align.START,
children: [ children: [
@@ -52,16 +53,12 @@ export const CenterWindow = (mon: number) => PopupWindow({
} as Widget.BoxProps), } as Widget.BoxProps),
Separator({ Separator({
orientation: Gtk.Orientation.HORIZONTAL, orientation: Gtk.Orientation.HORIZONTAL,
alpha: .5,
cssColor: "gray", cssColor: "gray",
margin: 5,
alpha: .3,
visible: bind(AstalMpris.get_default(), "players").as(players => players.length > 0), visible: bind(AstalMpris.get_default(), "players").as(players => players.length > 0),
size: 1
} as SeparatorProps), } as SeparatorProps),
new Widget.Box({ BigMedia()
className: "vertical right",
orientation: Gtk.Orientation.VERTICAL,
child: BigMedia()
} as Widget.BoxProps)
] ]
} as Widget.BoxProps) } as Widget.BoxProps)
} as PopupWindowProps); } as PopupWindowProps);