Skip to main content

ui_storybook/components/shell/
drop_zone.rs

1//! `DropZone` — the recorder's MP4 import surface.
2//!
3//! Two visual states: `idle` (subtle dashed outline, neutral copy) and
4//! `active` (solid accent border, bigger glyph, "release to drop" copy).
5//! The Tauri shell drives the active state from the OS-level drag events
6//! (`tauri::Window::on_window_event`), passing it in as a prop.
7
8use leptos::prelude::*;
9
10#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
11pub enum DropZoneState {
12    #[default]
13    Idle,
14    Active,
15}
16
17impl DropZoneState {
18    fn css(self) -> &'static str {
19        match self {
20            DropZoneState::Idle => "drop-zone-idle",
21            DropZoneState::Active => "drop-zone-active",
22        }
23    }
24
25    fn glyph(self) -> &'static str {
26        match self {
27            DropZoneState::Idle => "⤓",
28            DropZoneState::Active => "⇣",
29        }
30    }
31
32    fn headline(self) -> &'static str {
33        match self {
34            DropZoneState::Idle => "Drop a recording here",
35            DropZoneState::Active => "Release to import",
36        }
37    }
38
39    fn subtext(self) -> &'static str {
40        match self {
41            DropZoneState::Idle => "MP4, MOV, or any QuickTime-compatible video",
42            DropZoneState::Active => "Will open in the editor",
43        }
44    }
45}
46
47#[component]
48pub fn DropZone(
49    #[prop(optional)] state: DropZoneState,
50    #[prop(optional, into)] hint: String,
51) -> impl IntoView {
52    let class = format!("drop-zone {}", state.css());
53    let glyph = state.glyph();
54    let headline = state.headline();
55    let subtext = state.subtext();
56    let has_hint = !hint.is_empty();
57    view! {
58        <div class=class role="region" aria-label="Recording drop zone">
59            <div class="drop-zone-glyph">{glyph}</div>
60            <div class="drop-zone-headline">{headline}</div>
61            <div class="drop-zone-subtext">{subtext}</div>
62            <Show when=move || has_hint>
63                <div class="drop-zone-hint">{hint.clone()}</div>
64            </Show>
65        </div>
66    }
67}