summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-02-18 22:34:13 +1100
committer2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-02-18 22:34:13 +1100
commit0b771cbd1bfccdcbf4cbaabfed13eece4a2e8929 (patch)
treeb425f18696b5e17db585a90c39f1b3e7b1959c5c
parentbar: transparent + more round (diff)
downloadcaelestia-shell-0b771cbd1bfccdcbf4cbaabfed13eece4a2e8929.tar.gz
caelestia-shell-0b771cbd1bfccdcbf4cbaabfed13eece4a2e8929.tar.bz2
caelestia-shell-0b771cbd1bfccdcbf4cbaabfed13eece4a2e8929.zip
bar: vertical mode
-rw-r--r--config.ts3
-rw-r--r--scss/bar.scss147
-rw-r--r--src/modules/bar.tsx58
-rw-r--r--src/utils/widgets.ts2
-rw-r--r--src/widgets/popupwindow.ts22
5 files changed, 164 insertions, 68 deletions
diff --git a/config.ts b/config.ts
index 667e786..7aa6b8d 100644
--- a/config.ts
+++ b/config.ts
@@ -2,7 +2,8 @@ import { Astal } from "astal/gtk3";
// Modules
export const bar = {
- wsPerGroup: 10,
+ vertical: true,
+ wsPerGroup: 5,
dateTimeFormat: "%d/%m/%y %R",
};
diff --git a/scss/bar.scss b/scss/bar.scss
index fb47501..d4dd974 100644
--- a/scss/bar.scss
+++ b/scss/bar.scss
@@ -6,22 +6,12 @@
.bar {
@include font.mono;
- margin: 10px 10px 0 10px;
font-size: lib.s(14);
- @include lib.spacing(10);
-
- & > * {
- @include lib.spacing(10);
- }
-
.module {
@include lib.rounded(8);
- padding: lib.s(3) lib.s(8);
background-color: scheme.$base;
-
- @include lib.spacing;
}
label.icon {
@@ -33,7 +23,6 @@
color: scheme.$yellow;
font-size: lib.s(14);
- padding-right: lib.s(12);
}
.active-window {
@@ -43,55 +32,35 @@
.media-playing {
color: scheme.$lavender;
- @include lib.spacing(8);
-
icon {
font-size: lib.s(16);
}
}
- .workspaces {
- padding: lib.s(3) lib.s(18);
-
- @include lib.spacing(10);
-
- & > * {
- @include lib.rounded(100);
- @include lib.element-decel;
+ .workspaces > * {
+ @include lib.rounded(100);
+ @include lib.element-decel;
- min-width: lib.s(8);
- min-height: lib.s(8);
- background-color: scheme.$surface1;
+ min-width: lib.s(8);
+ min-height: lib.s(8);
+ background-color: scheme.$surface1;
- &.occupied {
- background-color: scheme.$overlay1;
- }
+ &.occupied {
+ background-color: scheme.$overlay1;
+ }
- &.focused {
- min-width: lib.s(30);
- background-color: scheme.$mauve;
- }
+ &.focused {
+ background-color: scheme.$mauve;
}
}
.tray {
font-size: lib.s(15);
color: scheme.$text;
-
- @include lib.spacing(10);
}
.status-icons {
color: scheme.$rosewater;
-
- .bluetooth {
- @include lib.spacing(10);
-
- // The spacing doesn't look right for some reason so this
- & > :first-child:not(:last-child) {
- margin-right: lib.s(5);
- }
- }
}
.pkg-updates {
@@ -123,4 +92,98 @@
font-weight: bold;
font-size: lib.s(16);
}
+
+ &.horizontal {
+ margin: 10px 10px 0 10px;
+
+ @include lib.spacing(10);
+
+ & > * {
+ @include lib.spacing(10);
+ }
+
+ .module {
+ padding: lib.s(3) lib.s(8);
+
+ @include lib.spacing;
+ }
+
+ .os-icon {
+ padding-right: lib.s(12);
+ }
+
+ .media-playing {
+ @include lib.spacing(8);
+ }
+
+ .workspaces {
+ padding: lib.s(3) lib.s(18);
+
+ @include lib.spacing(10);
+
+ & > .focused {
+ min-width: lib.s(30);
+ }
+ }
+
+ .tray {
+ @include lib.spacing(10);
+ }
+
+ .status-icons .bluetooth {
+ @include lib.spacing(10);
+
+ // The spacing doesn't look right for some reason so this
+ & > :first-child:not(:last-child) {
+ margin-right: lib.s(5);
+ }
+ }
+ }
+
+ &.vertical {
+ margin: 10px 0 10px 10px;
+
+ @include lib.spacing(10, true);
+
+ & > * {
+ @include lib.spacing(10, true);
+ }
+
+ .module {
+ padding: lib.s(8);
+
+ @include lib.spacing($vertical: true);
+ }
+
+ .os-icon > * {
+ margin-left: lib.s(-5);
+ }
+
+ .media-playing {
+ @include lib.spacing(8, true);
+ }
+
+ .workspaces {
+ padding: lib.s(18) lib.s(3);
+
+ @include lib.spacing(10, true);
+
+ & > .focused {
+ min-height: lib.s(30);
+ }
+ }
+
+ .tray {
+ @include lib.spacing(10, true);
+ }
+
+ .status-icons .bluetooth {
+ @include lib.spacing(10, true);
+
+ // The spacing doesn't look right for some reason so this
+ & > :first-child:not(:last-child) {
+ margin-bottom: lib.s(5);
+ }
+ }
+ }
}
diff --git a/src/modules/bar.tsx b/src/modules/bar.tsx
index ad11f43..33a5a9b 100644
--- a/src/modules/bar.tsx
+++ b/src/modules/bar.tsx
@@ -68,14 +68,15 @@ const togglePopup = (self: JSX.Element, event: Astal.ClickEvent, name: string) =
const OSIcon = () => (
<button
className="module os-icon"
- label={osIcon}
onClick={(self, event) => event.button === Astal.MouseButton.PRIMARY && togglePopup(self, event, "sideleft")}
- />
+ >
+ {osIcon}
+ </button>
);
const ActiveWindow = () => (
<box
- hasTooltip
+ vertical={config.vertical}
className="module active-window"
setup={self => {
const title = Variable("");
@@ -101,8 +102,13 @@ const ActiveWindow = () => (
}
/>
<label
+ angle={config.vertical ? 270 : 0}
setup={self =>
- hookFocusedClientProp(self, "title", c => (self.label = c?.title ? ellipsize(c.title) : "Desktop"))
+ hookFocusedClientProp(
+ self,
+ "title",
+ c => (self.label = c?.title ? ellipsize(c.title, config.vertical ? 30 : 40) : "Desktop")
+ )
}
/>
</box>
@@ -126,7 +132,7 @@ const MediaPlaying = () => {
setupCustomTooltip(self, bind(label));
}}
>
- <box className="module media-playing">
+ <box vertical={config.vertical} className="module media-playing">
<icon
setup={self =>
players.hookLastPlayer(self, "notify::identity", () => {
@@ -142,6 +148,7 @@ const MediaPlaying = () => {
}
/>
<label
+ angle={config.vertical ? 270 : 0}
setup={self =>
players.hookLastPlayer(self, ["notify::title", "notify::artist"], () => {
self.label = ellipsize(getLabel("No media")); // TODO: scroll text
@@ -195,7 +202,7 @@ const Workspaces = () => (
hyprland.dispatch("workspace", (event.delta_y < 0 ? "-" : "+") + 1);
}}
>
- <box className="module workspaces">
+ <box vertical={config.vertical} className="module workspaces">
{Array.from({ length: config.wsPerGroup }).map((_, idx) => (
<Workspace idx={idx + 1} /> // Start from 1
))}
@@ -248,7 +255,11 @@ const TrayItem = (item: AstalTray.TrayItem) => {
};
const Tray = () => (
- <box className="module tray" visible={bind(AstalTray.get_default(), "items").as(i => i.length > 0)}>
+ <box
+ vertical={config.vertical}
+ className="module tray"
+ visible={bind(AstalTray.get_default(), "items").as(i => i.length > 0)}
+ >
{bind(AstalTray.get_default(), "items").as(i => i.map(TrayItem))}
</box>
);
@@ -378,7 +389,7 @@ const BluetoothDevice = (device: AstalBluetooth.Device) => (
);
const Bluetooth = () => (
- <box className="bluetooth">
+ <box vertical={config.vertical} className="bluetooth">
<button
onClick={(self, event) => {
if (event.button === Astal.MouseButton.PRIMARY) togglePopup(self, event, "bluetooth-devices");
@@ -424,7 +435,7 @@ const Bluetooth = () => (
);
const StatusIcons = () => (
- <box className="module status-icons">
+ <box vertical={config.vertical} className="module status-icons">
<Network />
<Bluetooth />
</box>
@@ -440,7 +451,7 @@ const PkgUpdates = () => (
)
}
>
- <box className="module pkg-updates">
+ <box vertical={config.vertical} className="module pkg-updates">
<label className="icon" label="download" />
<label label={bind(Updates.get_default(), "numUpdates").as(String)} />
</box>
@@ -461,7 +472,7 @@ const NotifCount = () => (
)
}
>
- <box className="module notif-count">
+ <box vertical={config.vertical} className="module notif-count">
<label className="icon" label="info" />
<label label={bind(AstalNotifd.get_default(), "notifications").as(n => String(n.length))} />
</box>
@@ -476,6 +487,7 @@ const Battery = () => {
return (
<box
+ vertical={config.vertical}
className={bind(className)}
setup={self =>
setupCustomTooltip(
@@ -486,7 +498,9 @@ const Battery = () => {
onDestroy={() => className.drop()}
>
<revealer
- transitionType={Gtk.RevealerTransitionType.SLIDE_RIGHT}
+ transitionType={
+ config.vertical ? Gtk.RevealerTransitionType.SLIDE_UP : Gtk.RevealerTransitionType.SLIDE_LEFT
+ }
transitionDuration={150}
revealChild={bind(AstalBattery.get_default(), "charging")}
>
@@ -502,9 +516,9 @@ const DateTime = () => (
<button
onClick={(self, event) => event.button === Astal.MouseButton.PRIMARY && togglePopup(self, event, "sideright")}
>
- <box className="module date-time">
+ <box vertical={config.vertical} className="module date-time">
<label className="icon" label="calendar_month" />
- <label label={bindCurrentTime(config.dateTimeFormat)} />
+ <label angle={config.vertical ? 270 : 0} label={bindCurrentTime(config.dateTimeFormat)} />
</box>
</button>
);
@@ -521,25 +535,29 @@ export default ({ monitor }: { monitor: Monitor }) => (
<window
namespace="caelestia-bar"
monitor={monitor.id}
- anchor={Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT | Astal.WindowAnchor.RIGHT}
+ anchor={
+ Astal.WindowAnchor.TOP |
+ Astal.WindowAnchor.LEFT |
+ (config.vertical ? Astal.WindowAnchor.BOTTOM : Astal.WindowAnchor.RIGHT)
+ }
exclusivity={Astal.Exclusivity.EXCLUSIVE}
>
- <centerbox className="bar">
- <box>
+ <centerbox vertical={config.vertical} className={`bar ${config.vertical ? "vertical" : " horizontal"}`}>
+ <box vertical={config.vertical}>
<OSIcon />
<ActiveWindow />
<MediaPlaying />
<button
- hexpand
+ expand
onScroll={(_, event) =>
event.delta_y > 0 ? (monitor.brightness -= 0.1) : (monitor.brightness += 0.1)
}
/>
</box>
<Workspaces />
- <box>
+ <box vertical={config.vertical}>
<button
- hexpand
+ expand
onScroll={(_, event) => {
const speaker = AstalWp01.get_default()?.audio.defaultSpeaker;
if (!speaker) return;
diff --git a/src/utils/widgets.ts b/src/utils/widgets.ts
index c6f0f19..9802263 100644
--- a/src/utils/widgets.ts
+++ b/src/utils/widgets.ts
@@ -6,6 +6,8 @@ import type { AstalWidget } from "./types";
export const setupCustomTooltip = (self: AstalWidget, text: string | Binding<string>) => {
if (!text) return null;
+ self.set_has_tooltip(true);
+
const window = new Widget.Window({
visible: false,
namespace: "caelestia-tooltip",
diff --git a/src/widgets/popupwindow.ts b/src/widgets/popupwindow.ts
index ffed396..2ba49fc 100644
--- a/src/widgets/popupwindow.ts
+++ b/src/widgets/popupwindow.ts
@@ -1,5 +1,6 @@
import { Binding, register } from "astal";
import { App, Astal, Gdk, Widget } from "astal/gtk3";
+import { bar } from "config";
import AstalHyprland from "gi://AstalHyprland?version=0.1";
const extendProp = <T>(
@@ -29,19 +30,30 @@ export default class PopupWindow extends Widget.Window {
popup_at_widget(widget: JSX.Element, event: Gdk.Event | Astal.ClickEvent) {
const { width, height } = widget.get_allocation();
- const mWidth = AstalHyprland.get_default().get_focused_monitor().get_width();
+ const { width: mWidth, height: mHeight } = AstalHyprland.get_default().get_focused_monitor();
const pWidth = this.get_preferred_width()[1];
+ const pHeight = this.get_preferred_height()[1];
const [, x, y] = event instanceof Gdk.Event ? event.get_coords() : [null, event.x, event.y];
const { x: cx, y: cy } = AstalHyprland.get_default().get_cursor_position();
- let marginLeft = cx + ((width - pWidth) / 2 - x);
- if (marginLeft < 0) marginLeft = 0;
- else if (marginLeft + pWidth > mWidth) marginLeft = mWidth - pWidth;
+ let marginLeft = 0;
+ let marginTop = 0;
+ if (bar.vertical) {
+ marginLeft = cx + (width - x);
+ marginTop = cy + ((height - pHeight) / 2 - y);
+ if (marginTop < 0) marginTop = 0;
+ else if (marginTop + pHeight > mHeight) marginTop = mHeight - pHeight;
+ } else {
+ marginLeft = cx + ((width - pWidth) / 2 - x);
+ if (marginLeft < 0) marginLeft = 0;
+ else if (marginLeft + pWidth > mWidth) marginLeft = mWidth - pWidth;
+ marginTop = cy + (height - y);
+ }
this.anchor = Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT;
this.exclusivity = Astal.Exclusivity.IGNORE;
this.marginLeft = marginLeft;
- this.marginTop = cy + (height - y);
+ this.marginTop = marginTop;
this.show();
}