diff --git a/kayak_core/src/fragment.rs b/kayak_core/src/fragment.rs index 28151384c39d28265c84a3b386cb048862eb93eb..697691715f4d4443f7adb6841bd902e149d62c04 100644 --- a/kayak_core/src/fragment.rs +++ b/kayak_core/src/fragment.rs @@ -2,12 +2,26 @@ use crate::{ context_ref::KayakContextRef, styles::Style, Children, Index, OnEvent, Widget, WidgetProps, }; +/// Props used by the [`Fragment`] widget #[derive(Default, Debug, PartialEq, Clone)] pub struct FragmentProps { pub styles: Option<Style>, pub children: Option<crate::Children>, } +/// The base widget, used to actually build and render children +/// +/// # Props +/// +/// __Type:__ [`FragmentProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ⌠| +/// | `focusable` | ⌠| +/// #[derive(Default, Debug, PartialEq, Clone)] pub struct Fragment { pub id: Index, diff --git a/kayak_core/src/vec.rs b/kayak_core/src/vec.rs index 502a9359500658fe3609e25b3a62f2863afe542c..daefa34a1300d7305a90dc165d43f0c7ce662ab7 100644 --- a/kayak_core/src/vec.rs +++ b/kayak_core/src/vec.rs @@ -2,14 +2,31 @@ use crate::{ context_ref::KayakContextRef, styles::Style, Children, Index, OnEvent, Widget, WidgetProps, }; +/// Props used by the [`VecTracker`] widget #[derive(Default, Debug, PartialEq, Clone)] pub struct VecTrackerProps<T> { + /// The data to display in sequence + /// + /// The type of [T] should be implement the [`Widget`] trait pub data: Vec<T>, pub styles: Option<Style>, pub children: Option<Children>, pub on_event: Option<OnEvent>, } +/// A widget that renders a `Vec` of widgets +/// +/// # Props +/// +/// __Type:__ [`VecTrackerProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ⌠| +/// #[derive(Debug, PartialEq, Clone, Default)] pub struct VecTracker<T> { pub id: Index, diff --git a/src/lib.rs b/src/lib.rs index f72eb4905d0f0c26fd21e7b66004a228b7d81c9c..e0315294b43e31082e82feaecbea75637f2536fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(doc_auto_cfg)] + pub mod core { pub use kayak_core::*; pub use kayak_render_macros::{ diff --git a/src/widgets/app.rs b/src/widgets/app.rs index 6c54c8c66902fbb75a331dbfb908410f8fca37c0..4d95702591510b647667ea6e0f02ec290af36ac3 100644 --- a/src/widgets/app.rs +++ b/src/widgets/app.rs @@ -7,6 +7,7 @@ use crate::core::{ use crate::widgets::Clip; +/// Props used by the [`App`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct AppProps { #[prop_field(Styles)] @@ -20,6 +21,23 @@ pub struct AppProps { } #[widget] +/// The most common root widget +/// +/// # Props +/// +/// __Type:__ [`AppProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ✅ | +/// +/// # Using the `bevy_renderer` feature +/// +/// When the `bevy_renderer` feature is enabled, this widget will automatically bind to the window size +/// of the Bevy app. This allows it to update on window resize in order to match the width and height of the window. pub fn App(props: AppProps) { #[cfg(feature = "bevy_renderer")] { diff --git a/src/widgets/background.rs b/src/widgets/background.rs index 40a39e24935fa6b6d959876de306ae8ef5542e79..56f3b79cf11cc164264effa880065aeb79b3cd96 100644 --- a/src/widgets/background.rs +++ b/src/widgets/background.rs @@ -5,6 +5,7 @@ use crate::core::{ widget, Children, Fragment, OnEvent, WidgetProps, }; +/// Props used by the [`Background`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct BackgroundProps { #[prop_field(Styles)] @@ -18,6 +19,19 @@ pub struct BackgroundProps { } #[widget] +/// A widget that provides a simple, rectangular background +/// +/// # Props +/// +/// __Type:__ [`BackgroundProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ✅ | +/// pub fn Background(props: BackgroundProps) { if props.styles.is_none() { props.styles = Some(Style::default()) diff --git a/src/widgets/button.rs b/src/widgets/button.rs index a0cf25f65da1da47eb5fe6418f844d7b5fe708af..74e8bf39f85f8b2ac4578108909b5a95ee51c879 100644 --- a/src/widgets/button.rs +++ b/src/widgets/button.rs @@ -6,8 +6,13 @@ use crate::core::{ }; use kayak_core::CursorIcon; +/// Props used by the [`Button`] widget #[derive(Default, Debug, PartialEq, Clone)] pub struct ButtonProps { + /// If true, disables this widget not allowing it to be focusable + /// + // TODO: Update this documentation when the disabled issue is fixed + /// Currently, this does not actually disable the button from being clicked. pub disabled: bool, pub styles: Option<Style>, pub children: Option<Children>, @@ -38,7 +43,25 @@ impl WidgetProps for ButtonProps { } #[widget] +/// A widget that is styled like a button +/// +/// # Props +/// +/// __Type:__ [`ButtonProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ✅ | +/// pub fn Button(props: ButtonProps) { + // TODO: This should probably do more than just provide basic styling. + // Ideally, we could add a `Handler` prop for `on_click` and other common cursor + // events. Giving it the additional purpose of being a compact way to define a button. + // This also allows us to make `disable` trule disable the button. + // Also, styles need to reflect disabled status. props.styles = Some( Style::default() .with_style(Style { diff --git a/src/widgets/clip.rs b/src/widgets/clip.rs index a55a4c1dd9a328ae3ea2830977961c3e74de9800..9bfa12053d839f6ac9e1552a0e1da6a054d47935 100644 --- a/src/widgets/clip.rs +++ b/src/widgets/clip.rs @@ -5,6 +5,7 @@ use crate::core::{ widget, Children, OnEvent, WidgetProps, }; +/// Props used by the [`Clip`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct ClipProps { #[prop_field(Styles)] @@ -16,6 +17,20 @@ pub struct ClipProps { } #[widget] +/// A widget that clips its contents to fit the parent container or its designated +/// [`width`](Style::width) and [`height`](Style::height) styling +/// +/// # Props +/// +/// __Type:__ [`ClipProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ⌠| +/// pub fn Clip(props: ClipProps) { let incoming_styles = props.styles.clone().unwrap_or_default(); props.styles = Some(Style { diff --git a/src/widgets/element.rs b/src/widgets/element.rs index 901357e3d79be981d3c40f5d67cc4f910e959086..f32c3fda6de0ab0791bec1cd6c396c41f820a2dd 100644 --- a/src/widgets/element.rs +++ b/src/widgets/element.rs @@ -5,6 +5,7 @@ use crate::core::{ widget, Children, OnEvent, WidgetProps, }; +/// Props used by the [`Element`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct ElementProps { #[prop_field(Styles)] @@ -18,6 +19,21 @@ pub struct ElementProps { } #[widget] +/// The most basic widget, equivalent to `div` from HTML. +/// +/// It essentially just sets the [`RenderCommand`] of this widget to [`RenderCommand::Layout`]. +/// +/// # Props +/// +/// __Type:__ [`ElementProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ✅ | +/// pub fn Element(props: ElementProps) { props.styles = Some(Style { render_command: StyleProp::Value(RenderCommand::Layout), diff --git a/src/widgets/fold.rs b/src/widgets/fold.rs index a7458e0a9a4efa03b747ea1a5bc9a54d803ab428..97b4942291188e60d5ecc607afab2e215f170b94 100644 --- a/src/widgets/fold.rs +++ b/src/widgets/fold.rs @@ -7,12 +7,26 @@ use crate::core::{ use crate::widgets::{Background, Clip, If, Text}; +// TODO: Add `disabled` prop + +/// Props used by the [`Fold`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct FoldProps { + /// The initial open state of the fold + pub default_open: bool, + /// The string displayed as the label of this fold element pub label: String, - pub open: Option<bool>, + /// A callback for when the user presses the fold's label + /// + /// The handler is given the boolean value of the desired open state. For example, + /// if the fold is closed and the user presses on the label, this callback will be + /// fired with the boolean value `true`. pub on_change: Option<Handler<bool>>, - pub default_open: bool, + /// Sets the controlled open state of the fold + /// + /// If `None`, the open state will be automatically handled internally. + /// This is useful for if you don't need or care to manage the toggling yourself. + pub open: Option<bool>, #[prop_field(Styles)] pub styles: Option<Style>, #[prop_field(Children)] @@ -23,18 +37,19 @@ pub struct FoldProps { pub focusable: Option<bool>, } +#[widget] /// A widget container that toggles its content between visible and hidden when clicked /// -/// If `open` is set to `None`, then the toggle state will be automatically handled by -/// the widget. This is useful for if you don't need or care to manage the toggling yourself. +/// # Props /// -/// # Arguments +/// __Type:__ [`FoldProps`] /// -/// * `label`: The Fold's label -/// * `children`: The Fold's content -/// * `open`: If true, renders the content. If `None`, the widget will manage its own open/close state. -/// * `on_change`: Called when the user clicks on the Fold's label. Contains the next desired toggle state. -/// * `default_open`: Set the initial open state of this widget +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ✅ | /// /// # Examples /// @@ -53,7 +68,6 @@ pub struct FoldProps { /// </Fold> /// } /// ``` -#[widget] pub fn Fold(props: FoldProps) { let FoldProps { default_open, diff --git a/src/widgets/if_element.rs b/src/widgets/if_element.rs index a981384d623f01cf97e5e51be26d6ac42fab6e28..8a14b5ee601335488afe822275503658d84fe9c9 100644 --- a/src/widgets/if_element.rs +++ b/src/widgets/if_element.rs @@ -1,7 +1,9 @@ use crate::core::{rsx, styles::Style, widget, Children, OnEvent, WidgetProps}; +/// Props used by the [`If`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct IfProps { + /// If true, the children will be rendered, otherwise nothing will be rendered pub condition: bool, #[prop_field(Styles)] pub styles: Option<Style>, @@ -14,6 +16,19 @@ pub struct IfProps { } #[widget] +/// A widget that _conditionally_ renders its children +/// +/// # Props +/// +/// __Type:__ [`IfProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ✅ | +/// pub fn If(props: IfProps) { if props.condition { rsx! { diff --git a/src/widgets/image.rs b/src/widgets/image.rs index a1362cc7795be5e10b43e937cecd9469cf65ab0a..462c385d38f7ba3cd47c7f373eeed370e33398f0 100644 --- a/src/widgets/image.rs +++ b/src/widgets/image.rs @@ -5,6 +5,7 @@ use crate::core::{ widget, Children, OnEvent, WidgetProps, }; +/// Props used by the [`Image`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct ImageProps { pub handle: u16, @@ -19,6 +20,19 @@ pub struct ImageProps { } #[widget] +/// A widget that renders an image background +/// +/// # Props +/// +/// __Type:__ [`ImageProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ✅ | +/// pub fn Image(props: ImageProps) { props.styles = Some(Style { render_command: StyleProp::Value(RenderCommand::Image { diff --git a/src/widgets/inspector.rs b/src/widgets/inspector.rs index 88350ec2a22bc5308d547e6e5f46969de7322002..8c341e57edcaf1a8d59c46227b7afa6129b22fc6 100644 --- a/src/widgets/inspector.rs +++ b/src/widgets/inspector.rs @@ -6,12 +6,14 @@ use crate::core::{rsx, widget, MutableBound, WidgetProps}; use crate::widgets::{Background, Button, Text}; +// TODO: Remove if unneeded #[derive(Clone, PartialEq)] pub enum InspectData { None, Data(Vec<String>), } +/// Props used by the [`Inspector`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct InspectorProps { #[prop_field(Styles)] @@ -19,6 +21,21 @@ pub struct InspectorProps { } #[widget] +/// A widget that displays debug data for inspected widgets +/// +/// "Inspected widgets" refers to the last clicked widget. +/// +/// # Props +/// +/// __Type:__ [`InspectorProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ⌠| +/// | `styles` | ✅ | +/// | `on_event` | ⌠| +/// | `focusable` | ⌠| +/// pub fn Inspector(props: InspectorProps) { let (inspect_data, set_inspect_data, _) = use_state!(Vec::<String>::new()); diff --git a/src/widgets/nine_patch.rs b/src/widgets/nine_patch.rs index 21521847934e6c6319c5f4083fe81b19f853a6a2..1abd2557897e4591efd9ca69f874755d134afd31 100644 --- a/src/widgets/nine_patch.rs +++ b/src/widgets/nine_patch.rs @@ -6,9 +6,13 @@ use crate::core::{ widget, Children, OnEvent, WidgetProps, }; +/// Props used by the [`NinePatch`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct NinePatchProps { + /// The handle to image pub handle: u16, + /// The size of each edge (in pixels) + // TODO: Convert to Edge<f32> pub border: Space, #[prop_field(Styles)] pub styles: Option<Style>, @@ -21,6 +25,33 @@ pub struct NinePatchProps { } #[widget] +/// A widget that renders a nine-patch image background +/// +/// A nine-patch is a special type of image that's broken into nine parts: +/// +/// * Edges - Top, Bottom, Left, Right +/// * Corners - Top-Left, Top-Right, Bottom-Left, Bottom-Right +/// * Center +/// +/// Using these parts of an image, we can construct a scalable background and border +/// all from a single image. This is done by: +/// +/// * Stretching the edges (vertically for left/right and horizontally for top/bottom) +/// * Preserving the corners +/// * Scaling the center to fill the remaining space +/// +/// +/// # Props +/// +/// __Type:__ [`NinePatchProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ✅ | +/// pub fn NinePatch(props: NinePatchProps) { props.styles = Some(Style { render_command: StyleProp::Value(RenderCommand::NinePatch { diff --git a/src/widgets/text.rs b/src/widgets/text.rs index 759d2e6b58e20b2dd3c0e627aee139d44a815908..541df771b83a89e5c06e5d2f1f4ba37c6f1a8716 100644 --- a/src/widgets/text.rs +++ b/src/widgets/text.rs @@ -7,11 +7,18 @@ use crate::core::{ widget, OnEvent, WidgetProps, }; +/// PRops used by the [`Text`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct TextProps { + /// The string to display pub content: String, + /// The name of the font to use + /// + /// The given font must already be loaded into the [`KayakContext`](kayak_core::KayakContext) pub font: Option<String>, + /// The height of a line of text (currently in pixels) pub line_height: Option<f32>, + /// The font size (in pixels) pub size: f32, #[prop_field(Styles)] pub styles: Option<Style>, @@ -22,6 +29,19 @@ pub struct TextProps { } #[widget] +/// A widget that renders plain text +/// +/// # Props +/// +/// __Type:__ [`TextProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ⌠| +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ✅ | +/// pub fn Text(props: TextProps) { let TextProps { content, diff --git a/src/widgets/text_box.rs b/src/widgets/text_box.rs index 457f9b7624cf66f09839ebe6c4948abbacd05494..ee56ae90527952496f89cb042b62b41bb335e8a4 100644 --- a/src/widgets/text_box.rs +++ b/src/widgets/text_box.rs @@ -9,12 +9,20 @@ use std::sync::{Arc, RwLock}; use crate::widgets::{Background, Clip, Text}; +/// Props used by the [`TextBox`] widget #[derive(Default, Debug, PartialEq, Clone)] pub struct TextBoxProps { + /// If true, prevents the widget from being focused (and consequently edited) pub disabled: bool, - pub value: String, + /// A callback for when the text value was changed pub on_change: Option<OnChange>, + /// The text to display when the user input is empty pub placeholder: Option<String>, + /// The user input + /// + /// This is a controlled state. You _must_ set this to the value to you wish to be displayed. + /// You can use the [`on_change`] callback to update this prop as the user types. + pub value: String, pub styles: Option<Style>, pub children: Option<Children>, pub on_event: Option<OnEvent>, @@ -73,6 +81,19 @@ impl std::fmt::Debug for OnChange { pub struct Focus(pub bool); #[widget] +/// A widget that displays a text input field +/// +/// # Props +/// +/// __Type:__ [`TextBoxProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ✅ | +/// pub fn TextBox(props: TextBoxProps) { let TextBoxProps { on_change, diff --git a/src/widgets/tooltip.rs b/src/widgets/tooltip.rs index 71b5df916c9f269c215891ac905128860a6c63c0..f99175dd9b209587eeab30a680449df055c1117f 100644 --- a/src/widgets/tooltip.rs +++ b/src/widgets/tooltip.rs @@ -8,6 +8,7 @@ use std::sync::Arc; use crate::widgets::{Background, Clip, Element, If, Text}; +/// Data provided by a [`TooltipProvider`] used to control a tooltip #[derive(Clone, PartialEq, Debug, Default)] pub struct TooltipData { /// The anchor coordinates in pixels (x, y) @@ -20,9 +21,12 @@ pub struct TooltipData { pub visible: bool, } +/// Props used by the [`TooltipProvider`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct TooltipProviderProps { + /// The position of the containing rect (used to layout the tooltip) pub position: (f32, f32), + /// The size of the containing rect (used to layout the tooltip) pub size: (f32, f32), #[prop_field(Styles)] pub styles: Option<Style>, @@ -32,10 +36,18 @@ pub struct TooltipProviderProps { pub on_event: Option<OnEvent>, } +/// Props used by the [`TooltipProvider`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct TooltipConsumerProps { + /// The position at which to anchor the tooltip (in pixels) + /// + /// If `None`, the tooltip will follow the cursor pub anchor: Option<(f32, f32)>, + /// The size of the tooltip + /// + /// If `None`, the tooltip will be automatically sized pub size: Option<(f32, f32)>, + /// The text to display in the tooltip pub text: String, #[prop_field(Styles)] pub styles: Option<Style>, @@ -45,14 +57,22 @@ pub struct TooltipConsumerProps { pub on_event: Option<OnEvent>, } -/// A provider for managing a tooltip context. +#[widget] +/// A widget that provides a context for managing a tooltip +/// +/// This widget creates a single tooltip that can be controlled by any descendant [`TooltipConsumer`], +/// or by creating a consumer for [`TooltipData`] /// -/// This widget creates a single tooltip that can be controlled by any descendant [TooltipConsumer]. +/// # Props /// -/// # Arguments +/// __Type:__ [`TooltipProviderProps`] /// -/// * `position`: The position of the containing rect (used to layout the tooltip). -/// * `size`: The size of the containing rect (used to layout the tooltip). +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ⌠| /// /// # Styles /// @@ -82,7 +102,6 @@ pub struct TooltipConsumerProps { /// } /// } /// ``` -#[widget] pub fn TooltipProvider(props: TooltipProviderProps) { let TooltipProviderProps { position, size, .. } = props; const WIDTH: f32 = 150.0; @@ -164,13 +183,20 @@ pub fn TooltipProvider(props: TooltipProviderProps) { } } -/// A consumer of [TooltipProvider], displaying a tooltip when its children are hovered. +#[widget] +/// A widget that consumes the [`TooltipData`] from a [`TooltipProvider`], providing a +/// convenient way to apply a tooltip over its children. +/// +/// # Props /// -/// # Arguments +/// __Type:__ [`TooltipConsumerProps`] /// -/// * `text`: The text to display in the tooltip. -/// * `anchor`: The position (in pixels) to which the tooltip will be anchored. If `None`, defaults to the cursor's position. -/// * `size`: The size (in pixels) of the tooltip. +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ⌠| /// /// # Examples /// ``` @@ -194,7 +220,6 @@ pub fn TooltipProvider(props: TooltipProviderProps) { /// } /// } /// ``` -#[widget] pub fn TooltipConsumer(props: TooltipConsumerProps) { let TooltipConsumerProps { anchor, size, text, .. diff --git a/src/widgets/window.rs b/src/widgets/window.rs index f763dc22e7ad3eae4e7025b61883ff72002886b3..74cfb5962720bd2aa5734a3d18b7e321e3030f2e 100644 --- a/src/widgets/window.rs +++ b/src/widgets/window.rs @@ -9,11 +9,16 @@ use kayak_core::CursorIcon; use crate::widgets::{Background, Clip, Element, Text}; +/// Props used by the [`Window`] widget #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct WindowProps { + /// If true, allows the window to be draggable by its title bar pub draggable: bool, + /// The position at which to display the window in pixels pub position: (f32, f32), + /// The size of the window in pixels pub size: (f32, f32), + /// The text to display in the window's title bar pub title: String, #[prop_field(Styles)] pub styles: Option<Style>, @@ -26,6 +31,19 @@ pub struct WindowProps { } #[widget] +/// A widget that renders a window-like container element +/// +/// # Props +/// +/// __Type:__ [`WindowProps`] +/// +/// | Common Prop | Accepted | +/// | :---------: | :------: | +/// | `children` | ✅ | +/// | `styles` | ✅ | +/// | `on_event` | ✅ | +/// | `focusable` | ✅ | +/// pub fn Window(props: WindowProps) { let WindowProps { draggable,