context menu implementation testing

This commit is contained in:
2026-04-10 13:54:56 -04:00
parent ec0c6a3487
commit 4325280020
7 changed files with 101 additions and 142 deletions
@@ -1,64 +1,63 @@
use super::props::*;
use dioxus::prelude::*;
use dioxus_primitives::context_menu::{
self, ContextMenuContentProps, ContextMenuItemProps, ContextMenuProps, ContextMenuTriggerProps,
};
const CONTEXT_MENU_CSS: Asset = asset!("./style.scss");
#[component]
pub fn ContextMenu(props: ContextMenuProps) -> Element {
pub fn ContextMenu(props: ContextMenuProps) -> Element
{
rsx! {
document::Link { rel: "stylesheet", href: asset!("./style.css") }
context_menu::ContextMenu {
disabled: props.disabled,
open: props.open,
default_open: props.default_open,
on_open_change: props.on_open_change,
roving_loop: props.roving_loop,
attributes: props.attributes,
document::Link { rel: "stylesheet", href: CONTEXT_MENU_CSS }
{props.children}
}
}
#[component]
pub fn ContextMenuTrigger(props: ContextMenuTriggerProps) -> Element
{
rsx! {
div{
class: "contextMenuTrigger",
oncontextmenu: move|e|{
},
{props.children}
}
}
}
#[component]
pub fn ContextMenuTrigger(props: ContextMenuTriggerProps) -> Element {
pub fn ContextMenuContent(props: ContextMenuContentProps) -> Element
{
rsx! {
context_menu::ContextMenuTrigger {
padding: "20px",
background: "var(--primary-color)",
border: "1px dashed var(--primary-color-6)",
border_radius: ".5rem",
cursor: "context-menu",
user_select: "none",
text_align: "center",
attributes: props.attributes,
div{
class: "contextMenuContent",
{props.children}
}
}
}
#[component]
pub fn ContextMenuContent(props: ContextMenuContentProps) -> Element {
pub fn ContextMenuItem(props: ContextMenuItemProps) -> Element
{
rsx! {
context_menu::ContextMenuContent {
class: "context-menu-content",
id: props.id,
attributes: props.attributes,
div {
class: "contextMenuItem",
onclick: move |_|{
props.on_select.call(props.value.clone());
},
div {
class: "content",
{props.children}
}
}
}
}
#[component]
pub fn ContextMenuItem(props: ContextMenuItemProps) -> Element {
pub fn ContextMenuNestedContent(props: ContextMenuNestedProps) -> Element
{
rsx! {
context_menu::ContextMenuItem {
class: "context-menu-item",
disabled: props.disabled,
value: props.value,
index: props.index,
on_select: props.on_select,
attributes: props.attributes,
{props.children}
}
}
}
@@ -1,2 +1,3 @@
mod component;
mod props;
pub use component::*;
@@ -0,0 +1,33 @@
use dioxus::prelude::*;
#[derive(Props, Clone, PartialEq)]
pub struct ContextMenuProps
{
pub children: Element,
}
#[derive(Props, Clone, PartialEq)]
pub struct ContextMenuItemProps
{
pub value: String,
pub on_select: EventHandler<String>,
pub children: Element,
}
#[derive(Props, Clone, PartialEq)]
pub struct ContextMenuTriggerProps
{
pub children: Element,
}
#[derive(Props, Clone, PartialEq)]
pub struct ContextMenuContentProps
{
pub children: Element,
}
#[derive(Props, Clone, PartialEq)]
pub struct ContextMenuNestedProps
{
pub children: Element,
}
@@ -1,71 +0,0 @@
.context-menu-content {
z-index: 1000;
min-width: 220px;
padding: 0.25rem;
border-radius: 0.5rem;
background: var(--dark, var(--primary-color-5))
var(--light, var(--primary-color));
box-shadow: inset 0 0 0 1px var(--dark, var(--primary-color-7))
var(--light, var(--primary-color-6));
opacity: 0;
pointer-events: none;
will-change: transform, opacity;
}
.context-menu-content[data-state="closed"] {
animation: context-menu-animate-out 150ms ease-in forwards;
}
@keyframes context-menu-animate-out {
0% {
opacity: 1;
transform: scale(1) translateY(0);
}
100% {
opacity: 0;
transform: scale(0.95) translateY(-2px);
}
}
.context-menu-content[data-state="open"] {
animation: context-menu-animate-in 150ms ease-out forwards;
}
@keyframes context-menu-animate-in {
0% {
opacity: 0;
transform: scale(0.95) translateY(-2px);
}
100% {
opacity: 1;
transform: scale(1) translateY(0);
}
}
.context-menu-item {
display: flex;
align-items: center;
padding: 8px 12px;
border-radius: calc(0.5rem - 0.25rem);
color: var(--secondary-color-4);
cursor: pointer;
font-size: 14px;
outline: none;
transition: background-color 100ms ease-out;
user-select: none;
}
.context-menu-item[data-disabled="true"] {
color: var(--secondary-color-5);
cursor: not-allowed;
}
.context-menu-item:hover:not([data-disabled="true"]),
.context-menu-item:focus-visible {
background: var(--light, var(--primary-color-4))
var(--dark, var(--primary-color-7));
color: var(--light, var(--secondary-color-1))
var(--dark, var(--secondary-color-4));
}
+13 -16
View File
@@ -1,7 +1,5 @@
use dioxus::prelude::*;
use dioxus_primitives::context_menu::{
ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger,
};
use dioxus_primitives::context_menu::{ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger};
use tonic::{Response, Status};
use web_sys::window;
@@ -13,13 +11,15 @@ use crate::{
},
};
pub struct MediaClassChangeEvent {
pub struct MediaClassChangeEvent
{
pub index: usize,
pub class: String,
}
#[derive(PartialEq, Clone, Props)]
pub struct MediaItemProps {
pub struct MediaItemProps
{
pub item: MediaModel,
pub index: usize,
pub on_class_changed: Option<EventHandler<MediaClassChangeEvent>>,
@@ -27,14 +27,16 @@ pub struct MediaItemProps {
}
#[component]
pub fn MediaItem(props: MediaItemProps) -> Element {
pub fn MediaItem(props: MediaItemProps) -> Element
{
let item = props.item;
let mtype = item.media_type().as_str_name();
let filename = item.file_name;
let id = item.id.unwrap().value;
let thumb = item.thumb_url;
let class = item.class;
let mut class_signal = use_signal(|| match class {
let mut class_signal = use_signal(|| match class
{
1 => "blur",
2 => "secret",
_ => "",
@@ -42,13 +44,6 @@ pub fn MediaItem(props: MediaItemProps) -> Element {
let url = item.media_url;
let download = format!("{HOST}{url}");
// class_signal.set(match class
// {
// 1 => "blur",
// 2 => "secret",
// _ => "",
// });
return rsx! {
ContextMenu{
ContextMenuTrigger{
@@ -181,7 +176,8 @@ pub fn MediaItem(props: MediaItemProps) -> Element {
}
#[component]
pub fn MediaItemPlaceHolder() -> Element {
pub fn MediaItemPlaceHolder() -> Element
{
return rsx! {
div { class: "mediaItem placeholder",
img { },
@@ -196,7 +192,8 @@ pub fn MediaItemPlaceHolder() -> Element {
};
}
async fn set_class(id: String, class: i32) -> Result<Response<()>, Status> {
async fn set_class(id: String, class: i32) -> Result<Response<()>, Status>
{
let mut client = get_rpc_client();
return client
.set_media_class(SetMediaClassRequest {
+2 -2
View File
@@ -1,5 +1,5 @@
pub mod basic;
// mod context_menu;
mod context_menu;
mod icons;
mod media_grid;
mod media_item;
@@ -9,7 +9,7 @@ mod notif;
mod pagination;
mod passkey;
mod search;
// pub use context_menu::*;
pub use context_menu::*;
pub use media_grid::*;
pub use media_item::*;
pub use metrics_token::*;