summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/guide/getting-started/introduction.md12
-rw-r--r--docs/guide/typescript/cli-app.md6
-rw-r--r--docs/guide/typescript/first-widgets.md24
-rw-r--r--docs/guide/typescript/theming.md15
-rw-r--r--docs/guide/typescript/widget.md379
5 files changed, 405 insertions, 31 deletions
diff --git a/docs/guide/getting-started/introduction.md b/docs/guide/getting-started/introduction.md
index 782c069..43a7bd8 100644
--- a/docs/guide/getting-started/introduction.md
+++ b/docs/guide/getting-started/introduction.md
@@ -2,13 +2,15 @@
## What is Astal?
-Astal (_meaning "desk"_) is a suite of libraries in Vala and C.
+Astal (_meaning "desk"_) is a suite of libraries written in Vala and C.
The core library [astal3](https://aylur.github.io/libastal/astal3) and
-[astal4](https://aylur.github.io/libastal/astal4) (not yet available)
-has some Gtk widgets that come packaged,
+[astal4](https://aylur.github.io/libastal/astal4)
+have some Gtk widgets that come packaged,
the most important one being the [Window](https://aylur.github.io/libastal/astal3/class.Window.html) which is the main toplevel component using [gtk-layer-shell](https://github.com/wmww/gtk-layer-shell).
This is what allows us to use Gtk as shell components on Wayland.
-The other part of the core library [astal-io](https://aylur.github.io/libastal/astal-io)
+The other component is [Application](https://aylur.github.io/libastal/astal3/class.Application.html)
+which provides a way to send messages from the cli to running Astal instances.
+The other part of the core library is [astal-io](https://aylur.github.io/libastal/astal-io)
which contains some utility GLib shortcut for running external processes,
reading, writing and monitoring files, timeout and interval functions.
@@ -23,4 +25,4 @@ or an applauncher, but gave up because writing a workspace widget,
implementing the notification daemon or handling a search filter was too much of a hassle?
Astal libraries have you [covered](../libraries/references#astal-libraries), you don't have to worry about these,
-you just define the layout, style it with CSS and that's it.
+you just define the layout, style with CSS hook up the state from libraries you want and that's it.
diff --git a/docs/guide/typescript/cli-app.md b/docs/guide/typescript/cli-app.md
index 9b299aa..41b1d7c 100644
--- a/docs/guide/typescript/cli-app.md
+++ b/docs/guide/typescript/cli-app.md
@@ -26,7 +26,7 @@ App.start({
## Instance identifier
-You can run multiple instance by defining a unique instance name.
+You can run multiple instances by defining a unique instance name.
```ts
App.start({
@@ -44,7 +44,7 @@ you can do so by sending a message.
App.start({
requestHandler(request: string, res: (response: any) => void) {
if (request == "say hi") {
- res("hi cli")
+ return res("hi cli")
}
res("unknown command")
},
@@ -140,7 +140,7 @@ App.start({
// every subsequent calls
client(message: (msg: string) => string, ...args: Array<string>) {
const res = message("you can message the main instance")
- console.log(res)
+ print(res)
},
// this runs in the main instance
diff --git a/docs/guide/typescript/first-widgets.md b/docs/guide/typescript/first-widgets.md
index 77b2f61..9b8bf32 100644
--- a/docs/guide/typescript/first-widgets.md
+++ b/docs/guide/typescript/first-widgets.md
@@ -71,7 +71,7 @@ function MyButton(): JSX.Element {
}
```
-```ts [MyButton.ts]
+```ts [MyButton.ts (gtk3)]
import { Widget } from "astal/gtk3"
function MyButton(): Widget.Button {
@@ -82,6 +82,17 @@ function MyButton(): Widget.Button {
}
```
+```ts [MyButton.ts (gtk4)]
+import { Widget } from "astal/gtk4"
+
+function MyButton(): Widget.Button {
+ return Widget.Button(
+ { onClicked: "echo hello" },
+ Widget.Label({ label: "Click me!" }),
+ )
+}
+```
+
:::
:::info
@@ -218,6 +229,14 @@ Their types are not generated, but written by hand, which means not all of them
Refer to the Gtk and Astal docs to have a full list of them.
:::
+:::info
+Attributes prefixed with `onNotify` will connect to a `notify::` signal of the widget.
+
+```tsx
+<switch onNotifyActive={self => print("switched to", self.active)}>
+```
+:::
+
## How properties are passed
Using JSX, a custom widget will always have a single object as its parameter.
@@ -413,8 +432,7 @@ function Parent(props: {
:::tip
If you have a widget where you pass widgets in various ways, you can
-wrap `child` in `children` in a [`Subscribable`](./faq#custom-widgets-with-bindable-properties) and handle all cases
-as if they were bindings.
+wrap `child` and `children` props in a [`Subscribable`](./faq#custom-widgets-with-bindable-properties) and handle all cases as if they were bindings.
:::
:::info
diff --git a/docs/guide/typescript/theming.md b/docs/guide/typescript/theming.md
index 5944c4e..3cafa7d 100644
--- a/docs/guide/typescript/theming.md
+++ b/docs/guide/typescript/theming.md
@@ -1,24 +1,25 @@
# Theming
-Since the widget toolkit is **GTK3** theming is done with **CSS**.
+Since the widget toolkit is **GTK** theming is done with **CSS**.
- [CSS tutorial](https://www.w3schools.com/css/)
-- [GTK CSS Overview wiki](https://docs.gtk.org/gtk3/css-overview.html)
-- [GTK CSS Properties Overview wiki](https://docs.gtk.org/gtk3/css-properties.html)
+- [GTK3 CSS Overview wiki](https://docs.gtk.org/gtk3/css-overview.html)
+- [GTK3 CSS Properties Overview wiki](https://docs.gtk.org/gtk3/css-properties.html)
+- [GTK4 CSS Overview wiki](https://docs.gtk.org/gtk4/css-overview.html)
+- [GTK4 CSS Properties Overview wiki](https://docs.gtk.org/gtk4/css-properties.html)
:::warning GTK is not the web
While most features are implemented in GTK,
you can't assume anything that works on the web will work with GTK.
-Refer to the [GTK docs](https://docs.gtk.org/gtk3/css-overview.html)
-to see what is available.
+Refer to the GTK docs to see what is available.
:::
-So far every widget you made used your default GTK3 theme.
+So far every widget you made used your default GTK theme.
To make them more custom, you can apply stylesheets to them.
## From file at startup
-You can pass a path to a file or css as a string in `App.start`
+You can pass a path to a file or CSS as a string in `App.start`
:::code-group
diff --git a/docs/guide/typescript/widget.md b/docs/guide/typescript/widget.md
index 7ed69e3..43c8721 100644
--- a/docs/guide/typescript/widget.md
+++ b/docs/guide/typescript/widget.md
@@ -6,15 +6,21 @@
These are properties that Astal additionally adds to Gtk.Widgets
-- className: `string` - List of class CSS selectors separated by white space.
-- css: `string` - Inline CSS. e.g `label { color: white; }`. If no selector is specified `*` will be assumed. e.g `color: white;` will be inferred as `* { color: white; }`.
-- cursor: `string` - Cursor style when hovering over widgets that have hover states, e.g it won't work on labels. [list of valid values](https://docs.gtk.org/gdk3/ctor.Cursor.new_from_name.html).
-- clickThrough: `boolean` - Lets click events through.
+- `className`: `string` - List of class CSS selectors separated by white space.
+- `css`: `string` - Inline CSS. e.g `label { color: white; }`. If no selector is specified `*` will be assumed. e.g `color: white;` will be inferred as `* { color: white; }`.
+- `cursor`: `string` - Cursor style when hovering over widgets that have hover states, e.g it won't work on labels. [list of valid values](https://docs.gtk.org/gdk3/ctor.Cursor.new_from_name.html).
+- `clickThrough`: `boolean` - Lets click events through.
To have a full list of available properties, reference the documentation of the widget.
- [Astal3 widgets](https://aylur.github.io/libastal/astal3/index.html#classes)
-- [Gtk widgets](https://docs.gtk.org/gtk3/#classes)
+- [Gtk3 widgets](https://docs.gtk.org/gtk3/#classes)
+
+Most common ones you will use frequently are
+ - [halign](https://docs.gtk.org/gtk3/property.Widget.halign.html)
+ - [valign](https://docs.gtk.org/gtk3/property.Widget.valign.html)
+ - [hexpand](https://docs.gtk.org/gtk3/property.Widget.hexpand.html)
+ - [vexpand](https://docs.gtk.org/gtk3/property.Widget.vexpand.html)
### Additional widget methods
@@ -27,7 +33,7 @@ without `setup`
```tsx
function MyWidget() {
- const button = Widget.Button()
+ const button = new Widget.Button()
// setup button
return button
}
@@ -94,14 +100,14 @@ function MyWidget() {
### How to use non builtin Gtk widgets
-Using the `Widget.astalify` mixin you can subclass widgets
+Using the `astalify` mixin you can subclass widgets
to behave like builtin widgets.
The `astalify` mixin will apply the following:
- set `visible` to true by default (Gtk3 widgets are invisible by default)
- make gobject properties accept and consume `Binding` objects
- add properties and methods listed above
-- sets up signal handlers that are passed as props prefixed with `on`
+- set up signal handlers that are passed as props prefixed with `on`
```tsx
import GObject from "gi://GObject"
@@ -135,7 +141,7 @@ function MyWidget() {
alpha: 0.5,
})}
onColorSet={(self) => {
- console.log(self.rgba)
+ print(self.rgba)
}}
/>
}
@@ -144,7 +150,7 @@ function MyWidget() {
:::info
Signal properties have to be annotated manually for TypeScript.
You can reference [Gtk3](https://gjs-docs.gnome.org/gtk30~3.0/)
-and [Astal](https://aylur.github.io/libastal/index.html#classes) for available signals.
+and [Astal3](https://aylur.github.io/libastal/astal3/#classes) for available signals.
:::
### TypeScript
@@ -189,28 +195,375 @@ export default function ToggleButton(btnprops: ToggleButtonProps) {
### Builtin Widgets
-You can check the [source code](https://github.com/aylur/astal/blob/main/lang/gjs/src/gtk3/index.ts) to have a full list of builtin widgets.
-
These widgets are available by default in JSX.
- box: [Astal.Box](https://aylur.github.io/libastal/astal3/class.Box.html)
+ ```tsx
+ <box>Horizontal Box</box>
+ ```
+ ```tsx
+ <box orientation={1}>Vertical Box</box>
+ ```
- button: [Astal.Button](https://aylur.github.io/libastal/astal3/class.Button.html)
+ ```tsx
+ <button onClicked={self => print(self, "was clicked")}>
+ Click Me
+ </button>
+ ```
- centerbox: [Astal.CenterBox](https://aylur.github.io/libastal/astal3/class.CenterBox.html)
+ ```tsx
+ <centerbox orientation={1}>
+ <label vexpand valign={Gtk.Align.START} label="Start Widget" />
+ <label label="Center Widget" />
+ <label vexpand valign={Gtk.Align.END} label="End Widget" />
+ </box>
+ ```
- circularprogress: [Astal.CircularProgress](https://aylur.github.io/libastal/astal3/class.CircularProgress.html)
+ ```tsx
+ <circularprogress value={.5} startAt={0.75} endAt={0.75}>
+ <icon />
+ </circularprogress>
+ ```
+ ```css
+ circularprogress {
+ color: green;
+ background-color: black;
+ font-size: 6px;
+ margin: 2px;
+ min-width: 32px;
+ }
+ ```
+
- drawingarea: [Gtk.DrawingArea](https://docs.gtk.org/gtk3/class.DrawingArea.html)
+ ```tsx
+ <drawingarea onDraw={drawingFunction} />
+ ```
+
- entry: [Gtk.Entry](https://docs.gtk.org/gtk3/class.Entry.html)
+ ```tsx
+ <window keymode={Astal.Keymode.ON_DEMAND}>
+ <entry
+ onChanged={self => print("text changed", self.text)}
+ onActivate={self => print("enter", self.text)}
+ />
+ </window>
+ ```
+
- eventbox: [Astal.EventBox](https://aylur.github.io/libastal/astal3/class.EventBox.html)
+ ```tsx
+ <eventbox
+ onClick={(_, event) => {
+ print(event.modifier, event.button)
+ }}
+ />
+ ```
+
- icon: [Astal.Icon](https://aylur.github.io/libastal/astal3/class.Icon.html)
+ ```tsx
+ <icon icon={GLib.get_os_info("LOGO") || "missing-symbolic"} />
+ ```
+ ```css
+ icon {
+ font-size: 16px;
+ }
+ ```
+
- label: [Astal.Label](https://aylur.github.io/libastal/astal3/class.Label.html)
+ ```tsx
+ <label label="hello" maxWidthChars={16} wrap />
+ ```
+
- levelbar: [Astal.LevelBar](https://aylur.github.io/libastal/astal3/class.LevelBar.html)
+ ```tsx
+ <levelbar value={0.5} widthRequest={200} />
+ ```
+
- overlay: [Astal.Overlay](https://aylur.github.io/libastal/astal3/class.Overlay.html)
+ ```tsx
+ <overlay>
+ <box heightRequest={40} widthRequest={40}>Child</box>
+ <box className="overlay" valign={Gtk.Align.START} halign={Gtk.Align.END}>1</box>
+ </overlay>
+ ```
+
- revealer: [Gtk.Revealer](https://docs.gtk.org/gtk3/class.Revealer.html)
+ ```tsx
+ <revealer
+ setup={self => timeout(500, () => self.revealChild = true)}
+ transitionType={Gtk.RevealerTransitionType.SLIDE_UP}>
+ <label label="Child" />
+ </revealer>
+ ```
+
- scrollable: [Astal.Scrollable](https://aylur.github.io/libastal/astal3/class.Scrollable.html)
+ ```tsx
+ <scrollable heightRequest={100}>
+ <box orientation={1}>
+ {Array.from({ length: 10 }, (_, i) => (
+ <button>{i}</button>
+ ))}
+ </box>
+ </scrollable>
+ ```
+
- slider: [Astal.Slider](https://aylur.github.io/libastal/astal3/class.Slider.html)
+ ```tsx
+ <slider widthRequest={100} onDragged={self => print("new value", self.value)} />
+ ```
+
- stack: [Astal.Stack](https://aylur.github.io/libastal/astal3/class.Stack.html)
+ ```tsx
+ <stack visibleChildName="child2">
+ <label name="child1" label="child1" />
+ <label name="child2" label="child2" />
+ </stack>
+ ```
+
- switch: [Gtk.Switch](https://docs.gtk.org/gtk3/class.Switch.html)
+ ```tsx
+ <switch onNotifyActive={self => print(self.active)} />
+ ```
+
- window: [Astal.Window](https://aylur.github.io/libastal/astal3/class.Window.html)
+ ```tsx
+ <window
+ className="Bar"
+ name="bar"
+ namespace="bar"
+ application={App}
+ monitor={0}
+ anchor={Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT}
+ exclusivity={Astal.Exclusivity.EXCLUSIVE}
+ keymode={Astal.Keymode.ON_DEMAND}
+ >
+ <centerbox />
+ </window>
+ ```
## Gtk4
-🚧 Work in Progress 🚧
+The Gtk4 js library does not add any additional properties to the widgets,
+but it still has some additional properties that the constructors handle.
+
+- `type`: `string` an arbitrary string that the [Buildable](https://docs.gtk.org/gtk4/iface.Buildable.html) interface uses.
+- event handlers for [EventControllers](https://docs.gtk.org/gtk4/class.EventController.html)
+ ```ts
+ type EventController<Self extends Gtk.Widget> = {
+ onFocusEnter?: (self: Self) => void
+ onFocusLeave?: (self: Self) => void
+
+ onKeyPressed?: (self: Self, keyval: number, keycode: number, state: Gdk.ModifierType) => void
+ onKeyReleased?: (self: Self, keyval: number, keycode: number, state: Gdk.ModifierType) => void
+ onKeyModifier?: (self: Self, state: Gdk.ModifierType) => void
+
+ onLegacy?: (self: Self, event: Gdk.Event) => void
+ onButtonPressed?: (self: Self, state: Gdk.ButtonEvent) => void
+ onButtonReleased?: (self: Self, state: Gdk.ButtonEvent) => void
+
+ onHoverEnter?: (self: Self, x: number, y: number) => void
+ onHoverLeave?: (self: Self) => void
+ onMotion?: (self: Self, x: number, y: number) => void
+
+ onScroll?: (self: Self, dx: number, dy: number) => void
+ onScrollDecelerate?: (self: Self, vel_x: number, vel_y: number) => void
+ }
+ ```
+
+- `setup`: `(self): void` setup function that runs after constructor
+ ```tsx
+ // without `setup`
+ function MyWidget() {
+ const button = Widget.Button()
+ // setup button
+ return button
+ }
+
+ // using `setup`
+ function MyWidget() {
+ function setup(button: Widget.Button) {
+ // setup button
+ }
+
+ return <buttons setup={setup} />
+ }
+ ```
+
+There is also a `hook` utility
+
+```tsx
+// without `hook`
+function MyWidget() {
+ const id = gobject.connect("signal", callback)
+ const unsub = variable.subscribe(callback)
+
+ return <box
+ onDestroy={() => {
+ gobject.disconnect(id)
+ unsub()
+ }}
+ />
+}
+
+// with `hook`
+function MyWidget() {
+ return <box
+ setup={(self) => {
+ self.hook(gobject, "signal", callback)
+ self.hook(variable, callback)
+ }}
+ />
+}
+```
+
+### How to use non builtin Gtk widgets
+
+Using the `astalify` function you can create wrappers around widget constructors
+to make them behave like builtin widgets.
+The `astalify` function will do the followings:
+
+- make `gobject` properties accept and consume `Binding` objects
+- handle properties listed above
+- set up signal handlers that are passed as props prefixed with `on`
+
+```tsx
+import GObject from "gi://GObject"
+import { Gtk, astalify, type ConstructProps } from "astal/gtk4"
+
+type CalendarProps = ConstructProps<Gtk.Calendar, Gtk.Calendar.ConstructorProps>
+const Calendar = astalify<Gtk.Calendar, Gtk.Calendar.ConstructorProps>(Gtk.Calendar, {
+ // if it is a container widget, define children setter and getter here
+ getChildren(self) { return [] },
+ setChildren(self, children) {},
+})
+
+function MyWidget() {
+ function setup(button: Gtk.Calendar) {
+
+ }
+
+ return <Calendar
+ setup={setup}
+ onDaySelected={(self) => {
+ print(self.day)
+ }}
+ />
+}
+```
+
+### Builtin Widgets
+
+These widgets are available by default in JSX.
+
+- box: [Astal.Box](https://aylur.github.io/libastal/astal4/class.Box.html)
+ ```tsx
+ <box>Horizontal Box</box>
+ ```
+ ```tsx
+ <box orientation={1}>Vertical Box</box>
+ ```
+- button: [Gtk.Button](https://docs.gtk.org/gtk4/class.Button.html)
+ ```tsx
+ <button onClicked={self => print(self, "was clicked")}>
+ Click Me
+ </button>
+ ```
+- centerbox: [Gtk.CenterBox](https://docs.gtk.org/gtk4/class.CenterBox.html)
+ ```tsx
+ <centerbox orientation={1}>
+ <label label="Start Widget" />
+ <label label="Center Widget" />
+ <label label="End Widget" />
+ </box>
+ ```
+- entry: [Gtk.Entry](https://docs.gtk.org/gtk4/class.Entry.html)
+ ```tsx
+ <window keymode={Astal.Keymode.ON_DEMAND}>
+ <entry
+ onNotifyText={self => print("text changed", self.text)}
+ onActivate={self => print("enter", self.text)}
+ />
+ </window>
+ ```
+
+- image: [Gtk.Image](https://docs.gtk.org/gtk4/class.Image.html)
+ ```tsx
+ <image iconName={GLib.get_os_info("LOGO") || "missing-symbolic"} />
+ ```
+ ```css
+ image {
+ -gtk-icon-size: 16px;
+ }
+ ```
+
+- label: [Gtk.Label](https://docs.gtk.org/gtk4/class.Label.html)
+ ```tsx
+ <label label="hello" maxWidthChars={16} wrap />
+ ```
+
+- levelbar: [Gtk.LevelBar](https://docs.gtk.org/gtk4/class.LevelBar.html)
+ ```tsx
+ <levelbar value={0.5} widthRequest={200} />
+ ```
+
+- overlay: [Gtk.Overlay](https://docs.gtk.org/gtk4/class.Overlay.html)
+ ```tsx
+ <overlay>
+ <box heightRequest={40} widthRequest={40}>Child</box>
+ <box type="overlay measure" >1</box>
+ <box type="overlay clip" >2</box>
+ <box type="overlay clip measure" >3</box>
+ </overlay>
+ ```
+
+- revealer: [Gtk.Revealer](https://docs.gtk.org/gtk4/class.Revealer.html)
+ ```tsx
+ <revealer
+ setup={self => timeout(500, () => self.revealChild = true)}
+ transitionType={Gtk.RevealerTransitionType.SLIDE_UP}>
+ <label label="Child" />
+ </revealer>
+ ```
+
+- slider: [Astal.Slider](https://aylur.github.io/libastal/astal4/class.Slider.html)
+ ```tsx
+ <slider widthRequest={100} onNotifyValue={self => print("new value", self.value)} />
+ ```
+
+- stack: [Gtk.Stack](https://docs.gtk.org/gtk4/class.Stack.html)
+ ```tsx
+ <stack visibleChildName="child2">
+ <label name="child1" label="child1" />
+ <label name="child2" label="child2" />
+ </stack>
+ ```
+
+- switch: [Gtk.Switch](https://docs.gtk.org/gtk4/class.Switch.html)
+ ```tsx
+ <switch onNotifyActive={self => print(self.active)} />
+ ```
+
+- menubutton: [Gtk.MenuButton](https://docs.gtk.org/gtk4/class.MenuButton.html) and popover: [Gtk.Popover](https://docs.gtk.org/gtk4/class.Popover.html)
+ ```tsx
+ <menubutton>
+ <label label="Button Content" />
+ <popover>
+ <label label="Popover Content" />
+ </popover>
+ </menubutton>
+ ```
+
+- window: [Astal.Window](https://aylur.github.io/libastal/astal4/class.Window.html)
+ ```tsx
+ <window
+ className="Bar"
+ name="bar"
+ namespace="bar"
+ application={App}
+ monitor={0}
+ anchor={Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT}
+ exclusivity={Astal.Exclusivity.EXCLUSIVE}
+ keymode={Astal.Keymode.ON_DEMAND}
+ >
+ <centerbox />
+ </window>
+ ```