Compare commits

...

6 Commits

Author SHA1 Message Date
Nate Butler
e6f686adc7 Create shadow_REMOVE_BEFORE_MERGING.html 2024-12-21 10:13:52 -05:00
Nate Butler
5db2eb84a2 wip 2024-12-21 00:04:38 -05:00
Nate Butler
a2edbb71f9 Pass spread radius and offset to Shadow 2024-12-20 23:51:59 -05:00
Nate Butler
77c024bd1c Fix scrolling 2024-12-20 23:10:11 -05:00
Nate Butler
18fd51c5a1 WIP 2024-12-20 23:01:45 -05:00
Nate Butler
c7afd72e29 Update shadow example 2024-12-20 22:26:33 -05:00
6 changed files with 928 additions and 51 deletions

View File

@@ -1,25 +1,574 @@
use gpui::{
div, prelude::*, px, rgb, size, App, AppContext, Bounds, ViewContext, WindowBounds,
WindowOptions,
div, hsla, point, prelude::*, px, relative, rgb, size, App, AppContext, Bounds, BoxShadow, Div,
SharedString, ViewContext, WindowBounds, WindowOptions,
};
use smallvec::smallvec;
struct Shadow {}
impl Shadow {
fn base() -> Div {
div()
.size_16()
.bg(rgb(0xffffff))
.rounded_full()
.border_1()
.border_color(hsla(0.0, 0.0, 0.0, 0.1))
}
fn square() -> Div {
div()
.size_16()
.bg(rgb(0xffffff))
.border_1()
.border_color(hsla(0.0, 0.0, 0.0, 0.1))
}
fn rounded_small() -> Div {
div()
.size_16()
.bg(rgb(0xffffff))
.rounded(px(4.))
.border_1()
.border_color(hsla(0.0, 0.0, 0.0, 0.1))
}
fn rounded_medium() -> Div {
div()
.size_16()
.bg(rgb(0xffffff))
.rounded(px(8.))
.border_1()
.border_color(hsla(0.0, 0.0, 0.0, 0.1))
}
fn rounded_large() -> Div {
div()
.size_16()
.bg(rgb(0xffffff))
.rounded(px(12.))
.border_1()
.border_color(hsla(0.0, 0.0, 0.0, 0.1))
}
}
fn example(label: impl Into<SharedString>, example: impl IntoElement) -> impl IntoElement {
let label = label.into();
div()
.flex()
.flex_col()
.justify_center()
.items_center()
.w(relative(1. / 6.))
.border_r_1()
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
.child(
div()
.flex()
.items_center()
.justify_center()
.flex_1()
.py_12()
.child(example),
)
.child(
div()
.w_full()
.border_t_1()
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
.p_1()
.flex()
.items_center()
.child(label),
)
}
impl Render for Shadow {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
div()
.flex()
.id("shadow-example")
.overflow_y_scroll()
.bg(rgb(0xffffff))
.size_full()
.justify_center()
.items_center()
.child(div().size_8().shadow_sm())
.text_xs()
.child(div().flex().flex_col().w_full().children(vec![
div()
.border_b_1()
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
.flex()
.flex_row()
.children(vec![
example(
"Square",
Shadow::square()
.shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Rounded 4",
Shadow::rounded_small()
.shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Rounded 8",
Shadow::rounded_medium()
.shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Rounded 16",
Shadow::rounded_large()
.shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Circle",
Shadow::base()
.shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
]),
div()
.border_b_1()
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
.flex()
.w_full()
.children(vec![
example("None", Shadow::base()),
// Small shadow
example("Small", Shadow::base().shadow_sm()),
// Medium shadow
example("Medium", Shadow::base().shadow_md()),
// Large shadow
example("Large", Shadow::base().shadow_lg()),
example("Extra Large", Shadow::base().shadow_xl()),
example("2X Large", Shadow::base().shadow_2xl()),
]),
// Horizontal list of increasing blur radii
div()
.border_b_1()
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
.flex()
.children(vec![
example(
"Blur 0",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(0.),
spread_radius: px(0.),
}]),
),
example(
"Blur 2",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(2.),
spread_radius: px(0.),
}]),
),
example(
"Blur 4",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(4.),
spread_radius: px(0.),
}]),
),
example(
"Blur 8",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Blur 16",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(16.),
spread_radius: px(0.),
}]),
),
]),
// Horizontal list of increasing spread radii
div()
.border_b_1()
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
.flex()
.children(vec![
example(
"Spread 0",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Spread 2",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(2.),
}]),
),
example(
"Spread 4",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(4.),
}]),
),
example(
"Spread 8",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(8.),
}]),
),
example(
"Spread 16",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(16.),
}]),
),
]),
// Square spread examples
div()
.border_b_1()
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
.flex()
.children(vec![
example(
"Square Spread 0",
Shadow::square().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Square Spread 8",
Shadow::square().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(8.),
}]),
),
example(
"Square Spread 16",
Shadow::square().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(16.),
}]),
),
]),
// Rounded large spread examples
div()
.border_b_1()
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
.flex()
.children(vec![
example(
"Rounded Large Spread 0",
Shadow::rounded_large().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Rounded Large Spread 8",
Shadow::rounded_large().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(8.),
}]),
),
example(
"Rounded Large Spread 16",
Shadow::rounded_large().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.0, 0.0, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(16.),
}]),
),
]),
// Directional shadows
div()
.border_b_1()
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
.flex()
.children(vec![
example(
"Left",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(-8.), px(0.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Right",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(8.), px(0.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Top",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(0.), px(-8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Bottom",
Shadow::base().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
]),
// Square directional shadows
div()
.border_b_1()
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
.flex()
.children(vec![
example(
"Square Left",
Shadow::square().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(-8.), px(0.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Square Right",
Shadow::square().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(8.), px(0.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Square Top",
Shadow::square().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(0.), px(-8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Square Bottom",
Shadow::square().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
]),
// Rounded large directional shadows
div()
.border_b_1()
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
.flex()
.children(vec![
example(
"Rounded Large Left",
Shadow::rounded_large().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(-8.), px(0.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Rounded Large Right",
Shadow::rounded_large().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(8.), px(0.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Rounded Large Top",
Shadow::rounded_large().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(0.), px(-8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
example(
"Rounded Large Bottom",
Shadow::rounded_large().shadow(smallvec![BoxShadow {
color: hsla(0.0, 0.5, 0.5, 0.3),
offset: point(px(0.), px(8.)),
blur_radius: px(8.),
spread_radius: px(0.),
}]),
),
]),
// Multiple shadows for different shapes
div()
.border_b_1()
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
.flex()
.children(vec![
example(
"Circle Multiple",
Shadow::base().shadow(smallvec![
BoxShadow {
color: hsla(0.0 / 360., 1.0, 0.5, 0.3), // Red
offset: point(px(0.), px(-12.)),
blur_radius: px(8.),
spread_radius: px(2.),
},
BoxShadow {
color: hsla(60.0 / 360., 1.0, 0.5, 0.3), // Yellow
offset: point(px(12.), px(0.)),
blur_radius: px(8.),
spread_radius: px(2.),
},
BoxShadow {
color: hsla(120.0 / 360., 1.0, 0.5, 0.3), // Green
offset: point(px(0.), px(12.)),
blur_radius: px(8.),
spread_radius: px(2.),
},
BoxShadow {
color: hsla(240.0 / 360., 1.0, 0.5, 0.3), // Blue
offset: point(px(-12.), px(0.)),
blur_radius: px(8.),
spread_radius: px(2.),
},
]),
),
example(
"Square Multiple",
Shadow::square().shadow(smallvec![
BoxShadow {
color: hsla(0.0 / 360., 1.0, 0.5, 0.3), // Red
offset: point(px(0.), px(-12.)),
blur_radius: px(8.),
spread_radius: px(2.),
},
BoxShadow {
color: hsla(60.0 / 360., 1.0, 0.5, 0.3), // Yellow
offset: point(px(12.), px(0.)),
blur_radius: px(8.),
spread_radius: px(2.),
},
BoxShadow {
color: hsla(120.0 / 360., 1.0, 0.5, 0.3), // Green
offset: point(px(0.), px(12.)),
blur_radius: px(8.),
spread_radius: px(2.),
},
BoxShadow {
color: hsla(240.0 / 360., 1.0, 0.5, 0.3), // Blue
offset: point(px(-12.), px(0.)),
blur_radius: px(8.),
spread_radius: px(2.),
},
]),
),
example(
"Rounded Large Multiple",
Shadow::rounded_large().shadow(smallvec![
BoxShadow {
color: hsla(0.0 / 360., 1.0, 0.5, 0.3), // Red
offset: point(px(0.), px(-12.)),
blur_radius: px(8.),
spread_radius: px(2.),
},
BoxShadow {
color: hsla(60.0 / 360., 1.0, 0.5, 0.3), // Yellow
offset: point(px(12.), px(0.)),
blur_radius: px(8.),
spread_radius: px(2.),
},
BoxShadow {
color: hsla(120.0 / 360., 1.0, 0.5, 0.3), // Green
offset: point(px(0.), px(12.)),
blur_radius: px(8.),
spread_radius: px(2.),
},
BoxShadow {
color: hsla(240.0 / 360., 1.0, 0.5, 0.3), // Blue
offset: point(px(-12.), px(0.)),
blur_radius: px(8.),
spread_radius: px(2.),
},
]),
),
]),
]))
}
}
fn main() {
App::new().run(|cx: &mut AppContext| {
let bounds = Bounds::centered(None, size(px(300.0), px(300.0)), cx);
let bounds = Bounds::centered(None, size(px(1000.0), px(800.0)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
@@ -28,5 +577,7 @@ fn main() {
|cx| cx.new_view(|_cx| Shadow {}),
)
.unwrap();
cx.activate(true);
});
}

View File

@@ -0,0 +1,337 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Shadow Examples</title>
<style>
body {
font-family: Arial, sans-serif;
font-size: 12px;
margin: 0;
padding: 0;
background-color: #ffffff;
}
.container {
display: flex;
flex-direction: column;
height: 100vh;
overflow-y: scroll;
}
.row {
display: flex;
border-bottom: 1px solid rgba(0, 0, 0, 1);
}
.example {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: calc(100% / 6);
border-right: 1px solid rgba(0, 0, 0, 1);
}
.box {
width: 64px;
height: 64px;
background-color: #ffffff;
border: 1px solid rgba(0, 0, 0, 0.1);
margin: 48px 0;
}
.label {
width: 100%;
border-top: 1px solid rgba(0, 0, 0, 1);
padding: 4px;
text-align: center;
}
/* Shapes */
.square {
}
.rounded-small {
border-radius: 4px;
}
.rounded-medium {
border-radius: 8px;
}
.rounded-large {
border-radius: 12px;
}
.circle {
border-radius: 50%;
}
/* Shadows */
.shadow-sm {
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
.shadow-md {
box-shadow:
0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.shadow-lg {
box-shadow:
0 10px 15px -3px rgba(0, 0, 0, 0.1),
0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.shadow-xl {
box-shadow:
0 20px 25px -5px rgba(0, 0, 0, 0.1),
0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.shadow-2xl {
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}
/* Blur radii */
.blur-0 {
box-shadow: 0 8px 0 0 rgba(0, 0, 0, 0.3);
}
.blur-2 {
box-shadow: 0 8px 2px 0 rgba(0, 0, 0, 0.3);
}
.blur-4 {
box-shadow: 0 8px 4px 0 rgba(0, 0, 0, 0.3);
}
.blur-8 {
box-shadow: 0 8px 8px 0 rgba(0, 0, 0, 0.3);
}
.blur-16 {
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.3);
}
/* Spread radii */
.spread-0 {
box-shadow: 0 8px 8px 0 rgba(0, 0, 0, 0.3);
}
.spread-2 {
box-shadow: 0 8px 8px 2px rgba(0, 0, 0, 0.3);
}
.spread-4 {
box-shadow: 0 8px 8px 4px rgba(0, 0, 0, 0.3);
}
.spread-8 {
box-shadow: 0 8px 8px 8px rgba(0, 0, 0, 0.3);
}
.spread-16 {
box-shadow: 0 8px 8px 16px rgba(0, 0, 0, 0.3);
}
/* Directional shadows */
.shadow-left {
box-shadow: -8px 0 8px 0 rgba(128, 0, 128, 0.3);
}
.shadow-right {
box-shadow: 8px 0 8px 0 rgba(128, 0, 128, 0.3);
}
.shadow-top {
box-shadow: 0 -8px 8px 0 rgba(128, 0, 128, 0.3);
}
.shadow-bottom {
box-shadow: 0 8px 8px 0 rgba(128, 0, 128, 0.3);
}
/* Multiple shadows */
.shadow-multiple {
box-shadow:
0 -12px 8px 2px rgba(255, 0, 0, 0.3),
12px 0 8px 2px rgba(255, 255, 0, 0.3),
0 12px 8px 2px rgba(0, 255, 0, 0.3),
-12px 0 8px 2px rgba(0, 0, 255, 0.3);
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="example">
<div class="box square shadow-bottom"></div>
<div class="label">Square</div>
</div>
<div class="example">
<div class="box rounded-small shadow-bottom"></div>
<div class="label">Rounded 4</div>
</div>
<div class="example">
<div class="box rounded-medium shadow-bottom"></div>
<div class="label">Rounded 8</div>
</div>
<div class="example">
<div class="box rounded-large shadow-bottom"></div>
<div class="label">Rounded 16</div>
</div>
<div class="example">
<div class="box circle shadow-bottom"></div>
<div class="label">Circle</div>
</div>
</div>
<div class="row">
<div class="example">
<div class="box circle"></div>
<div class="label">None</div>
</div>
<div class="example">
<div class="box circle shadow-sm"></div>
<div class="label">Small</div>
</div>
<div class="example">
<div class="box circle shadow-md"></div>
<div class="label">Medium</div>
</div>
<div class="example">
<div class="box circle shadow-lg"></div>
<div class="label">Large</div>
</div>
<div class="example">
<div class="box circle shadow-xl"></div>
<div class="label">Extra Large</div>
</div>
<div class="example">
<div class="box circle shadow-2xl"></div>
<div class="label">2X Large</div>
</div>
</div>
<div class="row">
<div class="example">
<div class="box circle blur-0"></div>
<div class="label">Blur 0</div>
</div>
<div class="example">
<div class="box circle blur-2"></div>
<div class="label">Blur 2</div>
</div>
<div class="example">
<div class="box circle blur-4"></div>
<div class="label">Blur 4</div>
</div>
<div class="example">
<div class="box circle blur-8"></div>
<div class="label">Blur 8</div>
</div>
<div class="example">
<div class="box circle blur-16"></div>
<div class="label">Blur 16</div>
</div>
</div>
<div class="row">
<div class="example">
<div class="box circle spread-0"></div>
<div class="label">Spread 0</div>
</div>
<div class="example">
<div class="box circle spread-2"></div>
<div class="label">Spread 2</div>
</div>
<div class="example">
<div class="box circle spread-4"></div>
<div class="label">Spread 4</div>
</div>
<div class="example">
<div class="box circle spread-8"></div>
<div class="label">Spread 8</div>
</div>
<div class="example">
<div class="box circle spread-16"></div>
<div class="label">Spread 16</div>
</div>
</div>
<div class="row">
<div class="example">
<div class="box square spread-0"></div>
<div class="label">Square Spread 0</div>
</div>
<div class="example">
<div class="box square spread-8"></div>
<div class="label">Square Spread 8</div>
</div>
<div class="example">
<div class="box square spread-16"></div>
<div class="label">Square Spread 16</div>
</div>
</div>
<div class="row">
<div class="example">
<div class="box rounded-large spread-0"></div>
<div class="label">Rounded Large Spread 0</div>
</div>
<div class="example">
<div class="box rounded-large spread-8"></div>
<div class="label">Rounded Large Spread 8</div>
</div>
<div class="example">
<div class="box rounded-large spread-16"></div>
<div class="label">Rounded Large Spread 16</div>
</div>
</div>
<div class="row">
<div class="example">
<div class="box circle shadow-left"></div>
<div class="label">Left</div>
</div>
<div class="example">
<div class="box circle shadow-right"></div>
<div class="label">Right</div>
</div>
<div class="example">
<div class="box circle shadow-top"></div>
<div class="label">Top</div>
</div>
<div class="example">
<div class="box circle shadow-bottom"></div>
<div class="label">Bottom</div>
</div>
</div>
<div class="row">
<div class="example">
<div class="box square shadow-left"></div>
<div class="label">Square Left</div>
</div>
<div class="example">
<div class="box square shadow-right"></div>
<div class="label">Square Right</div>
</div>
<div class="example">
<div class="box square shadow-top"></div>
<div class="label">Square Top</div>
</div>
<div class="example">
<div class="box square shadow-bottom"></div>
<div class="label">Square Bottom</div>
</div>
</div>
<div class="row">
<div class="example">
<div class="box rounded-large shadow-left"></div>
<div class="label">Rounded Large Left</div>
</div>
<div class="example">
<div class="box rounded-large shadow-right"></div>
<div class="label">Rounded Large Right</div>
</div>
<div class="example">
<div class="box rounded-large shadow-top"></div>
<div class="label">Rounded Large Top</div>
</div>
<div class="example">
<div class="box rounded-large shadow-bottom"></div>
<div class="label">Rounded Large Bottom</div>
</div>
</div>
<div class="row">
<div class="example">
<div class="box circle shadow-multiple"></div>
<div class="label">Circle Multiple</div>
</div>
<div class="example">
<div class="box square shadow-multiple"></div>
<div class="label">Square Multiple</div>
</div>
<div class="example">
<div class="box rounded-large shadow-multiple"></div>
<div class="label">Rounded Large Multiple</div>
</div>
</div>
</div>
</body>
</html>

View File

@@ -180,14 +180,13 @@ vertex ShadowVertexOutput shadow_vertex(
float2 unit_vertex = unit_vertices[unit_vertex_id];
Shadow shadow = shadows[shadow_id];
float margin = 3. * shadow.blur_radius;
// Set the bounds of the shadow and adjust its size based on the shadow's
// spread radius to achieve the spreading effect
// Calculate the expanded bounds
float expansion = max(3. * shadow.blur_radius, 1.0);
Bounds_ScaledPixels bounds = shadow.bounds;
bounds.origin.x -= margin;
bounds.origin.y -= margin;
bounds.size.width += 2. * margin;
bounds.size.height += 2. * margin;
bounds.origin.x -= expansion;
bounds.origin.y -= expansion;
bounds.size.width += 2. * expansion;
bounds.size.height += 2. * expansion;
float4 device_position =
to_device_position(unit_vertex, bounds, viewport_size);
@@ -205,46 +204,32 @@ vertex ShadowVertexOutput shadow_vertex(
fragment float4 shadow_fragment(ShadowFragmentInput input [[stage_in]],
constant Shadow *shadows
[[buffer(ShadowInputIndex_Shadows)]]) {
Shadow shadow = shadows[input.shadow_id];
Shadow shadow = shadows[input.shadow_id];
float2 origin = float2(shadow.bounds.origin.x, shadow.bounds.origin.y);
float2 size = float2(shadow.bounds.size.width, shadow.bounds.size.height);
float2 half_size = size / 2.;
float2 center = origin + half_size;
float2 point = input.position.xy - center;
float corner_radius;
if (point.x < 0.) {
if (point.y < 0.) {
corner_radius = shadow.corner_radii.top_left;
} else {
corner_radius = shadow.corner_radii.bottom_left;
}
} else {
if (point.y < 0.) {
corner_radius = shadow.corner_radii.top_right;
} else {
corner_radius = shadow.corner_radii.bottom_right;
}
}
float2 origin = float2(shadow.bounds.origin.x, shadow.bounds.origin.y);
float2 size = float2(shadow.bounds.size.width, shadow.bounds.size.height);
float2 half_size = size / 2.;
float2 center = origin + half_size;
float2 point = input.position.xy - center;
// The signal is only non-zero in a limited range, so don't waste samples
float low = point.y - half_size.y;
float high = point.y + half_size.y;
float start = clamp(-3. * shadow.blur_radius, low, high);
float end = clamp(3. * shadow.blur_radius, low, high);
// Calculate distance from the edge of the shape
float2 d = abs(point) - half_size + shadow.corner_radii.top_left;
float corner_distance = length(max(d, 0.)) + min(max(d.x, d.y), 0.);
float distance = corner_distance - shadow.corner_radii.top_left;
// Accumulate samples (we can get away with surprisingly few samples)
float step = (end - start) / 4.;
float y = start + step * 0.5;
float alpha = 0.;
for (int i = 0; i < 4; i++) {
alpha += blur_along_x(point.x, point.y - y, shadow.blur_radius,
corner_radius, half_size) *
gaussian(y, shadow.blur_radius) * step;
y += step;
}
// Apply spread (reduced effect and maintaining circular shape)
float spread_factor = 0.5; // Adjust this to fine-tune the spread effect
distance -= shadow.spread_radius * spread_factor;
distance = length(max(float2(distance, 0.), 0.)) + min(distance, 0.);
return input.color * float4(1., 1., 1., alpha);
// Improved blur calculation
float blur_amount = shadow.blur_radius * 0.5;
float alpha = smoothstep(blur_amount, -blur_amount, distance);
// Apply a smoother falloff
alpha = pow(alpha, 1.3);
return input.color * float4(1., 1., 1., alpha);
}
struct UnderlineVertexOutput {

View File

@@ -493,10 +493,12 @@ impl From<Underline> for Primitive {
pub(crate) struct Shadow {
pub order: DrawOrder,
pub blur_radius: ScaledPixels,
pub spread_radius: ScaledPixels,
pub bounds: Bounds<ScaledPixels>,
pub corner_radii: Corners<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
pub color: Hsla,
pub offset: Point<ScaledPixels>,
}
impl From<Shadow> for Primitive {

View File

@@ -2286,6 +2286,8 @@ impl<'a> WindowContext<'a> {
content_mask: content_mask.scale(scale_factor),
corner_radii: corner_radii.scale(scale_factor),
color: shadow.color.opacity(opacity),
spread_radius: shadow.spread_radius.scale(scale_factor),
offset: shadow.offset.scale(scale_factor),
});
}
}

View File

@@ -421,7 +421,7 @@ pub fn box_shadow_style_methods(input: TokenStream) -> TokenStream {
self.style().box_shadow = Some(smallvec![
BoxShadow {
color: hsla(0.5, 0., 0., 0.1),
color: hsla(0., 0., 0., 0.1),
offset: point(px(0.), px(4.)),
blur_radius: px(6.),
spread_radius: px(-1.),