design-liquid: clear liquid glass with a light-catching edge

- clearer glass (0.4 by default), denser toward the bottom right where
  the equalizer labels and presets sit (fill alpha 0.55x / 1x / 1.6x)
- a white specular gradient: bright at the top left, a faint return at
  the bottom right; a 1.5 px light rim that warms to the theme's flame
  colour when hovered
- keeps the soft accent glow, as if the glass took the wallpaper's colour
- docs/design: board at glass 0.25 / 0.4 / 0.55, and the card at 0.4
This commit is contained in:
server2
2026-10-09 05:24:24 +02:00
parent 54ca75b855
commit ca884d0d31
4 changed files with 35 additions and 8 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

+1 -1
View File
@@ -10,4 +10,4 @@ transition_ms = 400
# how opaque the shell's surfaces are, 0.05 to 1 (1 = solid). below 1 the desktop shows
# through; to frost it, Hyprland has to blur behind the shell (README: Glass)
glass = 1.0
glass = 0.4
+34 -7
View File
@@ -1,28 +1,55 @@
use amane::{Blend, Color, Rectangle, Shadow};
use amane::{Blend, Color, Gradient, Rectangle, Shadow, Stack, children};
use crate::island::{backdrop, faded};
use crate::island::faded;
use crate::theme;
/*
* what the island, the idle pill and the workspace pill are made of: one place, so
* a design is this file. `shell` wraps `content` (already width x height, with its
* own alignment and padding) in the surface. `lift` (0 to 1) is how hovered it is.
* the default: the gradient of `colors`, a 1 px rim, a soft glow in the accent
*
* design: liquid glass. clear glass (0.4 by default) over what Hyprland blurs behind
* the shell, denser toward the bottom right where the equalizer's labels sit; a bright
* edge where light enters at the top left and leaves at the bottom right; and a soft
* accent glow, as if the glass took on the wallpaper's colour. hovered, it glows more
*/
pub fn shell(width: f32, height: f32, radius: f32, colors: &[Color; 3], lift: f32, content: Rectangle) -> Rectangle {
let theme = theme::now();
let glass = theme::glass();
// clearer at the top left, where nothing needs reading, denser at the bottom right
let fill = Gradient::linear(
150.0,
[
(0.0, faded(colors[0], alpha(glass * 0.55))),
(0.55, faded(colors[1], alpha(glass))),
(1.0, faded(colors[2], alpha(glass * 1.6))),
],
);
// the light catching the edges: strong at the top left, a faint return at the bottom right
let light = Rectangle::new()
.width(width - 2.0)
.height(height - 2.0)
.radius((radius - 1.0).max(0.0))
.fill(Gradient::linear(135.0, [(0.0, white(60)), (0.16, white(14)), (0.4, white(0)), (0.82, white(0)), (1.0, white(26))]))
.translate(1.0, 1.0);
Rectangle::new()
.width(width)
.height(height)
.radius(radius)
.fill(backdrop(colors, alpha(theme::glass())))
.border(1.0, Color::blend(theme.outline, faded(theme.accent, 110), lift))
.shadow(Shadow::drop(theme.accent).opacity(0.3 + 0.4 * lift).blur(22.0))
.child(content)
.fill(fill)
.border(1.5, Color::blend(white(84), faded(theme.flame, 200), lift))
.shadow(Shadow::drop(theme.accent).opacity(0.22 + 0.3 * lift).blur(24.0))
.child(Stack::new(children![light, content]).width(width).height(height))
}
// an opacity, 0 to 1, as a colour's alpha
pub fn alpha(opacity: f32) -> u8 {
(opacity.clamp(0.0, 1.0) * 255.0).round() as u8
}
fn white(alpha: u8) -> Color {
Color::rgba(255, 255, 255, alpha)
}