- Fix z-index issue by creating separate CSS classes for inline vs dropdown color pickers - Unify CalDAV and external calendar color pickers to use same grid interface - Improve color picker styling with 4x4 grid layout for 16 colors - Enhance color option appearance with proper border centering and sizing - Replace native HTML color input with consistent predefined color grid - Add visual improvements: larger swatches, better hover effects, checkmark selection 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
92 lines
3.8 KiB
Rust
92 lines
3.8 KiB
Rust
use crate::services::calendar_service::CalendarInfo;
|
|
use web_sys::MouseEvent;
|
|
use yew::prelude::*;
|
|
|
|
#[derive(Properties, PartialEq)]
|
|
pub struct CalendarListItemProps {
|
|
pub calendar: CalendarInfo,
|
|
pub color_picker_open: bool,
|
|
pub on_color_change: Callback<(String, String)>, // (calendar_path, color)
|
|
pub on_color_picker_toggle: Callback<String>, // calendar_path
|
|
pub available_colors: Vec<String>,
|
|
pub on_context_menu: Callback<(MouseEvent, String)>, // (event, calendar_path)
|
|
pub on_visibility_toggle: Callback<String>, // calendar_path
|
|
}
|
|
|
|
#[function_component(CalendarListItem)]
|
|
pub fn calendar_list_item(props: &CalendarListItemProps) -> Html {
|
|
let on_color_click = {
|
|
let cal_path = props.calendar.path.clone();
|
|
let on_color_picker_toggle = props.on_color_picker_toggle.clone();
|
|
Callback::from(move |e: MouseEvent| {
|
|
e.stop_propagation();
|
|
on_color_picker_toggle.emit(cal_path.clone());
|
|
})
|
|
};
|
|
|
|
let on_context_menu = {
|
|
let cal_path = props.calendar.path.clone();
|
|
let on_context_menu = props.on_context_menu.clone();
|
|
Callback::from(move |e: MouseEvent| {
|
|
e.prevent_default();
|
|
on_context_menu.emit((e, cal_path.clone()));
|
|
})
|
|
};
|
|
|
|
let on_visibility_toggle = {
|
|
let cal_path = props.calendar.path.clone();
|
|
let on_visibility_toggle = props.on_visibility_toggle.clone();
|
|
Callback::from(move |_| {
|
|
on_visibility_toggle.emit(cal_path.clone());
|
|
})
|
|
};
|
|
|
|
html! {
|
|
<li key={props.calendar.path.clone()} oncontextmenu={on_context_menu}>
|
|
<div class="calendar-info">
|
|
<input
|
|
type="checkbox"
|
|
checked={props.calendar.is_visible}
|
|
onchange={on_visibility_toggle}
|
|
/>
|
|
<span class="calendar-color"
|
|
style={format!("background-color: {}", props.calendar.color)}
|
|
onclick={on_color_click}>
|
|
{
|
|
if props.color_picker_open {
|
|
html! {
|
|
<div class="color-picker-dropdown">
|
|
{
|
|
props.available_colors.iter().map(|color| {
|
|
let color_str = color.clone();
|
|
let cal_path = props.calendar.path.clone();
|
|
let on_color_change = props.on_color_change.clone();
|
|
|
|
let on_color_select = Callback::from(move |_: MouseEvent| {
|
|
on_color_change.emit((cal_path.clone(), color_str.clone()));
|
|
});
|
|
|
|
let is_selected = props.calendar.color == *color;
|
|
let class_name = if is_selected { "color-option selected" } else { "color-option" };
|
|
|
|
html! {
|
|
<div class={class_name}
|
|
style={format!("background-color: {}", color)}
|
|
onclick={on_color_select}>
|
|
</div>
|
|
}
|
|
}).collect::<Html>()
|
|
}
|
|
</div>
|
|
}
|
|
} else {
|
|
html! {}
|
|
}
|
|
}
|
|
</span>
|
|
<span class="calendar-name">{&props.calendar.display_name}</span>
|
|
</div>
|
|
</li>
|
|
}
|
|
}
|