diff --git a/config/ags/bar/.gitignore b/config/ags/bar/.gitignore
new file mode 100644
index 0000000..298eb4d
--- /dev/null
+++ b/config/ags/bar/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+@girs/
diff --git a/config/ags/bar/app.ts b/config/ags/bar/app.ts
new file mode 100644
index 0000000..83217ef
--- /dev/null
+++ b/config/ags/bar/app.ts
@@ -0,0 +1,10 @@
+import { App } from "astal/gtk3"
+import style from "./style.scss"
+import Bar from "./widget/Bar"
+
+App.start({
+ css: style,
+ main() {
+ App.get_monitors().map(Bar)
+ },
+})
diff --git a/config/ags/bar/env.d.ts b/config/ags/bar/env.d.ts
new file mode 100644
index 0000000..467c0a4
--- /dev/null
+++ b/config/ags/bar/env.d.ts
@@ -0,0 +1,21 @@
+declare const SRC: string
+
+declare module "inline:*" {
+ const content: string
+ export default content
+}
+
+declare module "*.scss" {
+ const content: string
+ export default content
+}
+
+declare module "*.blp" {
+ const content: string
+ export default content
+}
+
+declare module "*.css" {
+ const content: string
+ export default content
+}
diff --git a/config/ags/bar/package.json b/config/ags/bar/package.json
new file mode 100644
index 0000000..44226f2
--- /dev/null
+++ b/config/ags/bar/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "astal-shell",
+ "dependencies": {
+ "astal": "/usr/share/astal/gjs"
+ }
+}
diff --git a/config/ags/bar/style.scss b/config/ags/bar/style.scss
new file mode 100644
index 0000000..1d0d3a9
--- /dev/null
+++ b/config/ags/bar/style.scss
@@ -0,0 +1,20 @@
+// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/theme/Adwaita/_colors-public.scss
+$fg-color: #{"@theme_fg_color"};
+$bg-color: #{"@theme_bg_color"};
+
+window.Bar {
+ background: transparent;
+ color: $fg-color;
+ font-weight: bold;
+
+ >centerbox {
+ background: $bg-color;
+ border-radius: 10px;
+ margin: 8px;
+ }
+
+ button {
+ border-radius: 8px;
+ margin: 2px;
+ }
+}
diff --git a/config/ags/bar/tsconfig.json b/config/ags/bar/tsconfig.json
new file mode 100644
index 0000000..9471e35
--- /dev/null
+++ b/config/ags/bar/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "experimentalDecorators": true,
+ "strict": true,
+ "target": "ES2022",
+ "module": "ES2022",
+ "moduleResolution": "Bundler",
+ // "checkJs": true,
+ // "allowJs": true,
+ "jsx": "react-jsx",
+ "jsxImportSource": "astal/gtk3",
+ }
+}
diff --git a/config/ags/bar/widget/Bar.tsx b/config/ags/bar/widget/Bar.tsx
new file mode 100644
index 0000000..0384535
--- /dev/null
+++ b/config/ags/bar/widget/Bar.tsx
@@ -0,0 +1,31 @@
+import { App, Astal, Gtk, Gdk } from "astal/gtk3"
+import { Variable } from "astal"
+
+const time = Variable("").poll(1000, "date")
+
+export default function Bar(gdkmonitor: Gdk.Monitor) {
+ const { TOP, LEFT, RIGHT } = Astal.WindowAnchor
+
+ return
+
+
+
+
+
+
+}
diff --git a/config/ags/launcher/.gitignore b/config/ags/launcher/.gitignore
new file mode 100644
index 0000000..298eb4d
--- /dev/null
+++ b/config/ags/launcher/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+@girs/
diff --git a/config/ags/launcher/app.ts b/config/ags/launcher/app.ts
new file mode 100644
index 0000000..83217ef
--- /dev/null
+++ b/config/ags/launcher/app.ts
@@ -0,0 +1,10 @@
+import { App } from "astal/gtk3"
+import style from "./style.scss"
+import Bar from "./widget/Bar"
+
+App.start({
+ css: style,
+ main() {
+ App.get_monitors().map(Bar)
+ },
+})
diff --git a/config/ags/launcher/definitions/components.d.ts b/config/ags/launcher/definitions/components.d.ts
new file mode 100644
index 0000000..7f8d342
--- /dev/null
+++ b/config/ags/launcher/definitions/components.d.ts
@@ -0,0 +1,62 @@
+/*
+* dotfiles - components.d.ts
+*
+* Created by Janis Hutz 03/22/2025, Licensed under the GPL V3 License
+* https://janishutz.com, development@janishutz.com
+*
+*
+*/
+
+import type { UIComponent, ResultElement } from "./rendering";
+
+
+export interface App extends ResultElement {
+ /**
+ * The app start command that will be executed
+ */
+ command: string;
+}
+
+// TODO: Finish
+export interface DictionaryEntry extends ResultElement {
+
+}
+
+// TODO: Finish
+export interface CMDOutput extends ResultElement {
+
+}
+
+// TODO: Finish
+export interface Calculation extends ResultElement {
+
+}
+
+
+/* ************* *
+ * UI Components *
+ * ************* */
+
+export interface LargeUIComponent extends UIComponent {
+ /**
+ * The number of items to display per line. Image size will automatically be scaled
+ * based on width
+ */
+ itemsPerLine: number;
+}
+
+export interface MediumUIComponent extends UIComponent {}
+
+export interface ListUIComponent extends UIComponent {}
+
+export interface DictionaryUIComponent extends UIComponent {
+ elements: DictionaryEntry[];
+}
+
+export interface CMDOutputUIComponent extends UIComponent {
+ elements: CMDOutput[];
+}
+
+export interface CalculationUIComponent extends UIComponent {
+ elements: Calculation[];
+}
diff --git a/config/ags/launcher/definitions/job.d.ts b/config/ags/launcher/definitions/job.d.ts
new file mode 100644
index 0000000..e69de29
diff --git a/config/ags/launcher/definitions/rendering.d.ts b/config/ags/launcher/definitions/rendering.d.ts
new file mode 100644
index 0000000..035186f
--- /dev/null
+++ b/config/ags/launcher/definitions/rendering.d.ts
@@ -0,0 +1,60 @@
+/*
+* dotfiles - rendering.d.ts
+*
+* Created by Janis Hutz 03/22/2025, Licensed under the GPL V3 License
+* https://janishutz.com, development@janishutz.com
+*
+*
+*/
+
+export interface UIComponent {
+ /**
+ * The title of the component (like a category name), shown above small divider line
+ */
+ title: string;
+
+ /**
+ * ResultElement list, made up of all elements that should be shown
+ */
+ elements: ResultElement[];
+
+ /**
+ * Choose how many elements to show before truncating (will expand when command is run)
+ */
+ truncate: number;
+
+ /**
+ * The weight of the element (determines order)
+ */
+ weight: number;
+}
+
+
+export interface ResultElement {
+ /**
+ * The name of the result element
+ */
+ name: string;
+
+ /**
+ * Path to the image to be displayed in the UI
+ */
+ img: string;
+
+ /**
+ * The weight of the element (determines order)
+ */
+ weight: number;
+
+ /**
+ * The action to be executed
+ */
+ action: Action;
+
+ /**
+ * The font size of the text (optional)
+ */
+ fontSize: number | undefined;
+}
+
+type Action = '';
diff --git a/config/ags/launcher/env.d.ts b/config/ags/launcher/env.d.ts
new file mode 100644
index 0000000..467c0a4
--- /dev/null
+++ b/config/ags/launcher/env.d.ts
@@ -0,0 +1,21 @@
+declare const SRC: string
+
+declare module "inline:*" {
+ const content: string
+ export default content
+}
+
+declare module "*.scss" {
+ const content: string
+ export default content
+}
+
+declare module "*.blp" {
+ const content: string
+ export default content
+}
+
+declare module "*.css" {
+ const content: string
+ export default content
+}
diff --git a/config/ags/launcher/package.json b/config/ags/launcher/package.json
new file mode 100644
index 0000000..44226f2
--- /dev/null
+++ b/config/ags/launcher/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "astal-shell",
+ "dependencies": {
+ "astal": "/usr/share/astal/gjs"
+ }
+}
diff --git a/config/ags/launcher/style.scss b/config/ags/launcher/style.scss
new file mode 100644
index 0000000..1d0d3a9
--- /dev/null
+++ b/config/ags/launcher/style.scss
@@ -0,0 +1,20 @@
+// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/theme/Adwaita/_colors-public.scss
+$fg-color: #{"@theme_fg_color"};
+$bg-color: #{"@theme_bg_color"};
+
+window.Bar {
+ background: transparent;
+ color: $fg-color;
+ font-weight: bold;
+
+ >centerbox {
+ background: $bg-color;
+ border-radius: 10px;
+ margin: 8px;
+ }
+
+ button {
+ border-radius: 8px;
+ margin: 2px;
+ }
+}
diff --git a/config/ags/launcher/tsconfig.json b/config/ags/launcher/tsconfig.json
new file mode 100644
index 0000000..9471e35
--- /dev/null
+++ b/config/ags/launcher/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "experimentalDecorators": true,
+ "strict": true,
+ "target": "ES2022",
+ "module": "ES2022",
+ "moduleResolution": "Bundler",
+ // "checkJs": true,
+ // "allowJs": true,
+ "jsx": "react-jsx",
+ "jsxImportSource": "astal/gtk3",
+ }
+}
diff --git a/config/ags/launcher/ui/AppLauncher.tsx b/config/ags/launcher/ui/AppLauncher.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/config/ags/launcher/ui/components/calc.tsx b/config/ags/launcher/ui/components/calc.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/config/ags/launcher/ui/components/cmd.tsx b/config/ags/launcher/ui/components/cmd.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/config/ags/launcher/ui/components/dict.tsx b/config/ags/launcher/ui/components/dict.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/config/ags/launcher/ui/components/large.tsx b/config/ags/launcher/ui/components/large.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/config/ags/launcher/ui/components/list.tsx b/config/ags/launcher/ui/components/list.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/config/ags/launcher/ui/components/medium.tsx b/config/ags/launcher/ui/components/medium.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/config/ags/launcher/util/file.ts b/config/ags/launcher/util/file.ts
new file mode 100644
index 0000000..39a0f1d
--- /dev/null
+++ b/config/ags/launcher/util/file.ts
@@ -0,0 +1,10 @@
+/*
+* dotfiles - file.ts
+*
+* Created by Janis Hutz 03/22/2025, Licensed under the GPL V3 License
+* https://janishutz.com, development@janishutz.com
+*
+*
+*/
+
+import { readFileAsync, writeFileAsync, monitorFile } from "astal";
diff --git a/config/ags/launcher/util/fzf.ts b/config/ags/launcher/util/fzf.ts
new file mode 100644
index 0000000..e69de29
diff --git a/config/ags/launcher/util/search.ts b/config/ags/launcher/util/search.ts
new file mode 100644
index 0000000..e69de29
diff --git a/config/ags/launcher/util/subprocessRunner.ts b/config/ags/launcher/util/subprocessRunner.ts
new file mode 100644
index 0000000..a74877e
--- /dev/null
+++ b/config/ags/launcher/util/subprocessRunner.ts
@@ -0,0 +1,43 @@
+/*
+ * dotfiles - subprocessRunner.ts
+ *
+ * Created by Janis Hutz 03/22/2025, Licensed under the GPL V3 License
+ * https://janishutz.com, development@janishutz.com
+ *
+ *
+ */
+
+import { subprocess, execAsync, Process } from "astal/process";
+
+// TODO: Get cwd and the likes to then use that to run JavaScript files with node / python with python, etc
+
+/**
+ * Run a subprocess. If you simply want to run a command that doesn't need continuous updates
+ * run executeCommand instead.
+ * @param cmd - The command to be run
+ * @param onOut - Calback function for stdout of the subprocess
+ * @param onErr - [TODO:description]
+ * @returns [TODO:return]
+ */
+const startSubProcess = (
+ cmd: string | string[],
+ onOut: (stdout: string) => void,
+ onErr: (stderr: string) => void | undefined,
+): Process => {
+ return subprocess( cmd, onOut, onErr );
+};
+
+/**
+ * Run a command. If you need continuous updates, run startSubProcess instead
+ * @param cmd - The command to be run. Either a string or an array of strings
+ * @returns A Promise resolving to stdout of the command
+ */
+const executeCommand = (cmd: string | string[]): Promise => {
+ return execAsync( cmd );
+};
+
+
+export default {
+ startSubProcess,
+ executeCommand
+}
diff --git a/config/ags/notifications/.gitignore b/config/ags/notifications/.gitignore
new file mode 100644
index 0000000..298eb4d
--- /dev/null
+++ b/config/ags/notifications/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+@girs/
diff --git a/config/ags/notifications/app.ts b/config/ags/notifications/app.ts
new file mode 100644
index 0000000..548b260
--- /dev/null
+++ b/config/ags/notifications/app.ts
@@ -0,0 +1,29 @@
+import { App } from "astal/gtk3"
+import style from "./style.scss"
+
+import not from "./handler"
+
+App.start({
+ instanceName: "notifier",
+ css: style,
+ main() {
+ not.startNotificationHandler( 0, App.get_monitors()[0] )
+ },
+ requestHandler(request, res) {
+ if ( request == 'show' ) {
+ not.openNotificationMenu( 0 );
+ res( 'Showing all open notifications' );
+ } else if ( request == 'hide' ) {
+ not.closeNotificationMenu( 0 );
+ res( 'Hid all notifications' );
+ } else if ( request == 'clear' ) {
+ not.clearAllNotifications( 0 );
+ res( 'Cleared all notifications' );
+ } else if ( request == 'clear-newest' ) {
+ not.clearNewestNotifications( 0 );
+ res( 'Cleared newest notification' );
+ } else {
+ res( 'Unknown command!' );
+ }
+ },
+})
diff --git a/config/ags/notifications/env.d.ts b/config/ags/notifications/env.d.ts
new file mode 100644
index 0000000..467c0a4
--- /dev/null
+++ b/config/ags/notifications/env.d.ts
@@ -0,0 +1,21 @@
+declare const SRC: string
+
+declare module "inline:*" {
+ const content: string
+ export default content
+}
+
+declare module "*.scss" {
+ const content: string
+ export default content
+}
+
+declare module "*.blp" {
+ const content: string
+ export default content
+}
+
+declare module "*.css" {
+ const content: string
+ export default content
+}
diff --git a/config/ags/notifications/handler.tsx b/config/ags/notifications/handler.tsx
new file mode 100644
index 0000000..ee2ad42
--- /dev/null
+++ b/config/ags/notifications/handler.tsx
@@ -0,0 +1,184 @@
+/*
+* dotfiles - handler.ts
+*
+* Created by Janis Hutz 03/21/2025, Licensed under the GPL V3 License
+* https://janishutz.com, development@janishutz.com
+*
+*
+*/
+
+import { Astal, Gtk, Gdk } from "astal/gtk3"
+import Notifd from "gi://AstalNotifd";
+import Notification from "./notifications/notifications";
+import { type Subscribable } from "astal/binding";
+import { Variable, bind, timeout } from "astal"
+
+// Config
+const TIMEOUT_DELAY = 5000;
+
+class Notifier implements Subscribable {
+ private display: Map = new Map();
+ private notifications: Map = new Map();
+
+ private notifd: Notifd.Notifd;
+ private subscriberData: Variable = Variable( [] );
+ private instanceID: number;
+ private menuOpen: boolean;
+
+ /**
+ * Sets up the notifier
+ */
+ constructor( id: number ) {
+ this.instanceID = id;
+ this.menuOpen = false;
+ this.notifd = Notifd.get_default();
+ this.notifd.ignoreTimeout = true;
+
+ this.notifd.connect( 'notified', ( _, id ) => {
+ this.add( id );
+ } );
+
+ this.notifd.connect( 'resolved', ( _, id ) => {
+ this.hide( id );
+ } );
+ }
+
+ private notify () {
+ this.subscriberData.set( [ ...this.display.values() ].reverse() );
+ }
+
+ private add ( id: number ) {
+ this.notifications.set( id, this.notifd.get_notification( id )! );
+ this.show( id );
+ }
+
+ /**
+ * Show an element on screen
+ * @param id - The id of the element to be shown
+ */
+ private show ( id: number ) {
+ this.set( id, Notification( {
+ notification: this.notifications.get( id )!,
+ onHoverLost: () => this.hide( id ),
+ setup: () => timeout( TIMEOUT_DELAY, () => {
+ if ( !this.menuOpen ) {
+ this.hide( id );
+ }
+ } ),
+ id: id,
+ delete: deleteHelper,
+ instanceID: this.instanceID
+ } ) )
+ }
+
+ /**
+ * Set a selected widget to be shown
+ * @param id - The id of the element to be referenced for later
+ * @param widget - A GTK widget instance
+ */
+ private set ( id: number, widget: Gtk.Widget ) {
+ this.display.get( id )?.destroy();
+ this.display.set( id, widget );
+ this.notify();
+ }
+
+ /**
+ * Hide, not delete notification (= send to notification centre)
+ * @param id - The id of the notification to hide
+ */
+ private hide ( id: number ) {
+ this.display.get( id )?.destroy();
+ this.display.delete( id );
+ this.notify();
+ }
+
+ /**
+ * Delete a notification (from notification centre too)
+ * @param id - The id of the notification to hide
+ */
+ delete ( id: number ) {
+ this.hide( id );
+ this.notifications.get( id )?.dismiss();
+ this.notifications.delete( id );
+ }
+
+ openNotificationMenu () {
+ // Show all notifications that have not been cleared
+ this.menuOpen = true;
+ this.notifications.forEach( ( _, id ) => {
+ this.show( id );
+ } )
+ }
+
+ hideNotifications () {
+ this.menuOpen = false;
+ this.notifications.forEach( ( _, id ) => {
+ this.hide( id );
+ } )
+ }
+
+ clearAllNotifications () {
+ this.menuOpen = false;
+ this.notifications.forEach( ( _, id ) => {
+ this.delete( id );
+ } )
+ }
+
+ clearNewestNotification () {
+ this.delete( [ ...this.notifications.keys() ][0] );
+ }
+
+ subscribe(callback: (value: unknown) => void): () => void {
+ return this.subscriberData.subscribe( callback );
+ }
+
+ get() {
+ return this.subscriberData.get();
+ }
+}
+
+const notifiers: Map = new Map();
+const deleteHelper = ( id: number, instanceID: number ) => {
+ notifiers.get( instanceID )?.delete( id );
+}
+
+const openNotificationMenu = ( id: number ) => {
+ notifiers.get( id )?.openNotificationMenu();
+}
+
+const closeNotificationMenu = ( id: number ) => {
+ notifiers.get( id )?.hideNotifications();
+}
+
+const clearAllNotifications = ( id: number ) => {
+ notifiers.get( id )?.clearAllNotifications();
+}
+
+const clearNewestNotifications = ( id: number ) => {
+ notifiers.get( id )?.clearNewestNotification();
+}
+
+const startNotificationHandler = (id: number, gdkmonitor: Gdk.Monitor) => {
+ const { TOP, RIGHT } = Astal.WindowAnchor
+ const notifier: Notifier = new Notifier( id );
+ notifiers.set( id, notifier );
+
+ return
+
+ {bind(notifier)}
+
+
+}
+
+
+export default {
+ startNotificationHandler,
+ openNotificationMenu,
+ closeNotificationMenu,
+ clearAllNotifications,
+ clearNewestNotifications
+}
diff --git a/config/ags/notifications/notifications/notifications.scss b/config/ags/notifications/notifications/notifications.scss
new file mode 100644
index 0000000..a32f08b
--- /dev/null
+++ b/config/ags/notifications/notifications/notifications.scss
@@ -0,0 +1,125 @@
+@use "sass:string";
+
+@function gtkalpha($c, $a) {
+ @return string.unquote("alpha(#{$c},#{$a})");
+}
+
+// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/theme/Adwaita/_colors-public.scss
+$fg-color: #{"@theme_fg_color"};
+$bg-color: #{"@theme_bg_color"};
+$error: red;
+
+window.NotificationPopups {
+ all: unset;
+}
+
+eventbox.Notification {
+
+ &:first-child>box {
+ margin-top: 1rem;
+ }
+
+ &:last-child>box {
+ margin-bottom: 1rem;
+ }
+
+ // eventboxes can not take margins so we style its inner box instead
+ >box {
+ min-width: 400px;
+ border-radius: 13px;
+ background-color: $bg-color;
+ margin: .5rem 1rem .5rem 1rem;
+ box-shadow: 2px 3px 8px 0 gtkalpha(black, .4);
+ border: 1pt solid gtkalpha($fg-color, .03);
+ }
+
+ &.critical>box {
+ border: 1pt solid gtkalpha($error, .4);
+
+ .header {
+
+ .app-name {
+ color: gtkalpha($error, .8);
+
+ }
+
+ .app-icon {
+ color: gtkalpha($error, .6);
+ }
+ }
+ }
+
+ .header {
+ padding: .5rem;
+ color: gtkalpha($fg-color, 0.5);
+
+ .app-icon {
+ margin: 0 .4rem;
+ }
+
+ .app-name {
+ margin-right: .3rem;
+ font-weight: bold;
+
+ &:first-child {
+ margin-left: .4rem;
+ }
+ }
+
+ .time {
+ margin: 0 .4rem;
+ }
+
+ button {
+ padding: .2rem;
+ min-width: 0;
+ min-height: 0;
+ }
+ }
+
+ separator {
+ margin: 0 .4rem;
+ background-color: gtkalpha($fg-color, .1);
+ }
+
+ .content {
+ margin: 1rem;
+ margin-top: .5rem;
+
+ .summary {
+ font-size: 1.2em;
+ color: $fg-color;
+ }
+
+ .body {
+ color: gtkalpha($fg-color, 0.8);
+ }
+
+ .image {
+ border: 1px solid gtkalpha($fg-color, .02);
+ margin-right: .5rem;
+ border-radius: 9px;
+ min-width: 100px;
+ min-height: 100px;
+ background-size: cover;
+ background-position: center;
+ }
+ }
+
+ .actions {
+ margin: 1rem;
+ margin-top: 0;
+
+ button {
+ margin: 0 .3rem;
+
+ &:first-child {
+ margin-left: 0;
+ }
+
+ &:last-child {
+ margin-right: 0;
+ }
+ }
+ }
+}
diff --git a/config/ags/notifications/notifications/notifications.tsx b/config/ags/notifications/notifications/notifications.tsx
new file mode 100644
index 0000000..de4e7b2
--- /dev/null
+++ b/config/ags/notifications/notifications/notifications.tsx
@@ -0,0 +1,112 @@
+// From astal examples
+
+import { GLib } from "astal"
+import { Gtk, Astal } from "astal/gtk3"
+import { type EventBox } from "astal/gtk3/widget"
+import Notifd from "gi://AstalNotifd"
+
+const isIcon = (icon: string) =>
+ !!Astal.Icon.lookup_icon(icon)
+
+const fileExists = (path: string) =>
+ GLib.file_test(path, GLib.FileTest.EXISTS)
+
+const time = (time: number, format = "%H:%M") => GLib.DateTime
+ .new_from_unix_local(time)
+ .format(format)!
+
+const urgency = (n: Notifd.Notification) => {
+ const { LOW, NORMAL, CRITICAL } = Notifd.Urgency
+ // match operator when?
+ switch (n.urgency) {
+ case LOW: return "low"
+ case CRITICAL: return "critical"
+ case NORMAL:
+ default: return "normal"
+ }
+}
+
+type Props = {
+ delete( id: number, instanceID: number ): void
+ setup(self: EventBox): void
+ onHoverLost(self: EventBox): void
+ notification: Notifd.Notification
+ id: number
+ instanceID: number
+}
+
+export default function Notification(props: Props) {
+ const { notification: n, onHoverLost, setup, id: id, delete: del, instanceID: instance } = props
+ const { START, CENTER, END } = Gtk.Align
+
+ return
+
+
+ {(n.appIcon || n.desktopEntry) && }
+
+
+
+
+
+
+ {n.image && fileExists(n.image) && }
+ {n.image && isIcon(n.image) &&
+
+ }
+
+
+ {n.body && }
+
+
+ {n.get_actions().length > 0 &&
+ {n.get_actions().map(({ label, id }) => (
+
+ ))}
+ }
+
+
+}
diff --git a/config/ags/notifications/package.json b/config/ags/notifications/package.json
new file mode 100644
index 0000000..44226f2
--- /dev/null
+++ b/config/ags/notifications/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "astal-shell",
+ "dependencies": {
+ "astal": "/usr/share/astal/gjs"
+ }
+}
diff --git a/config/ags/notifications/style.scss b/config/ags/notifications/style.scss
new file mode 100644
index 0000000..a1c9bb7
--- /dev/null
+++ b/config/ags/notifications/style.scss
@@ -0,0 +1,2 @@
+// Import notification box style
+@use "./notifications/notifications.scss"
diff --git a/config/ags/notifications/tsconfig.json b/config/ags/notifications/tsconfig.json
new file mode 100644
index 0000000..9471e35
--- /dev/null
+++ b/config/ags/notifications/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "experimentalDecorators": true,
+ "strict": true,
+ "target": "ES2022",
+ "module": "ES2022",
+ "moduleResolution": "Bundler",
+ // "checkJs": true,
+ // "allowJs": true,
+ "jsx": "react-jsx",
+ "jsxImportSource": "astal/gtk3",
+ }
+}
diff --git a/config/ags/quickactions/.gitignore b/config/ags/quickactions/.gitignore
new file mode 100644
index 0000000..298eb4d
--- /dev/null
+++ b/config/ags/quickactions/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+@girs/
diff --git a/config/ags/quickactions/app.ts b/config/ags/quickactions/app.ts
new file mode 100644
index 0000000..83217ef
--- /dev/null
+++ b/config/ags/quickactions/app.ts
@@ -0,0 +1,10 @@
+import { App } from "astal/gtk3"
+import style from "./style.scss"
+import Bar from "./widget/Bar"
+
+App.start({
+ css: style,
+ main() {
+ App.get_monitors().map(Bar)
+ },
+})
diff --git a/config/ags/quickactions/env.d.ts b/config/ags/quickactions/env.d.ts
new file mode 100644
index 0000000..467c0a4
--- /dev/null
+++ b/config/ags/quickactions/env.d.ts
@@ -0,0 +1,21 @@
+declare const SRC: string
+
+declare module "inline:*" {
+ const content: string
+ export default content
+}
+
+declare module "*.scss" {
+ const content: string
+ export default content
+}
+
+declare module "*.blp" {
+ const content: string
+ export default content
+}
+
+declare module "*.css" {
+ const content: string
+ export default content
+}
diff --git a/config/ags/quickactions/package.json b/config/ags/quickactions/package.json
new file mode 100644
index 0000000..44226f2
--- /dev/null
+++ b/config/ags/quickactions/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "astal-shell",
+ "dependencies": {
+ "astal": "/usr/share/astal/gjs"
+ }
+}
diff --git a/config/ags/quickactions/style.scss b/config/ags/quickactions/style.scss
new file mode 100644
index 0000000..1d0d3a9
--- /dev/null
+++ b/config/ags/quickactions/style.scss
@@ -0,0 +1,20 @@
+// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/theme/Adwaita/_colors-public.scss
+$fg-color: #{"@theme_fg_color"};
+$bg-color: #{"@theme_bg_color"};
+
+window.Bar {
+ background: transparent;
+ color: $fg-color;
+ font-weight: bold;
+
+ >centerbox {
+ background: $bg-color;
+ border-radius: 10px;
+ margin: 8px;
+ }
+
+ button {
+ border-radius: 8px;
+ margin: 2px;
+ }
+}
diff --git a/config/ags/quickactions/tsconfig.json b/config/ags/quickactions/tsconfig.json
new file mode 100644
index 0000000..9471e35
--- /dev/null
+++ b/config/ags/quickactions/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "experimentalDecorators": true,
+ "strict": true,
+ "target": "ES2022",
+ "module": "ES2022",
+ "moduleResolution": "Bundler",
+ // "checkJs": true,
+ // "allowJs": true,
+ "jsx": "react-jsx",
+ "jsxImportSource": "astal/gtk3",
+ }
+}
diff --git a/config/ags/quickactions/widget/Bar.tsx b/config/ags/quickactions/widget/Bar.tsx
new file mode 100644
index 0000000..0384535
--- /dev/null
+++ b/config/ags/quickactions/widget/Bar.tsx
@@ -0,0 +1,31 @@
+import { App, Astal, Gtk, Gdk } from "astal/gtk3"
+import { Variable } from "astal"
+
+const time = Variable("").poll(1000, "date")
+
+export default function Bar(gdkmonitor: Gdk.Monitor) {
+ const { TOP, LEFT, RIGHT } = Astal.WindowAnchor
+
+ return
+
+
+
+
+
+
+}