Skip to main content

gpui-patterns

Common UI patterns and advanced techniques for GPUI applications. Use when implementing modals, lists, forms, state sharing, or complex component compositions.

معلومات المصدر

المستودع
zerx-lab/rmx
آخر نشاط في المصدر
٥ فبراير ٢٠٢٦ في ٠٩:٤٩
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٧٠
التفرعات
٢

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
gpui-patterns
description
Common UI patterns and advanced techniques for GPUI applications. Use when implementing modals, lists, forms, state sharing, or complex component compositions.
# GPUI Patterns This skill provides common UI patterns and advanced techniques for GPUI applications. ## Modal/Overlay Pattern ### Basic Modal ```rust use gpui::*; struct Modal { is_open: bool, content: SharedString, } impl Render for Modal { fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement { div() .when(self.is_open, |this| { this.absolute() .inset_0() .flex() .items_center() .justify_center() .bg(rgba(0, 0, 0, 0.5)) .on_click(cx.listener(|this, _event, _window, cx| { this.close(cx); })) .child( div() .p_6() .bg(rgb(0x1a1a1a)) .rounded_lg() .min_w(px(300.0)) .child(self.content.clone()) ) }) } } impl Modal { fn open(&mut self, content: impl Into<SharedString>, cx: &mut Context<Self>) { self.is_open = true; self.content = content.into(); cx.notify(); } fn close(&mut self, cx: &mut Context<Self>) { self.is_open = false; cx.notify(); } } ``` ## List Pattern ### Dynamic List Rendering ```rust struct ListView { items: Vec<String>, } impl Render for ListView { fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement { div() .v_flex() .gap_2() .children( self.items.iter().enumerate().map(|(index, item)| { self.render_item(index, item, cx) }) ) } } impl ListView { fn render_item( &self, index: usize, item: &str, cx: &Context<Self>, ) -> impl IntoElement { div() .p_3() .bg(rgb(0x1a1a1a)) .rounded(px(4.0)) .flex() .justify_between() .child(format!("{}. {}", index + 1, item)) .child( div() .px_3() .py_1() .bg(rgb(0xef4444)) .rounded(px(4.0)) .cursor_pointer() .child("Delete") .on_click(cx.listener(move |this, _event, _window, cx| { this.remove_item(index, cx); })) ) } fn remove_item(&mut self, index: usize, cx: &mut Context<Self>) { if index < self.items.len() { self.items.remove(index); cx.notify(); } } } ``` ## Form Pattern ### Form with Validation ```rust struct LoginForm { username: SharedString, password: SharedString, error: Option<SharedString>, } impl Render for LoginForm { fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement { div() .v_flex() .gap_4() .p_6() .when_some(self.error.clone(), |this, error| { this.child( div() .p_3() .bg(rgb(0xef4444)) .rounded(px(4.0)) .child(error) ) }) .child(self.render_input("Username", &self.username, cx)) .child(self.render_input("Password", &self.password, cx)) .child( div() .px_6() .py_3() .bg(rgb(0x3b82f6)) .rounded(px(6.0)) .cursor_pointer() .child("Login") .on_click(cx.listener(|this, _event, _window, cx| { this.submit(cx); })) ) } } impl LoginForm { fn render_input( &self, label: &str, value: &SharedString, _cx: &Context<Self>, ) -> impl IntoElement { div() .v_flex() .gap_1() .child( div().text_sm().child(label) ) .child( div() .w_full() .px_3() .py_2() .bg(rgb(0x1a1a1a)) .border_1() .border_color(rgb(0x4a4a4a)) .rounded(px(4.0)) .child(value.clone()) ) } fn submit(&mut self, cx: &mut Context<Self>) { if self.username.is_empty() || self.password.is_empty() { self.error = Some("Please fill in all fields".into()); cx.notify(); return; } self.error = None; // Handle login... } } ``` ## Global State Pattern ### Shared Application State ```rust #[derive(Clone)] struct AppState { user: Option<String>, theme: String, } // Set global state fn init_app_state(cx: &mut App) { let state = AppState { user: None, theme: "dark".to_string(), }; cx.set_global(state); } // Access global state fn use_app_state(cx: &App) -> AppState { cx.global::<AppState>().clone() } // Update global state fn set_user(cx: &mut App, user: String) { let mut state = cx.global::<AppState>().clone(); state.user = Some(user); cx.set_global(state); } ``` ## Parent-Child Communication ### Child Notifying Parent ```rust #[derive(Clone, Debug)] enum ChildEvent { ValueChanged(i32), } impl EventEmitter<ChildEvent> for Child {} struct Parent { child: Entity<Child>, _subscription: Subscription, } impl Parent { fn new(cx: &mut Context<Self>) -> Self { let child = cx.new(|_| Child::new()); let subscription = cx.subscribe(&child, |this, _child, event, cx| { match event { ChildEvent::ValueChanged(value) => { println!("Child value changed to: {}", value); cx.notify(); } } }); Self { child, _subscription: subscription, } } } struct Child { value: i32, } impl Child { fn new() -> Self { Self { value: 0 } } fn set_value(&mut self, value: i32, cx: &mut Context<Self>) { self.value = value; cx.emit(ChildEvent::ValueChanged(value)); cx.notify(); } } ``` ## Tab Navigation ### Tab View Pattern ```rust #[derive(Clone, Copy, PartialEq)] enum Tab { Home, Settings, Profile, } struct TabView { active_tab: Tab, } impl Render for TabView { fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement { div() .v_flex() .size_full() .child(self.render_tabs(cx)) .child(self.render_content()) } } impl TabView { fn render_tabs(&self, cx: &Context<Self>) -> impl IntoElement { div() .h_flex() .gap_2() .p_2() .bg(rgb(0x1a1a1a)) .child(self.render_tab("Home", Tab::Home, cx)) .child(self.render_tab("Settings", Tab::Settings, cx)) .child(self.render_tab("Profile", Tab::Profile, cx)) } fn render_tab(&self, label: &str, tab: Tab, cx: &Context<Self>) -> impl IntoElement { let is_active = self.active_tab == tab; div() .px_4() .py_2() .rounded(px(4.0)) .cursor_pointer() .bg(if is_active { rgb(0x3b82f6) } else { rgb(0x2a2a2a) }) .child(label) .on_click(cx.listener(move |this, _event, _window, cx| { this.active_tab = tab; cx.notify(); })) } fn render_content(&self) -> impl IntoElement { match self.active_tab { Tab::Home => div().child("Home Content"), Tab::Settings => div().child("Settings Content"), Tab::Profile => div().child("Profile Content"), } } } ``` ## Loading State Pattern ### Async Data Loading ```rust enum LoadState<T> { Idle, Loading, Loaded(T), Error(String), } struct DataView { state: LoadState<Vec<String>>, } impl Render for DataView { fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement { match &self.state { LoadState::Idle => { div().child("Click to load") .on_click(cx.listener(|this, _event, _window, cx| { this.load_data(cx); })) } LoadState::Loading => { div().child("Loading...") } LoadState::Loaded(items) => { div() .v_flex() .gap_2() .children(items.iter().map(|item| { div().child(item.clone()) })) } LoadState::Error(error) => { div() .p_3() .bg(rgb(0xef4444)) .child(format!("Error: {}", error)) } } } } impl DataView { fn load_data(&mut self, cx: &mut Context<Self>) { self.state = LoadState::Loading; cx.notify(); cx.spawn(async move |this, cx| { match fetch_data().await { Ok(data) => { this.update(&mut *cx, |view, cx| { view.state = LoadState::Loaded(data); cx.notify(); })?; } Err(e) => { this.update(&mut *cx, |view, cx| { view.state = LoadState::Error(e.to_string()); cx.notify(); })?; } } Ok(()) }).detach(); } } async fn fetch_data() -> Result<Vec<String>, anyhow::Error> { // Simulate API call tokio::time::sleep(Duration::from_secs(1)).await; Ok(vec!["Item 1".to_string(), "Item 2".to_string()]) } ``` ## Dropdown Pattern ```rust struct Dropdown {
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub