gpui: Add support for slash pattern fills (///) (#23576)

TODO:
- [x] Add BackgroundTag::PatternSlash
- [x] Support metal slash pattern fills
- [x] Support blade slash pattern fills
---

Adds support for a new background type in gpui, `pattern_slash`.

Usage:

```rust
div().size(px(56.0)).bg(pattern_slash(gpui::red()))
```
This will create a 56px square with a red slash pattern fill.

You can run the pattern example with `cargo run -p gpui --example
pattern`:

![CleanShot 2025-01-23 at 16 22
09@2x](https://github.com/user-attachments/assets/39d9f8c8-816c-4d3b-bc75-fcc122747e17)

---

After talking with @as-cii at length about how we want to support
patterns in gpui, we decided for now we'll simply add a new
BackgroundTag specific to this pattern.

It isn't the best long term plan however – we'll likely want to
introduce the concept of a `Fill` at some point so we can have
`Fill::Solid`, `Fill::Gradient(LinearGradient)`, etc in the future.

The pattern is designed to seamlessly tile vertically for elements of
the same height. For example, for use in editor line backgrounds:

![CleanShot 2025-01-23 at 16 27
41@2x](https://github.com/user-attachments/assets/d51b94bc-cfc2-4aff-89e3-289a04ea8841)

---


Release Notes:

(do we do gpui release notes?)
- Adds support for slash pattern fills in `gpui`.

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
Nate Butler 2025-01-28 11:33:34 -05:00 committed by GitHub
parent 070890d361
commit 23672987ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 183 additions and 24 deletions

View file

@ -0,0 +1,103 @@
use gpui::{
div, linear_color_stop, linear_gradient, pattern_slash, prelude::*, px, rgb, size, App,
AppContext, Bounds, ViewContext, WindowBounds, WindowOptions,
};
struct PatternExample;
impl Render for PatternExample {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
div()
.flex()
.flex_col()
.gap_3()
.bg(rgb(0xffffff))
.size(px(600.0))
.justify_center()
.items_center()
.shadow_lg()
.text_xl()
.text_color(rgb(0x000000))
.child("Pattern Example")
.child(
div()
.flex()
.flex_col()
.border_1()
.border_color(gpui::blue())
.child(div().w(px(54.0)).h(px(18.0)).bg(pattern_slash(gpui::red())))
.child(div().w(px(54.0)).h(px(18.0)).bg(pattern_slash(gpui::red())))
.child(div().w(px(54.0)).h(px(18.0)).bg(pattern_slash(gpui::red())))
.child(div().w(px(54.0)).h(px(18.0)).bg(pattern_slash(gpui::red()))),
)
.child(
div()
.flex()
.flex_col()
.border_1()
.border_color(gpui::blue())
.bg(gpui::green().opacity(0.16))
.child("Elements the same height should align")
.child(
div()
.w(px(256.0))
.h(px(56.0))
.bg(pattern_slash(gpui::red())),
)
.child(
div()
.w(px(256.0))
.h(px(56.0))
.bg(pattern_slash(gpui::green())),
)
.child(
div()
.w(px(256.0))
.h(px(56.0))
.bg(pattern_slash(gpui::blue())),
)
.child(
div()
.w(px(256.0))
.h(px(26.0))
.bg(pattern_slash(gpui::yellow())),
),
)
.child(
div()
.border_1()
.border_color(gpui::blue())
.w(px(240.0))
.h(px(40.0))
.bg(gpui::red()),
)
.child(
div()
.border_1()
.border_color(gpui::blue())
.w(px(240.0))
.h(px(40.0))
.bg(linear_gradient(
45.,
linear_color_stop(gpui::red(), 0.),
linear_color_stop(gpui::blue(), 1.),
)),
)
}
}
fn main() {
App::new().run(|cx: &mut AppContext| {
let bounds = Bounds::centered(None, size(px(600.0), px(600.0)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
|cx| cx.new_view(|_cx| PatternExample),
)
.unwrap();
cx.activate(true);
});
}