assets/icons/reject.svg → assets/icons/decline.svg 🔗
Max Brunsfeld and Nathan Sobo created
Co-authored-by: Nathan Sobo <nathan@zed.dev>
assets/icons/decline.svg | 0
assets/themes/cave-dark.json | 14 ++
assets/themes/cave-light.json | 14 ++
assets/themes/dark.json | 14 ++
assets/themes/light.json | 14 ++
assets/themes/solarized-dark.json | 14 ++
assets/themes/solarized-light.json | 14 ++
assets/themes/sulphurpool-dark.json | 14 ++
assets/themes/sulphurpool-light.json | 14 ++
crates/client/src/user.rs | 2
crates/contacts_panel/src/contact_finder.rs | 2
crates/contacts_panel/src/contact_notification.rs | 67 ++++++++++------
crates/contacts_panel/src/contacts_panel.rs | 8 +-
crates/rpc/proto/zed.proto | 2
crates/theme/src/theme.rs | 4
crates/workspace/src/workspace.rs | 2
styles/src/styleTree/contactNotification.ts | 17 +++-
styles/src/styleTree/workspace.ts | 2
18 files changed, 152 insertions(+), 66 deletions(-)
@@ -505,7 +505,7 @@
}
},
"notifications": {
- "width": 256,
+ "width": 380,
"margin": {
"right": 10,
"bottom": 10
@@ -1698,7 +1698,8 @@
"color": "#e2dfe7",
"size": 12,
"margin": {
- "left": 4
+ "left": 8,
+ "right": 8
}
},
"header_height": 18,
@@ -1707,6 +1708,7 @@
"color": "#8b8792",
"size": 12,
"margin": {
+ "left": 20,
"top": 6,
"bottom": 6
}
@@ -1720,6 +1722,9 @@
"corner_radius": 6,
"margin": {
"left": 6
+ },
+ "hover": {
+ "background": "#26232a3d"
}
},
"dismiss_button": {
@@ -1727,7 +1732,10 @@
"icon_width": 8,
"icon_height": 8,
"button_width": 8,
- "button_height": 8
+ "button_height": 8,
+ "hover": {
+ "color": "#e2dfe7"
+ }
}
}
}
@@ -505,7 +505,7 @@
}
},
"notifications": {
- "width": 256,
+ "width": 380,
"margin": {
"right": 10,
"bottom": 10
@@ -1698,7 +1698,8 @@
"color": "#26232a",
"size": 12,
"margin": {
- "left": 4
+ "left": 8,
+ "right": 8
}
},
"header_height": 18,
@@ -1707,6 +1708,7 @@
"color": "#585260",
"size": 12,
"margin": {
+ "left": 20,
"top": 6,
"bottom": 6
}
@@ -1720,6 +1722,9 @@
"corner_radius": 6,
"margin": {
"left": 6
+ },
+ "hover": {
+ "background": "#e2dfe71f"
}
},
"dismiss_button": {
@@ -1727,7 +1732,10 @@
"icon_width": 8,
"icon_height": 8,
"button_width": 8,
- "button_height": 8
+ "button_height": 8,
+ "hover": {
+ "color": "#26232a"
+ }
}
}
}
@@ -505,7 +505,7 @@
}
},
"notifications": {
- "width": 256,
+ "width": 380,
"margin": {
"right": 10,
"bottom": 10
@@ -1698,7 +1698,8 @@
"color": "#f1f1f1",
"size": 12,
"margin": {
- "left": 4
+ "left": 8,
+ "right": 8
}
},
"header_height": 18,
@@ -1707,6 +1708,7 @@
"color": "#9c9c9c",
"size": 12,
"margin": {
+ "left": 20,
"top": 6,
"bottom": 6
}
@@ -1720,6 +1722,9 @@
"corner_radius": 6,
"margin": {
"left": 6
+ },
+ "hover": {
+ "background": "#070707"
}
},
"dismiss_button": {
@@ -1727,7 +1732,10 @@
"icon_width": 8,
"icon_height": 8,
"button_width": 8,
- "button_height": 8
+ "button_height": 8,
+ "hover": {
+ "color": "#c6c6c6"
+ }
}
}
}
@@ -505,7 +505,7 @@
}
},
"notifications": {
- "width": 256,
+ "width": 380,
"margin": {
"right": 10,
"bottom": 10
@@ -1698,7 +1698,8 @@
"color": "#2b2b2b",
"size": 12,
"margin": {
- "left": 4
+ "left": 8,
+ "right": 8
}
},
"header_height": 18,
@@ -1707,6 +1708,7 @@
"color": "#474747",
"size": 12,
"margin": {
+ "left": 20,
"top": 6,
"bottom": 6
}
@@ -1720,6 +1722,9 @@
"corner_radius": 6,
"margin": {
"left": 6
+ },
+ "hover": {
+ "background": "#e3e3e3"
}
},
"dismiss_button": {
@@ -1727,7 +1732,10 @@
"icon_width": 8,
"icon_height": 8,
"button_width": 8,
- "button_height": 8
+ "button_height": 8,
+ "hover": {
+ "color": "#393939"
+ }
}
}
}
@@ -505,7 +505,7 @@
}
},
"notifications": {
- "width": 256,
+ "width": 380,
"margin": {
"right": 10,
"bottom": 10
@@ -1698,7 +1698,8 @@
"color": "#eee8d5",
"size": 12,
"margin": {
- "left": 4
+ "left": 8,
+ "right": 8
}
},
"header_height": 18,
@@ -1707,6 +1708,7 @@
"color": "#93a1a1",
"size": 12,
"margin": {
+ "left": 20,
"top": 6,
"bottom": 6
}
@@ -1720,6 +1722,9 @@
"corner_radius": 6,
"margin": {
"left": 6
+ },
+ "hover": {
+ "background": "#0736423d"
}
},
"dismiss_button": {
@@ -1727,7 +1732,10 @@
"icon_width": 8,
"icon_height": 8,
"button_width": 8,
- "button_height": 8
+ "button_height": 8,
+ "hover": {
+ "color": "#eee8d5"
+ }
}
}
}
@@ -505,7 +505,7 @@
}
},
"notifications": {
- "width": 256,
+ "width": 380,
"margin": {
"right": 10,
"bottom": 10
@@ -1698,7 +1698,8 @@
"color": "#073642",
"size": 12,
"margin": {
- "left": 4
+ "left": 8,
+ "right": 8
}
},
"header_height": 18,
@@ -1707,6 +1708,7 @@
"color": "#586e75",
"size": 12,
"margin": {
+ "left": 20,
"top": 6,
"bottom": 6
}
@@ -1720,6 +1722,9 @@
"corner_radius": 6,
"margin": {
"left": 6
+ },
+ "hover": {
+ "background": "#eee8d51f"
}
},
"dismiss_button": {
@@ -1727,7 +1732,10 @@
"icon_width": 8,
"icon_height": 8,
"button_width": 8,
- "button_height": 8
+ "button_height": 8,
+ "hover": {
+ "color": "#073642"
+ }
}
}
}
@@ -505,7 +505,7 @@
}
},
"notifications": {
- "width": 256,
+ "width": 380,
"margin": {
"right": 10,
"bottom": 10
@@ -1698,7 +1698,8 @@
"color": "#dfe2f1",
"size": 12,
"margin": {
- "left": 4
+ "left": 8,
+ "right": 8
}
},
"header_height": 18,
@@ -1707,6 +1708,7 @@
"color": "#979db4",
"size": 12,
"margin": {
+ "left": 20,
"top": 6,
"bottom": 6
}
@@ -1720,6 +1722,9 @@
"corner_radius": 6,
"margin": {
"left": 6
+ },
+ "hover": {
+ "background": "#2932563d"
}
},
"dismiss_button": {
@@ -1727,7 +1732,10 @@
"icon_width": 8,
"icon_height": 8,
"button_width": 8,
- "button_height": 8
+ "button_height": 8,
+ "hover": {
+ "color": "#dfe2f1"
+ }
}
}
}
@@ -505,7 +505,7 @@
}
},
"notifications": {
- "width": 256,
+ "width": 380,
"margin": {
"right": 10,
"bottom": 10
@@ -1698,7 +1698,8 @@
"color": "#293256",
"size": 12,
"margin": {
- "left": 4
+ "left": 8,
+ "right": 8
}
},
"header_height": 18,
@@ -1707,6 +1708,7 @@
"color": "#5e6687",
"size": 12,
"margin": {
+ "left": 20,
"top": 6,
"bottom": 6
}
@@ -1720,6 +1722,9 @@
"corner_radius": 6,
"margin": {
"left": 6
+ },
+ "hover": {
+ "background": "#dfe2f11f"
}
},
"dismiss_button": {
@@ -1727,7 +1732,10 @@
"icon_width": 8,
"icon_height": 8,
"button_width": 8,
- "button_height": 8
+ "button_height": 8,
+ "hover": {
+ "color": "#293256"
+ }
}
}
}
@@ -371,7 +371,7 @@ impl UserStore {
response: if accept {
proto::ContactRequestResponse::Accept
} else {
- proto::ContactRequestResponse::Reject
+ proto::ContactRequestResponse::Decline
} as i32,
},
cx,
@@ -118,7 +118,7 @@ impl PickerDelegate for ContactFinder {
"icons/accept.svg"
}
ContactRequestStatus::RequestSent | ContactRequestStatus::RequestAccepted => {
- "icons/reject.svg"
+ "icons/decline.svg"
}
};
let button_style = if self.user_store.read(cx).is_contact_request_pending(&user) {
@@ -6,6 +6,8 @@ use gpui::{
use settings::Settings;
use workspace::Notification;
+use crate::render_icon_button;
+
impl_internal_actions!(contact_notifications, [Dismiss, RespondToContactRequest]);
pub fn init(cx: &mut MutableAppContext) {
@@ -31,7 +33,7 @@ pub enum Event {
Dismiss,
}
-enum Reject {}
+enum Decline {}
enum Accept {}
impl Entity for ContactNotification {
@@ -87,7 +89,7 @@ impl ContactNotification {
let user_id = user.id;
Flex::column()
- .with_child(self.render_header("added you", theme, cx))
+ .with_child(self.render_header("wants to add you as a contact.", theme, cx))
.with_child(
Label::new(
"They won't know if you decline.".to_string(),
@@ -100,13 +102,14 @@ impl ContactNotification {
.with_child(
Flex::row()
.with_child(
- MouseEventHandler::new::<Reject, _, _>(
+ MouseEventHandler::new::<Decline, _, _>(
self.event.user.id as usize,
cx,
- |_, _| {
- Label::new("Reject".to_string(), theme.button.text.clone())
+ |state, _| {
+ let button = theme.button.style_for(state, false);
+ Label::new("Decline".to_string(), button.text.clone())
.contained()
- .with_style(theme.button.container)
+ .with_style(button.container)
.boxed()
},
)
@@ -120,10 +123,11 @@ impl ContactNotification {
.boxed(),
)
.with_child(
- MouseEventHandler::new::<Accept, _, _>(user.id as usize, cx, |_, _| {
- Label::new("Accept".to_string(), theme.button.text.clone())
+ MouseEventHandler::new::<Accept, _, _>(user.id as usize, cx, |state, _| {
+ let button = theme.button.style_for(state, false);
+ Label::new("Accept".to_string(), button.text.clone())
.contained()
- .with_style(theme.button.container)
+ .with_style(button.container)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
@@ -163,42 +167,51 @@ impl ContactNotification {
Image::new(avatar)
.with_style(theme.header_avatar)
.aligned()
- .left()
+ .constrained()
+ .with_height(
+ cx.font_cache()
+ .line_height(theme.header_message.text.font_size),
+ )
+ .aligned()
+ .top()
.boxed()
}))
.with_child(
- Label::new(
+ Text::new(
format!("{} {}", user.github_login, message),
theme.header_message.text.clone(),
)
.contained()
.with_style(theme.header_message.container)
.aligned()
+ .top()
+ .left()
+ .flex(1., true)
.boxed(),
)
.with_child(
- MouseEventHandler::new::<Dismiss, _, _>(user.id as usize, cx, |_, _| {
- Svg::new("icons/reject.svg")
- .with_color(theme.dismiss_button.color)
- .constrained()
- .with_width(theme.dismiss_button.icon_width)
- .aligned()
- .contained()
- .with_style(theme.dismiss_button.container)
- .constrained()
- .with_width(theme.dismiss_button.button_width)
- .with_height(theme.dismiss_button.button_width)
- .aligned()
- .boxed()
+ MouseEventHandler::new::<Dismiss, _, _>(user.id as usize, cx, |state, _| {
+ render_icon_button(
+ theme.dismiss_button.style_for(state, false),
+ "icons/decline.svg",
+ )
+ .boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
+ .with_padding(Padding::uniform(5.))
.on_click(move |_, cx| cx.dispatch_action(Dismiss(user_id)))
+ .aligned()
+ .constrained()
+ .with_height(
+ cx.font_cache()
+ .line_height(theme.header_message.text.font_size),
+ )
+ .aligned()
+ .top()
.flex_float()
.boxed(),
)
- .constrained()
- .with_height(theme.header_height)
- .boxed()
+ .named("contact notification header")
}
fn dismiss(&mut self, _: &Dismiss, cx: &mut ViewContext<Self>) {
@@ -344,7 +344,7 @@ impl ContactsPanel {
is_incoming: bool,
cx: &mut LayoutContext,
) -> ElementBox {
- enum Reject {}
+ enum Decline {}
enum Accept {}
enum Cancel {}
@@ -373,13 +373,13 @@ impl ContactsPanel {
if is_incoming {
row.add_children([
- MouseEventHandler::new::<Reject, _, _>(user.id as usize, cx, |mouse_state, _| {
+ MouseEventHandler::new::<Decline, _, _>(user.id as usize, cx, |mouse_state, _| {
let button_style = if is_contact_request_pending {
&theme.disabled_contact_button
} else {
&theme.contact_button.style_for(mouse_state, false)
};
- render_icon_button(button_style, "icons/reject.svg")
+ render_icon_button(button_style, "icons/decline.svg")
.aligned()
.flex_float()
.boxed()
@@ -421,7 +421,7 @@ impl ContactsPanel {
} else {
&theme.contact_button.style_for(mouse_state, false)
};
- render_icon_button(button_style, "icons/reject.svg")
+ render_icon_button(button_style, "icons/decline.svg")
.aligned()
.flex_float()
.boxed()
@@ -564,7 +564,7 @@ message RespondToContactRequest {
enum ContactRequestResponse {
Accept = 0;
- Reject = 1;
+ Decline = 1;
Block = 2;
Dismiss = 3;
}
@@ -362,8 +362,8 @@ pub struct ContactNotification {
pub header_message: ContainedText,
pub header_height: f32,
pub body_message: ContainedText,
- pub button: ContainedText,
- pub dismiss_button: IconButton,
+ pub button: Interactive<ContainedText>,
+ pub dismiss_button: Interactive<IconButton>,
}
#[derive(Clone, Deserialize, Default)]
@@ -1769,7 +1769,7 @@ impl Workspace {
.boxed()
}))
.constrained()
- .with_width(250.)
+ .with_width(theme.notifications.width)
.contained()
.with_style(theme.notifications.container)
.aligned()
@@ -1,21 +1,24 @@
import Theme from "../themes/theme";
import { backgroundColor, iconColor, text } from "./components";
+const avatarSize = 12;
+const headerPadding = 8;
+
export default function contactNotification(theme: Theme): Object {
return {
headerAvatar: {
- height: 12,
- width: 12,
+ height: avatarSize,
+ width: avatarSize,
cornerRadius: 6,
},
headerMessage: {
...text(theme, "sans", "primary", { size: "xs" }),
- margin: { left: 4 }
+ margin: { left: headerPadding, right: headerPadding }
},
headerHeight: 18,
bodyMessage: {
...text(theme, "sans", "secondary", { size: "xs" }),
- margin: { top: 6, bottom: 6 },
+ margin: { left: avatarSize + headerPadding, top: 6, bottom: 6 },
},
button: {
...text(theme, "sans", "primary", { size: "xs" }),
@@ -23,6 +26,9 @@ export default function contactNotification(theme: Theme): Object {
padding: 4,
cornerRadius: 6,
margin: { left: 6 },
+ hover: {
+ background: backgroundColor(theme, "on300", "hovered")
+ }
},
dismissButton: {
color: iconColor(theme, "secondary"),
@@ -30,6 +36,9 @@ export default function contactNotification(theme: Theme): Object {
iconHeight: 8,
buttonWidth: 8,
buttonHeight: 8,
+ hover: {
+ color: iconColor(theme, "primary")
+ }
}
}
}
@@ -159,7 +159,7 @@ export default function workspace(theme: Theme) {
shadow: shadow(theme),
},
notifications: {
- width: 256,
+ width: 380,
margin: { right: 10, bottom: 10 },
}
};