zebar
zebar copied to clipboard
Zebar is a tool for creating customizable and cross-platform taskbars, desktop widgets, and popups.
Zebar
Zebar lets you create customizable and cross-platform taskbars, desktop widgets, and popups.
🔧 Development & how to contribute
Readme contents
- Installation
- Migration from GlazeWM bar
-
Intro to Zebar
- Styled with HTML + CSS
- Reactive "providers"
- Templating language
- Providers
⚙️ Installation
Downloads for Windows, MacOS, and Linux are available in the latest release.
A default start script can also be downloaded from the release. Run the script after install to launch the default bar, which will create a config file located at %userprofile%/.glzr/zebar/config.yaml
.
➡️ Migration from GlazeWM bar
Modify the following GlazeWM config options (at %userprofile%/.glaze-wm/config.yaml
):
gaps:
# Add more spacing at the top.
outer_gap: '45px 20px 20px 20px'
bar:
# Disable the built-in GlazeWM bar.
enabled: false
window_rules:
# Ignore the bar window.
- command: 'ignore'
match_process_name: '/Zebar/'
➡️ Usage with Komorebi
Modify the float_rules
in the Komorebi config options (at %userprofile%/komorebi.json
).
{
"float_rules": [
{
"kind": "Exe",
"id": "Zebar.exe",
"matching_strategy": "Equals"
}
]
}
And in the Zebar config (if using the default generated one), replace the GlazeWM element with the following:
template/workspaces:
styles: |
display: flex;
align-items: center;
.workspace {
background: rgba(255, 255, 255, 0.05);
margin-right: 4px;
width: 30px;
height: 30px;
color: #ffffffe6;
border: none;
border-radius: 2px;
&.active {
background: rgba(255, 255, 255, 0.1);
}
}
providers: ['komorebi']
template: |
@for (workspace of komorebi.currentWorkspaces) {
<button class="workspace {{ workspace === komorebi.focusedWorkspace && 'active' }}">
{{ workspace.name }}
</button>
}
🌟 Intro to Zebar
There's 3 big differences that set Zebar apart from other similar projects:
- Styled with HTML + CSS
- Reactive "providers" for modifying the bar on the fly
- Templating language
Concept 1: Styled with HTML + CSS
The entire html + css of the bar can be customized via the user config. CSS/SCSS can be added to an element via the styles
property, and child divs can be created via template/<id>
and group/<id>
properties.
A basic config might look like this:
# Define a new window with an ID of 'example', which can then be launched
# by running 'zebar open example'.
window/example:
width: '200'
height: '200'
position_x: '0'
position_y: '0'
styles: |
background: lightgreen;
height: 100%;
width: 100%;
# Add a child div for showing CPU usage. It uses the CPU provider to
# get a variable for the current usage (more on that below).
template/cpu:
providers: ['cpu']
template: |
<p>{{ cpu.usage }}</p>
Running zebar open example
in a terminal will create an instance of this window config. It'll launch a 200x200 window in the corner of the screen where the CPU changes over time.
The resulting window and underlying HTML from the above config.
group/<id>
properties are used to add a child div, whereas template/<id>
properties are used to add a child div that can have a custom HTML template. group/<id>
properties can be nested infinitely, whereas template/<id>
properties cannot be nested. The order of these config properties matters as can be seen from the resulting HTML (pic 3).
window/example:
width: '200'
height: '200'
position_x: '0'
position_y: '0'
group/nested1:
group/nested2:
group/nested3:
template/my_template1:
template: |
<span>The mitochondria is the powerhouse of the cell</span>
<img src="https://google.com/mitochondria.jpg">
template/my_template2:
template: |
<span>Another template</span>
The resulting HTML from the above config.
Concept 2: Reactive "providers"
Rather than having predefined components (eg. a cpu component, battery component, etc), Zebar instead introduces providers. Providers are a collection of functions and/or variables that can change over time. When a variable changes, it'll cause a reactive change wherever it is used in the config.
window/example:
providers: ['cpu', 'memory']
width: '200'
height: '200'
# Set position of the window to be based off current memory/cpu usage. We
# need to round the values since `position_x` and `position_y` only accept
# whole numbers.
position_x: '{{ Math.round(cpu.usage) }}'
position_y: '{{ Math.round(memory.usage) }}'
template/cpu_and_memory:
template: |
CPU usage: {{ cpu.usage }}
Memory usage: {{ memory.usage}}
The above will create a window that jumps around the screen whenever cpu and memory usage changes. All config properties are reactive to changes in providers.
Providers "trickle down", meaning that a provider declared on a parent element (eg. window/example
) will be available to any elements below (eg. template/cpu-and-memory
). So we don't have to repeat declaring a CPU provider if we need it in multiple places; instead move the provider to a parent element.
Providers can also optionally take some config options. For example, the CPU provider refreshes every 5 seconds by default but that can be changed by defining the providers as such:
window/example:
providers:
- type: 'cpu'
refresh_interval: 3000
- type: 'weather'
latitude: 51.509865
longitude: -0.118092
A full list of providers and their configs is available here.
Lastly, concept 3: Templating language
Zebar's templating language has support for interpolation tags, if-else statements, for-loops, and switch statements. Just like providers, the templating syntax can be used on any config property (this includes switch, if-else statements etc).
Interpolation tags
window/example:
providers: ['weather']
# Window is only resizable when there is nice weather.
resizable: "{{ weather.status === 'sunny_day' }}"
Any arbitrary JavaScript is accepted within interpolation tags (eg. {{ Math.random() }}
). However, it'll only re-evaluated when a provider changes.
window/example:
template/weather:
providers: ['weather']
# Template will only change when weather temperature variable is updated.
template: |
<span>Random number: {{ Math.random() }}</span>
<span>Temperature: {{ weather.celsiusTemp }}</span>
If-else statements
window/example:
template/weather:
providers: ['weather']
styles: |
.hot {
color: red;
}
template: |
@if (weather.celsiusTemp > 30) {
<p class="hot">It's hot yo</p>
} @else if (weather.celsiusTemp > 20) {
<p>It's not that bad</p>
} @else {
<p>It's chilly here</p>
}
For-loops
window/example:
template/fruit:
template: |
@for (fruit of ['apple', 'orange', 'pineapple']) {
<span>{{ fruit }}</span>
}
Switch statements
window/example:
template/weather:
providers: ['weather']
template: |
@switch (weather.status) {
@case ('clear_day') {<i class="nf nf-weather-day_sunny"></i>}
@case ('cloudy_day') {<i class="nf nf-weather-day_cloudy"></i>}
@case ('snow_day') {<i class="nf nf-weather-day_snow"></i>}
@default {<i class="nf nf-weather-day_sunny"></i>}
}
🧩 Providers
- battery
- cpu
- date
- glazewm
- host
- ip
- memory
- monitors
- network
- self
- weather
Battery
Provider config
Option | Description | Option type | Default value |
---|---|---|---|
refresh_interval |
How often this provider refreshes in milliseconds. | number |
5000 |
Variables
Variable | Description | Return type | Supported OS |
---|---|---|---|
chargePercent |
Battery charge as a percentage of maximum capacity (aka. 'state of charge'). Returned value is between 0 to 100 . |
number |
|
healthPercent |
Condition of the battery as a percentage of perfect health. Returned value is between 0 to 100 . |
number |
|
cycleCount |
Number of charge/discharge cycles. | number |
|
state |
State of the battery. | 'discharging' | 'charging' | 'full' | 'empty' | 'unknown' |
|
isCharging |
Whether the battery is in a charging state. |
boolean |
|
timeTillEmpty |
Approximate time in milliseconds till battery is empty. | number | null |
|
timeTillFull |
Approximate time in milliseconds till battery is fully charged. | number | null |
|
powerConsumption |
Battery power consumption in watts. | number |
|
voltage |
Battery voltage. | number | null |
CPU
Provider config
Option | Description | Option type | Default value |
---|---|---|---|
refresh_interval |
How often this provider refreshes in milliseconds. | number |
5000 |
Variables
Variable | Description | Return type | Supported OS |
---|---|---|---|
frequency |
TODO | number |
|
usage |
TODO | number |
|
logicalCoreCount |
TODO | number |
|
physicalCoreCount |
TODO | number |
|
vendor |
TODO | string |
Date
Provider config
Option | Description | Option type | Default value |
---|---|---|---|
refresh_interval |
How often this provider refreshes in milliseconds. | number |
1000 |
Variables
Variable | Description | Return type | Supported OS |
---|---|---|---|
new |
Current date/time as a JavaScript Date object. Uses new Date() under the hood. |
Date |
|
now |
Current date/time as milliseconds since epoch. Uses Date.now() under the hood. |
number |
|
iso |
Current date/time as an ISO-8601 string (eg. 2017-04-22T20:47:05.335-04:00 ). Uses date.toISOString() under the hood. |
string |
Functions
Function | Description | Return type | Supported OS |
---|---|---|---|
toFormat |
Format a given date/time into a custom string format. Refer to table of tokens for available date/time tokens. Examples: - toFormat(now, 'yyyy LLL dd') -> 2023 Feb 13 - toFormat(now, "HH 'hours and' mm 'minutes'") -> 20 hours and 55 minutes Parameters: - now : number Date/time as milliseconds since epoch.- format : string Custom string format. |
string |
GlazeWM
Provider config
GlazeWM provider doesn't take any config options.
Variables
Variable | Description | Return type | Supported OS |
---|---|---|---|
workspacesOnMonitor |
TODO | Workspace[] |
Host
Provider config
Option | Description | Option type | Default value |
---|---|---|---|
refresh_interval |
How often this provider refreshes in milliseconds. | number |
60000 |
Variables
Variable | Description | Return type | Supported OS |
---|---|---|---|
hostname |
Name used to identify the device in various network-related activities. | string | null |
|
osName |
Name of the operating system. This is Darwin on MacOS, Windows on Windows, or the Linux distro name retrieved from either /etc/os-release or /etc/lsb-release (eg. Debian GNU/Linux on Debian). |
string | null |
|
osVersion |
Operating system version. This is the version number on MacOS (eg. 13.2.1 ), the major version + build number on Windows (eg. 11 22000 ), or the Linux distro version retrieved from either /etc/os-release or /etc/lsb-release (eg. 9 on Debian 9). |
string | null |
|
friendlyOsVersion |
Friendly name of operating system version (eg. MacOS 13.2.1 , Windows 10 Pro , Linux Debian GNU/Linux 9 ). |
string | null |
|
bootTime |
Time when the system booted since UNIX epoch in milliseconds (eg. 1699452379304 ). |
string |
|
uptime |
Time in milliseconds since boot. | string |
IP
Provider config
Option | Description | Option type | Default value |
---|---|---|---|
refresh_interval |
How often this provider refreshes in milliseconds. | number |
3600000 |
Variables
Variable | Description | Return type | Supported OS |
---|---|---|---|
address |
TODO | string |
|
approxCity |
TODO | string |
|
approxCountry |
TODO | string |
|
approxLatitude |
TODO | number |
|
approxLongitude |
TODO | number |
Memory
Provider config
Option | Description | Option type | Default value |
---|---|---|---|
refresh_interval |
How often this provider refreshes in milliseconds. | number |
5000 |
Variables
Variable | Description | Return type | Supported OS |
---|---|---|---|
usage |
TODO | number |
|
freeMemory |
TODO | number |
|
usedMemory |
TODO | number |
|
totalMemory |
TODO | number |
|
freeSwap |
TODO | number |
|
usedSwap |
TODO | number |
|
totalSwap |
TODO | number |
Monitors
Provider config
Monitors provider doesn't take any config options.
Variables
Variable | Description | Return type | Supported OS |
---|---|---|---|
primary |
TODO | MonitorInfo | undefined |
|
secondary |
TODO | MonitorInfo[] |
|
all |
TODO | MonitorInfo[] |
Network
Provider config
Option | Description | Option type | Default value |
---|---|---|---|
refresh_interval |
How often this provider refreshes in milliseconds. | number |
5000 |
Variables
Variable | Description | Return type | Supported OS |
---|---|---|---|
interfaces |
TODO | NetworkInterface[] |
Self
Provider config
Self provider doesn't take any config options.
Variables
Variable | Description | Return type | Supported OS |
---|---|---|---|
args |
Args used to open the window. | Record<string, string> |
|
env |
Environment variables when window was opened. | Record<string, string> |
|
providers |
Map of this element's providers and their variables. | Record<string, unknown> |
|
id |
ID of this element. | string |
|
type |
Type of this element. | ElementType |
|
rawConfig |
Unparsed config for this element. | unknown |
|
parsedConfig |
Parsed config for this element. | WindowConfig | GroupConfig | TemplateConfig |
|
globalConfig |
Global user config. | GlobalConfig |
Weather
Provider config
Option | Description | Option type | Default value |
---|---|---|---|
refresh_interval |
How often this provider refreshes in milliseconds. | number |
3600000 |
latitude |
Latitude to retrieve weather for. If not provided, latitude is instead estimated based on public IP. | number | undefined |
undefined |
longitude |
Longitude to retrieve weather for. If not provided, longitude is instead estimated based on public IP. | number | undefined |
undefined |
Variables
Variable | Description | Return type | Supported OS |
---|---|---|---|
address |
TODO | string |
|
approxCity |
TODO | string |
|
approxCountry |
TODO | string |
|
approxLatitude |
TODO | number |
|
approxLongitude |
TODO | number |