summary refs log tree commit diff stats
path: root/src/components/select_placeholder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/select_placeholder.rs')
-rw-r--r--src/components/select_placeholder.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/components/select_placeholder.rs b/src/components/select_placeholder.rs
new file mode 100644
index 0000000..947931c
--- /dev/null
+++ b/src/components/select_placeholder.rs
@@ -0,0 +1,93 @@
+use leptos::{
+    IntoView,
+    attr::{AttributeValue, IntoAttributeValue},
+    component,
+    html::Select,
+    prelude::{
+        ClassAttribute, CollectView, ElementChild, GlobalAttributes, NodeRef, NodeRefAttribute,
+    },
+    view,
+};
+
+use crate::components::get_id;
+
+#[component]
+pub fn SelectPlaceholder<T>(
+    label: &'static str,
+    node_ref: NodeRef<Select>,
+    options: Vec<(&'static str, T)>,
+) -> impl IntoView
+where
+    T: IntoAttributeValue,
+    <T as IntoAttributeValue>::Output: Send + AttributeValue,
+{
+    let id = get_id();
+
+    let options = options
+        .into_iter()
+        .map(|(label, value)| {
+            view! {
+                <option value=value>{label}</option>
+            }
+        })
+        .collect_view();
+
+    view! {
+        <div class="relative h-14">
+            <select
+                id=id.to_string()
+                class="\
+                absolute \
+                bottom-0 \
+                bg-gray-200 \
+                border-8 \
+                border-b-2 \
+                border-b-trasparent \
+                border-gray-200 \
+                focus:outline-none \
+                h-10 \
+                peer \
+                placeholder-transparent \
+                rounded-t-lg \
+                text-gray-900 \
+                w-full \
+                "
+                node_ref=node_ref
+            >
+                {options}
+            </select>
+
+            // TODO: Reference `var(--tw-border-2)` instead of the `2 px` <2025-10-01>
+            <div class="
+            absolute \
+            bottom-0 \
+            h-[2px] \
+            w-full \
+            bg-gray-300 \
+            peer-focus:bg-indigo-600 \
+            " />
+
+            <label
+                for=id.to_string()
+                class="\
+                bottom-10 \
+                absolute \
+                left-0 \
+                text-gray-700 \
+                text-sm \
+                transition-all \
+                peer-focus:bottom-10 \
+                peer-focus:left-0 \
+                peer-focus:text-gray-700 \
+                peer-focus:text-sm \
+                peer-placeholder-shown:text-base \
+                peer-placeholder-shown:text-gray-400 \
+                peer-placeholder-shown:bottom-2 \
+                peer-placeholder-shown:left-2 \
+                "
+            >
+                {label}
+            </label>
+        </div>
+    }
+}