From 3afb4aff645621eb85d64e9c36e9a6194d21ed99 Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Tue, 23 Jan 2024 11:49:48 +0200 Subject: [PATCH] init release (#1) --- .github/dependabot.yml | 11 +++ .github/workflows/rust.yml | 22 ++++++ .gitignore | 8 +-- Cargo.toml | 22 ++++++ LICENSE | 2 +- README.md | 116 ++++++++++++++++++++++++++++++- src/lib.rs | 137 +++++++++++++++++++++++++++++++++++++ 7 files changed, 309 insertions(+), 9 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/rust.yml create mode 100644 Cargo.toml create mode 100644 src/lib.rs diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..e8d486a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "cargo" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..58d869d --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,22 @@ +name: CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/.gitignore b/.gitignore index 6985cf1..50c8301 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,10 @@ # Generated by Cargo # will have compiled files and executables -debug/ -target/ +/target/ # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html Cargo.lock # These are backup files generated by rustfmt -**/*.rs.bk - -# MSVC Windows builds of rustc generate these, which store debugging information -*.pdb +**/*.rs.bk \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..4fd23f2 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "yew-scroll" +version = "0.1.0" +description = "🔝 A sleek and customizable Yew component for effortless scroll to top functionality." +license = "MIT" +keywords = ["scroll-to-top", "yew", "rust", "yew-scroll"] +repository = "https://github.com/wiseaidev/yew-scroll" +documentation = "https://docs.rs/yew-scroll/" +authors = ["Mahmoud Harmouch "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +gloo = { version = "0.11.0", features = ["utils"] } +yew = { version = "0.21.0", default-features = false } + +[profile.release] +codegen-units = 1 +opt-level = "z" +lto = "thin" +strip = "symbols" diff --git a/LICENSE b/LICENSE index 3e796e7..9062ee7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 Mahmoud +Copyright (c) 2024 Mahmoud Harmouch Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index fde1f4e..b19cccc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,114 @@ -# yew-scroll -🔝 A Yew component for effortless "scroll to top" functionality. +# 🔝 Yew Scroll + +[![Crates.io](https://img.shields.io/crates/v/yew-scroll)](https://crates.io/crates/yew-scroll) +[![Crates.io Downloads](https://img.shields.io/crates/d/yew-scroll)](https://crates.io/crates/yew-scroll) +![Crates.io License](https://img.shields.io/crates/l/yew-scroll) +![Rust](https://img.shields.io/badge/rust-stable-orange) + +![demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3wyypvi0bgxwsr0i146j.gif) + +## 📜 Introduction + +This component is designed to provide a convenient and customizable solution for implementing a "scroll to top" button in your Yew applications. Enhance user experience by allowing them to easily navigate to the top of the page with a single click. + +## 🤔 Why is this Component Useful? + +This component comes with several benefits that make it an essential addition to your Yew projects: + +1. 🔄 Scroll Navigation: Simplify user navigation by adding a convenient button to scroll smoothly to the top of the page. + +1. 🎨 Customization: Tailor the appearance of the "scroll to top" button using custom CSS classes, and provide a personalized SVG icon. + +1. 📏 Customizable Offset: Define a custom vertical offset (Y position) to trigger the visibility of the button, ensuring a seamless user experience. + +## ⚙️ Installation + +Integrating this component into your Yew project is a straightforward process. Follow these simple steps: + +1. Make sure you have Yew set up in your project. If not, refer to the [Yew documentation](https://yew.rs/docs/getting-started/introduction) for installation instructions. + +2. Install the component package using your preferred package manager: + + ```bash + $ cargo add yew-scroll + ``` + +3. Import the component into your Yew application and start using it to improve user navigation. + +## 🛠️ Usage + +Incorporating this component into your application is easy. Follow these steps: + +1. Import the component and its required dependencies: + + ```rust + use yew-scroll::{ScrollToTop, ScrollToTopProps}; + ``` + +1. Set up the props for the `ScrollToTop` component: + + ```rust + // Custom SVG content for the scroll-to-top button (an arrow). + fn custom_svg() -> Html { + html! { + + + + } + } + + // Custom SVG content for the scroll-to-top button (an arrow). + #[function_component(MyComponent)] + pub fn my_component() -> Html { + + // Set props for the `ScrollToTop` component + let custom_props = ScrollToTopProps { + css: "custom-css", // Add any custom CSS classes + top_offset: 0.0, // Set the desired top offset value to show the button + svg_content: custom_svg(), // Provide custom SVG content + }; + + // Render the `ScrollToTop` component with the specified props + html! { + <> + // Other content in your component +

{"Scroll down to see the button"}

+ + // Use the scroll_to_top component + + + // Default Usage + + + } + } + ``` + +1. Customize the appearance and behavior of the "scroll to top" button based on your project requirements. + +## 🔧 Props + +| Name | Type | Description | Example | Default Value | +| --- | --- | --- | --- | --- | +| `css` | `&'static str` | Custom CSS classes for styling the button. | "custom-scroll-button", "highlight-button". | "fixed bottom-4 right-4 bg-blue-500 text-white p-3 rounded-full cursor-pointer hover:bg-blue-600 transition duration-300 ease-in-out" | +| `top_offset` | `f64` | The vertical offset value (Y position) to trigger button visibility. | 200.0, 300.0 | 500.0 | +| `svg_content` | `Html` | Custom SVG content for the button. | `custom_svg()` | `default_svg()` | + +## 🤝 Contribution + +We encourage contributions from the community to enhance this Yew component. Feel free to open issues, submit pull requests, or provide feedback. Let's collaborate and make this component even more powerful! + +## 📜 License + +The Scroll To Top Yew component is licensed under the `MIT` License, allowing you to use, modify, and distribute it freely. Refer to the [`LICENSE`](LICENSE) file for more details. diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..fda485e --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,137 @@ +use gloo::events::EventListener; +use gloo::utils::window; +use yew::prelude::*; + +/// Constant defining default Tailwind CSS classes for the scroll-to-top button. +const SCROLL_TO_TOP_CLASSES: &'static str = + "fixed bottom-4 right-4 bg-blue-500 text-white p-3 rounded-full cursor-pointer hover:bg-blue-600 transition duration-300 ease-in-out"; + +#[derive(Properties, Clone, PartialEq)] +pub struct ScrollToTopProps { + /// Custom CSS classes for styling the scroll-to-top button. + #[prop_or(SCROLL_TO_TOP_CLASSES)] + pub css: &'static str, + + /// The vertical offset value (Y position) to show the button. + #[prop_or(500.0)] + pub top_offset: f64, + + /// Custom SVG content for the scroll-to-top button. + #[prop_or_else(default_svg)] + pub svg_content: Html, +} + +/// scroll_to_top +/// A Yew component that provides a button to scroll to the top of the page when clicked. +/// +/// # Arguments +/// * `props` - The properties of the component. +/// - `css` - Custom CSS classes for styling the scroll-to-top button. Defaults to predefined Tailwind classes. +/// - `top_offset` - The vertical offset value (Y position) to show the button. Defaults to 500.0 pixels. +/// - `svg_content` - Custom SVG content for the scroll-to-top button. Defaults to a default arrow SVG. +/// +/// # Returns +/// (Html): An HTML representation of the scroll-to-top button. +/// +/// # Examples +/// ``` +/// // Example of using the scroll_to_top component +/// use yew::prelude::*; +/// use yew_scroll::{ScrollToTop, ScrollToTopProps}; +/// +/// // Custom SVG content for the scroll-to-top button (an arrow). +/// fn custom_svg() -> Html { +/// html! { +/// +/// +/// +/// } +/// } +/// +/// #[function_component(MyComponent)] +/// pub fn my_component() -> Html { +/// // Set props for the scroll_to_top component +/// let scroll_to_top_props = ScrollToTopProps { +/// css: "custom-css", // Add any custom CSS classes +/// top_offset: 0.0, // Set the desired top offset value to show the button +/// svg_content: custom_svg(), // Provide custom SVG content +/// }; +/// +/// // Render the scroll_to_top component with the specified props +/// html! { +/// <> +/// // Other content in your component +///

{"Scroll down to see the button"}

+/// +/// // Use the scroll_to_top component +/// +/// +/// // Default Usage +/// +/// +/// } +/// } +/// ``` +#[function_component(ScrollToTop)] +pub fn scroll_to_top(props: &ScrollToTopProps) -> Html { + // State handle to track the visibility of the scroll-to-top button. + let visible_handle = use_state(|| false); + let visible = *visible_handle; + let top_offset = props.top_offset.clone(); + + // Effect to add a scroll event listener and update the visibility state. + use_effect(move || { + let listener = EventListener::new(&window(), "scroll", move |_| { + let scroll_position = window().scroll_y().unwrap_or_default(); + visible_handle.set(scroll_position > top_offset); + }); + + // Cleanup when the component is unmounted. + move || { + drop(listener); + } + }); + + // Callback for the button click event to scroll to the top. + let on_click = Callback::from(|_| { + let win = window(); + win.scroll_to_with_x_and_y(0.0, 0.0); + }); + + html! { + if visible { +
{ props.svg_content.clone() }
+ } + } +} + +/// Default SVG content for the scroll-to-top button (an arrow). +fn default_svg() -> Html { + html! { + + + + } +}