MODAL
This commit is contained in:
parent
1e6a0f1c7b
commit
acab2f9003
9 changed files with 207 additions and 65 deletions
|
@ -1,4 +1,8 @@
|
||||||
use gpui::{actions, div, px, red, AppContext, Div, Render, Styled, ViewContext, VisualContext};
|
use gpui::{
|
||||||
|
actions, div, px, red, AppContext, Div, ParentElement, Render, Styled, ViewContext,
|
||||||
|
VisualContext,
|
||||||
|
};
|
||||||
|
use ui::modal;
|
||||||
use workspace::ModalRegistry;
|
use workspace::ModalRegistry;
|
||||||
|
|
||||||
actions!(Toggle);
|
actions!(Toggle);
|
||||||
|
@ -27,9 +31,8 @@ pub struct GoToLine;
|
||||||
impl Render for GoToLine {
|
impl Render for GoToLine {
|
||||||
type Element = Div<Self>;
|
type Element = Div<Self>;
|
||||||
|
|
||||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
dbg!("rendering GoToLine");
|
modal(cx).child(div().bg(red()).w(px(100.0)).h(px(100.0)))
|
||||||
div().bg(red()).w(px(100.0)).h(px(100.0))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
SharedString, StyleRefinement, Visibility,
|
SharedString, StyleRefinement, Visibility,
|
||||||
};
|
};
|
||||||
use crate::{BoxShadow, TextStyleRefinement};
|
use crate::{BoxShadow, TextStyleRefinement};
|
||||||
use smallvec::smallvec;
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
pub trait Styled {
|
pub trait Styled {
|
||||||
fn style(&mut self) -> &mut StyleRefinement;
|
fn style(&mut self) -> &mut StyleRefinement;
|
||||||
|
@ -290,24 +290,11 @@ pub trait Styled {
|
||||||
|
|
||||||
/// Sets the box shadow of the element.
|
/// Sets the box shadow of the element.
|
||||||
/// [Docs](https://tailwindcss.com/docs/box-shadow)
|
/// [Docs](https://tailwindcss.com/docs/box-shadow)
|
||||||
fn shadow(mut self) -> Self
|
fn shadow(mut self, shadows: SmallVec<[BoxShadow; 2]>) -> Self
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style().box_shadow = Some(smallvec![
|
self.style().box_shadow = Some(shadows);
|
||||||
BoxShadow {
|
|
||||||
color: hsla(0., 0., 0., 0.1),
|
|
||||||
offset: point(px(0.), px(1.)),
|
|
||||||
blur_radius: px(3.),
|
|
||||||
spread_radius: px(0.),
|
|
||||||
},
|
|
||||||
BoxShadow {
|
|
||||||
color: hsla(0., 0., 0., 0.1),
|
|
||||||
offset: point(px(0.), px(1.)),
|
|
||||||
blur_radius: px(2.),
|
|
||||||
spread_radius: px(-1.),
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ mod button;
|
||||||
mod checkbox;
|
mod checkbox;
|
||||||
mod context_menu;
|
mod context_menu;
|
||||||
mod details;
|
mod details;
|
||||||
|
mod elevated_surface;
|
||||||
mod facepile;
|
mod facepile;
|
||||||
mod icon;
|
mod icon;
|
||||||
mod icon_button;
|
mod icon_button;
|
||||||
|
@ -30,6 +31,7 @@ pub use button::*;
|
||||||
pub use checkbox::*;
|
pub use checkbox::*;
|
||||||
pub use context_menu::*;
|
pub use context_menu::*;
|
||||||
pub use details::*;
|
pub use details::*;
|
||||||
|
pub use elevated_surface::*;
|
||||||
pub use facepile::*;
|
pub use facepile::*;
|
||||||
pub use icon::*;
|
pub use icon::*;
|
||||||
pub use icon_button::*;
|
pub use icon_button::*;
|
||||||
|
|
28
crates/ui2/src/components/elevated_surface.rs
Normal file
28
crates/ui2/src/components/elevated_surface.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
use gpui::{div, hsla, point, px, BoxShadow, Div};
|
||||||
|
|
||||||
|
use crate::{prelude::*, v_stack};
|
||||||
|
|
||||||
|
/// Create an elevated surface.
|
||||||
|
///
|
||||||
|
/// Must be used inside of a relative parent element
|
||||||
|
pub fn elevated_surface<V: 'static>(level: ElevationIndex, cx: &mut ViewContext<V>) -> Div<V> {
|
||||||
|
let colors = cx.theme().colors();
|
||||||
|
|
||||||
|
// let shadow = BoxShadow {
|
||||||
|
// color: hsla(0., 0., 0., 0.1),
|
||||||
|
// offset: point(px(0.), px(1.)),
|
||||||
|
// blur_radius: px(3.),
|
||||||
|
// spread_radius: px(0.),
|
||||||
|
// };
|
||||||
|
|
||||||
|
v_stack()
|
||||||
|
.rounded_lg()
|
||||||
|
.bg(colors.elevated_surface_background)
|
||||||
|
.border()
|
||||||
|
.border_color(colors.border)
|
||||||
|
.shadow(level.shadow())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn modal<V>(cx: &mut ViewContext<V>) -> Div<V> {
|
||||||
|
elevated_surface(ElevationIndex::ModalSurfaces, cx)
|
||||||
|
}
|
|
@ -1,3 +1,6 @@
|
||||||
|
use gpui::{hsla, point, px, BoxShadow};
|
||||||
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
#[doc = include_str!("elevation.md")]
|
#[doc = include_str!("elevation.md")]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Elevation {
|
pub enum Elevation {
|
||||||
|
@ -17,8 +20,8 @@ pub enum ElevationIndex {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ElevationIndex {
|
impl ElevationIndex {
|
||||||
pub fn usize(&self) -> usize {
|
pub fn z_index(self) -> u32 {
|
||||||
match *self {
|
match self {
|
||||||
ElevationIndex::AppBackground => 0,
|
ElevationIndex::AppBackground => 0,
|
||||||
ElevationIndex::UISurface => 100,
|
ElevationIndex::UISurface => 100,
|
||||||
ElevationIndex::ElevatedSurface => 200,
|
ElevationIndex::ElevatedSurface => 200,
|
||||||
|
@ -27,6 +30,26 @@ impl ElevationIndex {
|
||||||
ElevationIndex::DraggedElement => 900,
|
ElevationIndex::DraggedElement => 900,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn shadow(self) -> SmallVec<[BoxShadow; 2]> {
|
||||||
|
match self {
|
||||||
|
ElevationIndex::AppBackground => smallvec![],
|
||||||
|
|
||||||
|
ElevationIndex::UISurface => smallvec![BoxShadow {
|
||||||
|
color: hsla(0., 0., 0., 0.12),
|
||||||
|
offset: point(px(0.), px(1.)),
|
||||||
|
blur_radius: px(3.),
|
||||||
|
spread_radius: px(0.),
|
||||||
|
}],
|
||||||
|
|
||||||
|
_ => smallvec![BoxShadow {
|
||||||
|
color: hsla(0., 0., 0., 0.32),
|
||||||
|
offset: point(px(1.), px(3.)),
|
||||||
|
blur_radius: px(12.),
|
||||||
|
spread_radius: px(0.),
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::{any::TypeId, sync::Arc};
|
use std::{any::TypeId, sync::Arc};
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, AnyView, AppContext, DispatchPhase, Div, ParentElement, Render, StatelessInteractive,
|
div, AnyView, AppContext, Component, DispatchPhase, Div, ParentElement, Render,
|
||||||
View, ViewContext,
|
StatelessInteractive, Styled, View, ViewContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Workspace;
|
use crate::Workspace;
|
||||||
|
@ -69,22 +69,47 @@ impl ModalLayer {
|
||||||
Self { open_modal: None }
|
Self { open_modal: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Workspace
|
||||||
|
// - ModalLayer parent
|
||||||
|
// - - container
|
||||||
|
// - - - modal
|
||||||
|
// - - - content of the modal
|
||||||
|
// - - content of the workspace
|
||||||
|
|
||||||
|
// app
|
||||||
|
// workspace
|
||||||
|
// container some layer that contains all modals and is 100% wide and high
|
||||||
|
// modal (this has a shadow, some witdht)
|
||||||
|
// whatever
|
||||||
|
|
||||||
pub fn render(&self, workspace: &Workspace, cx: &ViewContext<Workspace>) -> Div<Workspace> {
|
pub fn render(&self, workspace: &Workspace, cx: &ViewContext<Workspace>) -> Div<Workspace> {
|
||||||
let mut div = div();
|
let mut parent = div().relative();
|
||||||
|
|
||||||
// div, c workspace.toggle_modal()div.on_action()) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for (type_id, action) in cx.global::<ModalRegistry>().registered_modals.iter() {
|
|
||||||
// div = div.useful_on_action(*type_id, action)
|
|
||||||
// }
|
|
||||||
|
|
||||||
for (_, action) in cx.global::<ModalRegistry>().registered_modals.iter() {
|
for (_, action) in cx.global::<ModalRegistry>().registered_modals.iter() {
|
||||||
div = (action)(div);
|
parent = (action)(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
div.children(self.open_modal.clone())
|
parent.when_some(self.open_modal.as_ref(), |parent, open_modal| {
|
||||||
|
let container1 = div()
|
||||||
|
.absolute()
|
||||||
|
.size_full()
|
||||||
|
.top_0()
|
||||||
|
.left_0()
|
||||||
|
.right_0()
|
||||||
|
.bottom_0();
|
||||||
|
|
||||||
|
// transparent layer
|
||||||
|
let container2 = div()
|
||||||
|
.flex()
|
||||||
|
.h_96()
|
||||||
|
.justify_center()
|
||||||
|
.size_full()
|
||||||
|
.relative()
|
||||||
|
.top_20()
|
||||||
|
.z_index(400);
|
||||||
|
|
||||||
|
parent.child(container1.child(container2.child(open_modal.clone())))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ export default function assistant(): any {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
|
||||||
const interactive_role = (
|
const interactive_role = (
|
||||||
color: StyleSets
|
color: StyleSets,
|
||||||
): Interactive<RoleCycleButton> => {
|
): Interactive<RoleCycleButton> => {
|
||||||
return interactive({
|
return interactive({
|
||||||
base: {
|
base: {
|
||||||
|
@ -94,7 +94,7 @@ export default function assistant(): any {
|
||||||
margin: { left: 8, right: 18 },
|
margin: { left: 8, right: 18 },
|
||||||
color: foreground(theme.highest, "positive"),
|
color: foreground(theme.highest, "positive"),
|
||||||
width: 12,
|
width: 12,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
retrieve_context: toggleable({
|
retrieve_context: toggleable({
|
||||||
base: interactive({
|
base: interactive({
|
||||||
|
@ -106,7 +106,8 @@ export default function assistant(): any {
|
||||||
background: background(theme.highest, "on"),
|
background: background(theme.highest, "on"),
|
||||||
corner_radius: 2,
|
corner_radius: 2,
|
||||||
border: {
|
border: {
|
||||||
width: 1., color: background(theme.highest, "on")
|
width: 1,
|
||||||
|
color: background(theme.highest, "on"),
|
||||||
},
|
},
|
||||||
margin: { left: 2 },
|
margin: { left: 2 },
|
||||||
padding: {
|
padding: {
|
||||||
|
@ -118,17 +119,45 @@ export default function assistant(): any {
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
hovered: {
|
hovered: {
|
||||||
...text(theme.highest, "mono", "variant", "hovered"),
|
...text(
|
||||||
background: background(theme.highest, "on", "hovered"),
|
theme.highest,
|
||||||
|
"mono",
|
||||||
|
"variant",
|
||||||
|
"hovered",
|
||||||
|
),
|
||||||
|
background: background(
|
||||||
|
theme.highest,
|
||||||
|
"on",
|
||||||
|
"hovered",
|
||||||
|
),
|
||||||
border: {
|
border: {
|
||||||
width: 1., color: background(theme.highest, "on", "hovered")
|
width: 1,
|
||||||
|
color: background(
|
||||||
|
theme.highest,
|
||||||
|
"on",
|
||||||
|
"hovered",
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
clicked: {
|
clicked: {
|
||||||
...text(theme.highest, "mono", "variant", "pressed"),
|
...text(
|
||||||
background: background(theme.highest, "on", "pressed"),
|
theme.highest,
|
||||||
|
"mono",
|
||||||
|
"variant",
|
||||||
|
"pressed",
|
||||||
|
),
|
||||||
|
background: background(
|
||||||
|
theme.highest,
|
||||||
|
"on",
|
||||||
|
"pressed",
|
||||||
|
),
|
||||||
border: {
|
border: {
|
||||||
width: 1., color: background(theme.highest, "on", "pressed")
|
width: 1,
|
||||||
|
color: background(
|
||||||
|
theme.highest,
|
||||||
|
"on",
|
||||||
|
"pressed",
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -143,11 +172,19 @@ export default function assistant(): any {
|
||||||
border: border(theme.highest, "accent"),
|
border: border(theme.highest, "accent"),
|
||||||
},
|
},
|
||||||
hovered: {
|
hovered: {
|
||||||
background: background(theme.highest, "accent", "hovered"),
|
background: background(
|
||||||
|
theme.highest,
|
||||||
|
"accent",
|
||||||
|
"hovered",
|
||||||
|
),
|
||||||
border: border(theme.highest, "accent", "hovered"),
|
border: border(theme.highest, "accent", "hovered"),
|
||||||
},
|
},
|
||||||
clicked: {
|
clicked: {
|
||||||
background: background(theme.highest, "accent", "pressed"),
|
background: background(
|
||||||
|
theme.highest,
|
||||||
|
"accent",
|
||||||
|
"pressed",
|
||||||
|
),
|
||||||
border: border(theme.highest, "accent", "pressed"),
|
border: border(theme.highest, "accent", "pressed"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -163,7 +200,8 @@ export default function assistant(): any {
|
||||||
background: background(theme.highest, "on"),
|
background: background(theme.highest, "on"),
|
||||||
corner_radius: 2,
|
corner_radius: 2,
|
||||||
border: {
|
border: {
|
||||||
width: 1., color: background(theme.highest, "on")
|
width: 1,
|
||||||
|
color: background(theme.highest, "on"),
|
||||||
},
|
},
|
||||||
padding: {
|
padding: {
|
||||||
left: 4,
|
left: 4,
|
||||||
|
@ -174,17 +212,45 @@ export default function assistant(): any {
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
hovered: {
|
hovered: {
|
||||||
...text(theme.highest, "mono", "variant", "hovered"),
|
...text(
|
||||||
background: background(theme.highest, "on", "hovered"),
|
theme.highest,
|
||||||
|
"mono",
|
||||||
|
"variant",
|
||||||
|
"hovered",
|
||||||
|
),
|
||||||
|
background: background(
|
||||||
|
theme.highest,
|
||||||
|
"on",
|
||||||
|
"hovered",
|
||||||
|
),
|
||||||
border: {
|
border: {
|
||||||
width: 1., color: background(theme.highest, "on", "hovered")
|
width: 1,
|
||||||
|
color: background(
|
||||||
|
theme.highest,
|
||||||
|
"on",
|
||||||
|
"hovered",
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
clicked: {
|
clicked: {
|
||||||
...text(theme.highest, "mono", "variant", "pressed"),
|
...text(
|
||||||
background: background(theme.highest, "on", "pressed"),
|
theme.highest,
|
||||||
|
"mono",
|
||||||
|
"variant",
|
||||||
|
"pressed",
|
||||||
|
),
|
||||||
|
background: background(
|
||||||
|
theme.highest,
|
||||||
|
"on",
|
||||||
|
"pressed",
|
||||||
|
),
|
||||||
border: {
|
border: {
|
||||||
width: 1., color: background(theme.highest, "on", "pressed")
|
width: 1,
|
||||||
|
color: background(
|
||||||
|
theme.highest,
|
||||||
|
"on",
|
||||||
|
"pressed",
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -199,11 +265,19 @@ export default function assistant(): any {
|
||||||
border: border(theme.highest, "accent"),
|
border: border(theme.highest, "accent"),
|
||||||
},
|
},
|
||||||
hovered: {
|
hovered: {
|
||||||
background: background(theme.highest, "accent", "hovered"),
|
background: background(
|
||||||
|
theme.highest,
|
||||||
|
"accent",
|
||||||
|
"hovered",
|
||||||
|
),
|
||||||
border: border(theme.highest, "accent", "hovered"),
|
border: border(theme.highest, "accent", "hovered"),
|
||||||
},
|
},
|
||||||
clicked: {
|
clicked: {
|
||||||
background: background(theme.highest, "accent", "pressed"),
|
background: background(
|
||||||
|
theme.highest,
|
||||||
|
"accent",
|
||||||
|
"pressed",
|
||||||
|
),
|
||||||
border: border(theme.highest, "accent", "pressed"),
|
border: border(theme.highest, "accent", "pressed"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -78,33 +78,33 @@ export default function status_bar(): any {
|
||||||
padding: { top: 2, bottom: 2, left: 6, right: 6 },
|
padding: { top: 2, bottom: 2, left: 6, right: 6 },
|
||||||
},
|
},
|
||||||
container_warning: diagnostic_status_container,
|
container_warning: diagnostic_status_container,
|
||||||
container_error: diagnostic_status_container
|
container_error: diagnostic_status_container,
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
hovered: {
|
hovered: {
|
||||||
icon_color_ok: foreground(layer, "on"),
|
icon_color_ok: foreground(layer, "on"),
|
||||||
container_ok: {
|
container_ok: {
|
||||||
background: background(layer, "hovered")
|
background: background(layer, "hovered"),
|
||||||
},
|
},
|
||||||
container_warning: {
|
container_warning: {
|
||||||
background: background(layer, "hovered")
|
background: background(layer, "hovered"),
|
||||||
},
|
},
|
||||||
container_error: {
|
container_error: {
|
||||||
background: background(layer, "hovered")
|
background: background(layer, "hovered"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
clicked: {
|
clicked: {
|
||||||
icon_color_ok: foreground(layer, "on"),
|
icon_color_ok: foreground(layer, "on"),
|
||||||
container_ok: {
|
container_ok: {
|
||||||
background: background(layer, "pressed")
|
background: background(layer, "pressed"),
|
||||||
},
|
},
|
||||||
container_warning: {
|
container_warning: {
|
||||||
background: background(layer, "pressed")
|
background: background(layer, "pressed"),
|
||||||
},
|
},
|
||||||
container_error: {
|
container_error: {
|
||||||
background: background(layer, "pressed")
|
background: background(layer, "pressed"),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
panel_buttons: {
|
panel_buttons: {
|
||||||
|
|
|
@ -31,7 +31,7 @@ export const theme: ThemeConfig = {
|
||||||
color.muted,
|
color.muted,
|
||||||
color.subtle,
|
color.subtle,
|
||||||
color.text,
|
color.text,
|
||||||
].reverse()
|
].reverse(),
|
||||||
)
|
)
|
||||||
.domain([0, 0.35, 0.45, 0.65, 0.7, 0.8, 0.9, 1]),
|
.domain([0, 0.35, 0.45, 0.65, 0.7, 0.8, 0.9, 1]),
|
||||||
red: color_ramp(chroma(color.love)),
|
red: color_ramp(chroma(color.love)),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue