Structure the contact finder more similarly to the channel modal
Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
parent
b6f3dd51a0
commit
2bb9f7929d
10 changed files with 351 additions and 232 deletions
|
@ -7,7 +7,7 @@ use call::ActiveCall;
|
||||||
use client::{
|
use client::{
|
||||||
proto::PeerId, Channel, ChannelEvent, ChannelId, ChannelStore, Client, Contact, User, UserStore,
|
proto::PeerId, Channel, ChannelEvent, ChannelId, ChannelStore, Client, Contact, User, UserStore,
|
||||||
};
|
};
|
||||||
use contact_finder::build_contact_finder;
|
|
||||||
use context_menu::{ContextMenu, ContextMenuItem};
|
use context_menu::{ContextMenu, ContextMenuItem};
|
||||||
use db::kvp::KEY_VALUE_STORE;
|
use db::kvp::KEY_VALUE_STORE;
|
||||||
use editor::{Cancel, Editor};
|
use editor::{Cancel, Editor};
|
||||||
|
@ -46,6 +46,8 @@ use workspace::{
|
||||||
use crate::face_pile::FacePile;
|
use crate::face_pile::FacePile;
|
||||||
use channel_modal::ChannelModal;
|
use channel_modal::ChannelModal;
|
||||||
|
|
||||||
|
use self::contact_finder::ContactFinder;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
struct RemoveChannel {
|
struct RemoveChannel {
|
||||||
channel_id: u64,
|
channel_id: u64,
|
||||||
|
@ -1945,7 +1947,7 @@ impl CollabPanel {
|
||||||
workspace.update(cx, |workspace, cx| {
|
workspace.update(cx, |workspace, cx| {
|
||||||
workspace.toggle_modal(cx, |_, cx| {
|
workspace.toggle_modal(cx, |_, cx| {
|
||||||
cx.add_view(|cx| {
|
cx.add_view(|cx| {
|
||||||
let finder = build_contact_finder(self.user_store.clone(), cx);
|
let mut finder = ContactFinder::new(self.user_store.clone(), cx);
|
||||||
finder.set_query(self.filter_editor.read(cx).text(cx), cx);
|
finder.set_query(self.filter_editor.read(cx).text(cx), cx);
|
||||||
finder
|
finder
|
||||||
})
|
})
|
||||||
|
|
|
@ -66,7 +66,7 @@ impl ChannelModal {
|
||||||
},
|
},
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.with_theme(|theme| theme.collab_panel.channel_modal.picker.clone())
|
.with_theme(|theme| theme.collab_panel.tabbed_modal.picker.clone())
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.subscribe(&picker, |_, _, e, cx| cx.emit(*e)).detach();
|
cx.subscribe(&picker, |_, _, e, cx| cx.emit(*e)).detach();
|
||||||
|
@ -143,7 +143,7 @@ impl View for ChannelModal {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||||
let theme = &theme::current(cx).collab_panel.channel_modal;
|
let theme = &theme::current(cx).collab_panel.tabbed_modal;
|
||||||
|
|
||||||
let mode = self.picker.read(cx).delegate().mode;
|
let mode = self.picker.read(cx).delegate().mode;
|
||||||
let Some(channel) = self
|
let Some(channel) = self
|
||||||
|
@ -160,12 +160,12 @@ impl View for ChannelModal {
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
text: &'static str,
|
text: &'static str,
|
||||||
current_mode: Mode,
|
current_mode: Mode,
|
||||||
theme: &theme::ChannelModal,
|
theme: &theme::TabbedModal,
|
||||||
cx: &mut ViewContext<ChannelModal>,
|
cx: &mut ViewContext<ChannelModal>,
|
||||||
) -> AnyElement<ChannelModal> {
|
) -> AnyElement<ChannelModal> {
|
||||||
let active = mode == current_mode;
|
let active = mode == current_mode;
|
||||||
MouseEventHandler::<T, _>::new(0, cx, move |state, _| {
|
MouseEventHandler::<T, _>::new(0, cx, move |state, _| {
|
||||||
let contained_text = theme.mode_button.style_for(active, state);
|
let contained_text = theme.tab_button.style_for(active, state);
|
||||||
Label::new(text, contained_text.text.clone())
|
Label::new(text, contained_text.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(contained_text.container.clone())
|
.with_style(contained_text.container.clone())
|
||||||
|
@ -367,11 +367,17 @@ impl PickerDelegate for ChannelModalDelegate {
|
||||||
selected: bool,
|
selected: bool,
|
||||||
cx: &gpui::AppContext,
|
cx: &gpui::AppContext,
|
||||||
) -> AnyElement<Picker<Self>> {
|
) -> AnyElement<Picker<Self>> {
|
||||||
let theme = &theme::current(cx).collab_panel.channel_modal;
|
let full_theme = &theme::current(cx);
|
||||||
|
let theme = &full_theme.collab_panel.channel_modal;
|
||||||
|
let tabbed_modal = &full_theme.collab_panel.tabbed_modal;
|
||||||
let (user, admin) = self.user_at_index(ix).unwrap();
|
let (user, admin) = self.user_at_index(ix).unwrap();
|
||||||
let request_status = self.member_status(user.id, cx);
|
let request_status = self.member_status(user.id, cx);
|
||||||
|
|
||||||
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
let style = tabbed_modal
|
||||||
|
.picker
|
||||||
|
.item
|
||||||
|
.in_state(selected)
|
||||||
|
.style_for(mouse_state);
|
||||||
|
|
||||||
let in_manage = matches!(self.mode, Mode::ManageMembers);
|
let in_manage = matches!(self.mode, Mode::ManageMembers);
|
||||||
|
|
||||||
|
@ -448,7 +454,7 @@ impl PickerDelegate for ChannelModalDelegate {
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
.constrained()
|
.constrained()
|
||||||
.with_height(theme.row_height)
|
.with_height(tabbed_modal.row_height)
|
||||||
.into_any();
|
.into_any();
|
||||||
|
|
||||||
if selected {
|
if selected {
|
||||||
|
|
|
@ -1,28 +1,127 @@
|
||||||
use client::{ContactRequestStatus, User, UserStore};
|
use client::{ContactRequestStatus, User, UserStore};
|
||||||
use gpui::{elements::*, AppContext, ModelHandle, MouseState, Task, ViewContext};
|
use gpui::{
|
||||||
|
elements::*, AppContext, Entity, ModelHandle, MouseState, Task, View, ViewContext, ViewHandle,
|
||||||
|
};
|
||||||
use picker::{Picker, PickerDelegate, PickerEvent};
|
use picker::{Picker, PickerDelegate, PickerEvent};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use util::TryFutureExt;
|
use util::TryFutureExt;
|
||||||
|
use workspace::Modal;
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
Picker::<ContactFinderDelegate>::init(cx);
|
Picker::<ContactFinderDelegate>::init(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ContactFinder = Picker<ContactFinderDelegate>;
|
pub struct ContactFinder {
|
||||||
|
picker: ViewHandle<Picker<ContactFinderDelegate>>,
|
||||||
|
has_focus: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build_contact_finder(
|
impl ContactFinder {
|
||||||
user_store: ModelHandle<UserStore>,
|
pub fn new(user_store: ModelHandle<UserStore>, cx: &mut ViewContext<Self>) -> Self {
|
||||||
cx: &mut ViewContext<ContactFinder>,
|
let picker = cx.add_view(|cx| {
|
||||||
) -> ContactFinder {
|
Picker::new(
|
||||||
Picker::new(
|
ContactFinderDelegate {
|
||||||
ContactFinderDelegate {
|
user_store,
|
||||||
user_store,
|
potential_contacts: Arc::from([]),
|
||||||
potential_contacts: Arc::from([]),
|
selected_index: 0,
|
||||||
selected_index: 0,
|
},
|
||||||
},
|
cx,
|
||||||
cx,
|
)
|
||||||
)
|
.with_theme(|theme| theme.collab_panel.tabbed_modal.picker.clone())
|
||||||
.with_theme(|theme| theme.picker.clone())
|
});
|
||||||
|
|
||||||
|
cx.subscribe(&picker, |_, _, e, cx| cx.emit(*e)).detach();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
picker,
|
||||||
|
has_focus: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_query(&mut self, query: String, cx: &mut ViewContext<Self>) {
|
||||||
|
self.picker.update(cx, |picker, cx| {
|
||||||
|
picker.set_query(query, cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entity for ContactFinder {
|
||||||
|
type Event = PickerEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl View for ContactFinder {
|
||||||
|
fn ui_name() -> &'static str {
|
||||||
|
"ContactFinder"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||||
|
let full_theme = &theme::current(cx);
|
||||||
|
let theme = &full_theme.collab_panel.tabbed_modal;
|
||||||
|
|
||||||
|
fn render_mode_button(
|
||||||
|
text: &'static str,
|
||||||
|
theme: &theme::TabbedModal,
|
||||||
|
_cx: &mut ViewContext<ContactFinder>,
|
||||||
|
) -> AnyElement<ContactFinder> {
|
||||||
|
let contained_text = &theme.tab_button.active_state().default;
|
||||||
|
Label::new(text, contained_text.text.clone())
|
||||||
|
.contained()
|
||||||
|
.with_style(contained_text.container.clone())
|
||||||
|
.into_any()
|
||||||
|
}
|
||||||
|
|
||||||
|
Flex::column()
|
||||||
|
.with_child(
|
||||||
|
Flex::column()
|
||||||
|
.with_child(
|
||||||
|
Label::new("Contacts", theme.title.text.clone())
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.title.container.clone()),
|
||||||
|
)
|
||||||
|
.with_child(Flex::row().with_children([render_mode_button(
|
||||||
|
"Invite new contacts",
|
||||||
|
&theme,
|
||||||
|
cx,
|
||||||
|
)]))
|
||||||
|
.expanded()
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.header),
|
||||||
|
)
|
||||||
|
.with_child(
|
||||||
|
ChildView::new(&self.picker, cx)
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.body),
|
||||||
|
)
|
||||||
|
.constrained()
|
||||||
|
.with_max_height(theme.max_height)
|
||||||
|
.with_max_width(theme.max_width)
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.modal)
|
||||||
|
.into_any()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
self.has_focus = true;
|
||||||
|
if cx.is_self_focused() {
|
||||||
|
cx.focus(&self.picker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn focus_out(&mut self, _: gpui::AnyViewHandle, _: &mut ViewContext<Self>) {
|
||||||
|
self.has_focus = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Modal for ContactFinder {
|
||||||
|
fn has_focus(&self) -> bool {
|
||||||
|
self.has_focus
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dismiss_on_event(event: &Self::Event) -> bool {
|
||||||
|
match event {
|
||||||
|
PickerEvent::Dismiss => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ContactFinderDelegate {
|
pub struct ContactFinderDelegate {
|
||||||
|
@ -97,7 +196,9 @@ impl PickerDelegate for ContactFinderDelegate {
|
||||||
selected: bool,
|
selected: bool,
|
||||||
cx: &gpui::AppContext,
|
cx: &gpui::AppContext,
|
||||||
) -> AnyElement<Picker<Self>> {
|
) -> AnyElement<Picker<Self>> {
|
||||||
let theme = &theme::current(cx).contact_finder;
|
let full_theme = &theme::current(cx);
|
||||||
|
let theme = &full_theme.collab_panel.contact_finder;
|
||||||
|
let tabbed_modal = &full_theme.collab_panel.tabbed_modal;
|
||||||
let user = &self.potential_contacts[ix];
|
let user = &self.potential_contacts[ix];
|
||||||
let request_status = self.user_store.read(cx).contact_request_status(user);
|
let request_status = self.user_store.read(cx).contact_request_status(user);
|
||||||
|
|
||||||
|
@ -113,7 +214,11 @@ impl PickerDelegate for ContactFinderDelegate {
|
||||||
} else {
|
} else {
|
||||||
&theme.contact_button
|
&theme.contact_button
|
||||||
};
|
};
|
||||||
let style = theme.picker.item.in_state(selected).style_for(mouse_state);
|
let style = tabbed_modal
|
||||||
|
.picker
|
||||||
|
.item
|
||||||
|
.in_state(selected)
|
||||||
|
.style_for(mouse_state);
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_children(user.avatar.clone().map(|avatar| {
|
.with_children(user.avatar.clone().map(|avatar| {
|
||||||
Image::from_data(avatar)
|
Image::from_data(avatar)
|
||||||
|
@ -145,7 +250,7 @@ impl PickerDelegate for ContactFinderDelegate {
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
.constrained()
|
.constrained()
|
||||||
.with_height(theme.row_height)
|
.with_height(tabbed_modal.row_height)
|
||||||
.into_any()
|
.into_any()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,6 @@ pub struct Theme {
|
||||||
pub collab_panel: CollabPanel,
|
pub collab_panel: CollabPanel,
|
||||||
pub project_panel: ProjectPanel,
|
pub project_panel: ProjectPanel,
|
||||||
pub command_palette: CommandPalette,
|
pub command_palette: CommandPalette,
|
||||||
pub contact_finder: ContactFinder,
|
|
||||||
pub picker: Picker,
|
pub picker: Picker,
|
||||||
pub editor: Editor,
|
pub editor: Editor,
|
||||||
pub search: Search,
|
pub search: Search,
|
||||||
|
@ -224,6 +223,8 @@ pub struct CollabPanel {
|
||||||
pub log_in_button: Interactive<ContainedText>,
|
pub log_in_button: Interactive<ContainedText>,
|
||||||
pub channel_editor: ContainerStyle,
|
pub channel_editor: ContainerStyle,
|
||||||
pub channel_hash: Icon,
|
pub channel_hash: Icon,
|
||||||
|
pub tabbed_modal: TabbedModal,
|
||||||
|
pub contact_finder: ContactFinder,
|
||||||
pub channel_modal: ChannelModal,
|
pub channel_modal: ChannelModal,
|
||||||
pub user_query_editor: FieldEditor,
|
pub user_query_editor: FieldEditor,
|
||||||
pub user_query_editor_height: f32,
|
pub user_query_editor_height: f32,
|
||||||
|
@ -251,13 +252,20 @@ pub struct CollabPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, JsonSchema)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct ChannelModal {
|
pub struct TabbedModal {
|
||||||
|
pub tab_button: Toggleable<Interactive<ContainedText>>,
|
||||||
|
pub modal: ContainerStyle,
|
||||||
|
pub header: ContainerStyle,
|
||||||
|
pub body: ContainerStyle,
|
||||||
|
pub title: ContainedText,
|
||||||
|
pub picker: Picker,
|
||||||
pub max_height: f32,
|
pub max_height: f32,
|
||||||
pub max_width: f32,
|
pub max_width: f32,
|
||||||
pub title: ContainedText,
|
|
||||||
pub mode_button: Toggleable<Interactive<ContainedText>>,
|
|
||||||
pub picker: Picker,
|
|
||||||
pub row_height: f32,
|
pub row_height: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
|
pub struct ChannelModal {
|
||||||
pub contact_avatar: ImageStyle,
|
pub contact_avatar: ImageStyle,
|
||||||
pub contact_username: ContainerStyle,
|
pub contact_username: ContainerStyle,
|
||||||
pub remove_member_button: ContainedText,
|
pub remove_member_button: ContainedText,
|
||||||
|
@ -265,9 +273,6 @@ pub struct ChannelModal {
|
||||||
pub member_icon: Icon,
|
pub member_icon: Icon,
|
||||||
pub invitee_icon: Icon,
|
pub invitee_icon: Icon,
|
||||||
pub member_tag: ContainedText,
|
pub member_tag: ContainedText,
|
||||||
pub modal: ContainerStyle,
|
|
||||||
pub header: ContainerStyle,
|
|
||||||
pub body: ContainerStyle,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, JsonSchema)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
|
@ -286,8 +291,6 @@ pub struct TreeBranch {
|
||||||
|
|
||||||
#[derive(Deserialize, Default, JsonSchema)]
|
#[derive(Deserialize, Default, JsonSchema)]
|
||||||
pub struct ContactFinder {
|
pub struct ContactFinder {
|
||||||
pub picker: Picker,
|
|
||||||
pub row_height: f32,
|
|
||||||
pub contact_avatar: ImageStyle,
|
pub contact_avatar: ImageStyle,
|
||||||
pub contact_username: ContainerStyle,
|
pub contact_username: ContainerStyle,
|
||||||
pub contact_button: IconButton,
|
pub contact_button: IconButton,
|
||||||
|
|
|
@ -256,7 +256,7 @@ impl PickerDelegate for BranchListDelegate {
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
.constrained()
|
.constrained()
|
||||||
.with_height(theme.contact_finder.row_height)
|
.with_height(theme.collab_panel.tabbed_modal.row_height)
|
||||||
.into_any()
|
.into_any()
|
||||||
}
|
}
|
||||||
fn render_header(
|
fn render_header(
|
||||||
|
|
|
@ -46,7 +46,6 @@ export default function app(): any {
|
||||||
project_diagnostics: project_diagnostics(),
|
project_diagnostics: project_diagnostics(),
|
||||||
project_panel: project_panel(),
|
project_panel: project_panel(),
|
||||||
collab_panel: collab_panel(),
|
collab_panel: collab_panel(),
|
||||||
contact_finder: contact_finder(),
|
|
||||||
toolbar_dropdown_menu: toolbar_dropdown_menu(),
|
toolbar_dropdown_menu: toolbar_dropdown_menu(),
|
||||||
search: search(),
|
search: search(),
|
||||||
shared_screen: shared_screen(),
|
shared_screen: shared_screen(),
|
||||||
|
|
|
@ -1,153 +0,0 @@
|
||||||
import { useTheme } from "../theme"
|
|
||||||
import { background, border, foreground, text } from "./components"
|
|
||||||
import picker from "./picker"
|
|
||||||
import { input } from "../component/input"
|
|
||||||
import { toggleable_text_button } from "../component/text_button"
|
|
||||||
|
|
||||||
export default function channel_modal(): any {
|
|
||||||
const theme = useTheme()
|
|
||||||
|
|
||||||
const side_margin = 6
|
|
||||||
const contact_button = {
|
|
||||||
background: background(theme.middle, "variant"),
|
|
||||||
color: foreground(theme.middle, "variant"),
|
|
||||||
icon_width: 8,
|
|
||||||
button_width: 16,
|
|
||||||
corner_radius: 8,
|
|
||||||
}
|
|
||||||
|
|
||||||
const picker_style = picker()
|
|
||||||
delete picker_style.shadow
|
|
||||||
delete picker_style.border
|
|
||||||
|
|
||||||
const picker_input = input()
|
|
||||||
|
|
||||||
return {
|
|
||||||
header: {
|
|
||||||
background: background(theme.middle, "accent"),
|
|
||||||
border: border(theme.middle, { "bottom": true, "top": false, left: false, right: false }),
|
|
||||||
corner_radii: {
|
|
||||||
top_right: 12,
|
|
||||||
top_left: 12,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
background: background(theme.middle),
|
|
||||||
corner_radii: {
|
|
||||||
bottom_right: 12,
|
|
||||||
bottom_left: 12,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modal: {
|
|
||||||
background: background(theme.middle),
|
|
||||||
shadow: theme.modal_shadow,
|
|
||||||
corner_radius: 12,
|
|
||||||
padding: {
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
top: 0,
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
// This is used for the icons that are rendered to the right of channel Members in both UIs
|
|
||||||
member_icon: {
|
|
||||||
background: background(theme.middle),
|
|
||||||
padding: {
|
|
||||||
bottom: 4,
|
|
||||||
left: 4,
|
|
||||||
right: 4,
|
|
||||||
top: 4,
|
|
||||||
},
|
|
||||||
width: 5,
|
|
||||||
color: foreground(theme.middle, "accent"),
|
|
||||||
},
|
|
||||||
// This is used for the icons that are rendered to the right of channel invites in both UIs
|
|
||||||
invitee_icon: {
|
|
||||||
background: background(theme.middle),
|
|
||||||
padding: {
|
|
||||||
bottom: 4,
|
|
||||||
left: 4,
|
|
||||||
right: 4,
|
|
||||||
top: 4,
|
|
||||||
},
|
|
||||||
width: 5,
|
|
||||||
color: foreground(theme.middle, "accent"),
|
|
||||||
},
|
|
||||||
remove_member_button: {
|
|
||||||
...text(theme.middle, "sans", { size: "xs" }),
|
|
||||||
background: background(theme.middle),
|
|
||||||
padding: {
|
|
||||||
left: 7,
|
|
||||||
right: 7
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cancel_invite_button: {
|
|
||||||
...text(theme.middle, "sans", { size: "xs" }),
|
|
||||||
background: background(theme.middle),
|
|
||||||
},
|
|
||||||
member_tag: {
|
|
||||||
...text(theme.middle, "sans", { size: "xs" }),
|
|
||||||
border: border(theme.middle, "active"),
|
|
||||||
background: background(theme.middle),
|
|
||||||
margin: {
|
|
||||||
left: 8,
|
|
||||||
},
|
|
||||||
padding: {
|
|
||||||
left: 4,
|
|
||||||
right: 4,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
max_height: 400,
|
|
||||||
max_width: 540,
|
|
||||||
title: {
|
|
||||||
...text(theme.middle, "sans", "on", { size: "lg" }),
|
|
||||||
padding: {
|
|
||||||
left: 6,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mode_button: toggleable_text_button(theme, {
|
|
||||||
variant: "ghost",
|
|
||||||
layer: theme.middle,
|
|
||||||
active_color: "accent",
|
|
||||||
margin: {
|
|
||||||
top: 8,
|
|
||||||
bottom: 8,
|
|
||||||
right: 4
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
picker: {
|
|
||||||
empty_container: {},
|
|
||||||
item: {
|
|
||||||
...picker_style.item,
|
|
||||||
margin: { left: side_margin, right: side_margin },
|
|
||||||
},
|
|
||||||
no_matches: picker_style.no_matches,
|
|
||||||
input_editor: picker_input,
|
|
||||||
empty_input_editor: picker_input,
|
|
||||||
header: picker_style.header,
|
|
||||||
footer: picker_style.footer,
|
|
||||||
},
|
|
||||||
row_height: 28,
|
|
||||||
contact_avatar: {
|
|
||||||
corner_radius: 10,
|
|
||||||
width: 18,
|
|
||||||
},
|
|
||||||
contact_username: {
|
|
||||||
padding: {
|
|
||||||
left: 8,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
contact_button: {
|
|
||||||
...contact_button,
|
|
||||||
hover: {
|
|
||||||
background: background(theme.middle, "variant", "hovered"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
disabled_contact_button: {
|
|
||||||
...contact_button,
|
|
||||||
background: background(theme.middle, "disabled"),
|
|
||||||
color: foreground(theme.middle, "disabled"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
159
styles/src/style_tree/collab_modals.ts
Normal file
159
styles/src/style_tree/collab_modals.ts
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
import { useTheme } from "../theme"
|
||||||
|
import { background, border, foreground, text } from "./components"
|
||||||
|
import picker from "./picker"
|
||||||
|
import { input } from "../component/input"
|
||||||
|
import { toggleable_text_button } from "../component/text_button"
|
||||||
|
import contact_finder from "./contact_finder"
|
||||||
|
|
||||||
|
export default function channel_modal(): any {
|
||||||
|
const theme = useTheme()
|
||||||
|
|
||||||
|
const side_margin = 6
|
||||||
|
const contact_button = {
|
||||||
|
background: background(theme.middle, "variant"),
|
||||||
|
color: foreground(theme.middle, "variant"),
|
||||||
|
icon_width: 8,
|
||||||
|
button_width: 16,
|
||||||
|
corner_radius: 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
const picker_style = picker()
|
||||||
|
delete picker_style.shadow
|
||||||
|
delete picker_style.border
|
||||||
|
|
||||||
|
const picker_input = input()
|
||||||
|
|
||||||
|
return {
|
||||||
|
contact_finder: contact_finder(),
|
||||||
|
tabbed_modal: {
|
||||||
|
tab_button: toggleable_text_button(theme, {
|
||||||
|
variant: "ghost",
|
||||||
|
layer: theme.middle,
|
||||||
|
active_color: "accent",
|
||||||
|
margin: {
|
||||||
|
top: 8,
|
||||||
|
bottom: 8,
|
||||||
|
right: 4
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
row_height: 28,
|
||||||
|
header: {
|
||||||
|
background: background(theme.middle, "accent"),
|
||||||
|
border: border(theme.middle, { "bottom": true, "top": false, left: false, right: false }),
|
||||||
|
corner_radii: {
|
||||||
|
top_right: 12,
|
||||||
|
top_left: 12,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
background: background(theme.middle),
|
||||||
|
corner_radii: {
|
||||||
|
bottom_right: 12,
|
||||||
|
bottom_left: 12,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modal: {
|
||||||
|
background: background(theme.middle),
|
||||||
|
shadow: theme.modal_shadow,
|
||||||
|
corner_radius: 12,
|
||||||
|
padding: {
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
top: 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
max_height: 400,
|
||||||
|
max_width: 540,
|
||||||
|
title: {
|
||||||
|
...text(theme.middle, "sans", "on", { size: "lg" }),
|
||||||
|
padding: {
|
||||||
|
left: 6,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
picker: {
|
||||||
|
empty_container: {},
|
||||||
|
item: {
|
||||||
|
...picker_style.item,
|
||||||
|
margin: { left: side_margin, right: side_margin },
|
||||||
|
},
|
||||||
|
no_matches: picker_style.no_matches,
|
||||||
|
input_editor: picker_input,
|
||||||
|
empty_input_editor: picker_input,
|
||||||
|
header: picker_style.header,
|
||||||
|
footer: picker_style.footer,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
channel_modal: {
|
||||||
|
// This is used for the icons that are rendered to the right of channel Members in both UIs
|
||||||
|
member_icon: {
|
||||||
|
background: background(theme.middle),
|
||||||
|
padding: {
|
||||||
|
bottom: 4,
|
||||||
|
left: 4,
|
||||||
|
right: 4,
|
||||||
|
top: 4,
|
||||||
|
},
|
||||||
|
width: 5,
|
||||||
|
color: foreground(theme.middle, "accent"),
|
||||||
|
},
|
||||||
|
// This is used for the icons that are rendered to the right of channel invites in both UIs
|
||||||
|
invitee_icon: {
|
||||||
|
background: background(theme.middle),
|
||||||
|
padding: {
|
||||||
|
bottom: 4,
|
||||||
|
left: 4,
|
||||||
|
right: 4,
|
||||||
|
top: 4,
|
||||||
|
},
|
||||||
|
width: 5,
|
||||||
|
color: foreground(theme.middle, "accent"),
|
||||||
|
},
|
||||||
|
remove_member_button: {
|
||||||
|
...text(theme.middle, "sans", { size: "xs" }),
|
||||||
|
background: background(theme.middle),
|
||||||
|
padding: {
|
||||||
|
left: 7,
|
||||||
|
right: 7
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancel_invite_button: {
|
||||||
|
...text(theme.middle, "sans", { size: "xs" }),
|
||||||
|
background: background(theme.middle),
|
||||||
|
},
|
||||||
|
member_tag: {
|
||||||
|
...text(theme.middle, "sans", { size: "xs" }),
|
||||||
|
border: border(theme.middle, "active"),
|
||||||
|
background: background(theme.middle),
|
||||||
|
margin: {
|
||||||
|
left: 8,
|
||||||
|
},
|
||||||
|
padding: {
|
||||||
|
left: 4,
|
||||||
|
right: 4,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
contact_avatar: {
|
||||||
|
corner_radius: 10,
|
||||||
|
width: 18,
|
||||||
|
},
|
||||||
|
contact_username: {
|
||||||
|
padding: {
|
||||||
|
left: 8,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
contact_button: {
|
||||||
|
...contact_button,
|
||||||
|
hover: {
|
||||||
|
background: background(theme.middle, "variant", "hovered"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
disabled_contact_button: {
|
||||||
|
...contact_button,
|
||||||
|
background: background(theme.middle, "disabled"),
|
||||||
|
color: foreground(theme.middle, "disabled"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,9 +7,7 @@ import {
|
||||||
} from "./components"
|
} from "./components"
|
||||||
import { interactive, toggleable } from "../element"
|
import { interactive, toggleable } from "../element"
|
||||||
import { useTheme } from "../theme"
|
import { useTheme } from "../theme"
|
||||||
import channel_modal from "./channel_modal"
|
import collab_modals from "./collab_modals"
|
||||||
import { icon_button, toggleable_icon_button } from "../component/icon_button"
|
|
||||||
|
|
||||||
|
|
||||||
export default function contacts_panel(): any {
|
export default function contacts_panel(): any {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
@ -109,7 +107,7 @@ export default function contacts_panel(): any {
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
channel_modal: channel_modal(),
|
...collab_modals(),
|
||||||
log_in_button: interactive({
|
log_in_button: interactive({
|
||||||
base: {
|
base: {
|
||||||
background: background(theme.middle),
|
background: background(theme.middle),
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import picker from "./picker"
|
// import picker from "./picker"
|
||||||
import { background, border, foreground, text } from "./components"
|
import { background, border, foreground, text } from "./components"
|
||||||
import { useTheme } from "../theme"
|
import { useTheme } from "../theme"
|
||||||
|
|
||||||
export default function contact_finder(): any {
|
export default function contact_finder(): any {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
|
||||||
const side_margin = 6
|
// const side_margin = 6
|
||||||
const contact_button = {
|
const contact_button = {
|
||||||
background: background(theme.middle, "variant"),
|
background: background(theme.middle, "variant"),
|
||||||
color: foreground(theme.middle, "variant"),
|
color: foreground(theme.middle, "variant"),
|
||||||
|
@ -14,42 +14,42 @@ export default function contact_finder(): any {
|
||||||
corner_radius: 8,
|
corner_radius: 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
const picker_style = picker()
|
// const picker_style = picker()
|
||||||
const picker_input = {
|
// const picker_input = {
|
||||||
background: background(theme.middle, "on"),
|
// background: background(theme.middle, "on"),
|
||||||
corner_radius: 6,
|
// corner_radius: 6,
|
||||||
text: text(theme.middle, "mono"),
|
// text: text(theme.middle, "mono"),
|
||||||
placeholder_text: text(theme.middle, "mono", "on", "disabled", {
|
// placeholder_text: text(theme.middle, "mono", "on", "disabled", {
|
||||||
size: "xs",
|
// size: "xs",
|
||||||
}),
|
// }),
|
||||||
selection: theme.players[0],
|
// selection: theme.players[0],
|
||||||
border: border(theme.middle),
|
// border: border(theme.middle),
|
||||||
padding: {
|
// padding: {
|
||||||
bottom: 4,
|
// bottom: 4,
|
||||||
left: 8,
|
// left: 8,
|
||||||
right: 8,
|
// right: 8,
|
||||||
top: 4,
|
// top: 4,
|
||||||
},
|
// },
|
||||||
margin: {
|
// margin: {
|
||||||
left: side_margin,
|
// left: side_margin,
|
||||||
right: side_margin,
|
// right: side_margin,
|
||||||
},
|
// },
|
||||||
}
|
// }
|
||||||
|
|
||||||
return {
|
return {
|
||||||
picker: {
|
// picker: {
|
||||||
empty_container: {},
|
// empty_container: {},
|
||||||
item: {
|
// item: {
|
||||||
...picker_style.item,
|
// ...picker_style.item,
|
||||||
margin: { left: side_margin, right: side_margin },
|
// margin: { left: side_margin, right: side_margin },
|
||||||
},
|
// },
|
||||||
no_matches: picker_style.no_matches,
|
// no_matches: picker_style.no_matches,
|
||||||
input_editor: picker_input,
|
// input_editor: picker_input,
|
||||||
empty_input_editor: picker_input,
|
// empty_input_editor: picker_input,
|
||||||
header: picker_style.header,
|
// header: picker_style.header,
|
||||||
footer: picker_style.footer,
|
// footer: picker_style.footer,
|
||||||
},
|
// },
|
||||||
row_height: 28,
|
// row_height: 28,
|
||||||
contact_avatar: {
|
contact_avatar: {
|
||||||
corner_radius: 10,
|
corner_radius: 10,
|
||||||
width: 18,
|
width: 18,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue