From 0e19d90fb7a005b89c3479284d363950ea01f29a Mon Sep 17 00:00:00 2001 From: w3bdesign <45217974+w3bdesign@users.noreply.github.com> Date: Wed, 4 Dec 2024 03:58:28 +0100 Subject: [PATCH 1/8] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20stories=20for=20I?= =?UTF-8?q?nputField=20and=20Pill=20components?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement component stories using Ladle for visual testing and documentation of the InputField and Pill UI components, complete with variants and props examples 🚀 component-library 📱 storybook 💄 ui-components --- package.json | 3 +- src/stories/components/InputField.stories.tsx | 59 +++++++++++++++++++ src/stories/components/Pill.stories.tsx | 35 +++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 src/stories/components/InputField.stories.tsx create mode 100644 src/stories/components/Pill.stories.tsx diff --git a/package.json b/package.json index cd589891..fdaad2ac 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "cypress:open": "cypress open", "cypress:headless": "cypress run", "e2e": "start-test dev 3000 cypress:headless", - "refresh": "pnpm i && rm -rf node_modules && rm pnpm-lock.yaml && pnpm store prune && pnpm i && pnpm format" + "refresh": "pnpm i && rm -rf node_modules && rm pnpm-lock.yaml && pnpm store prune && pnpm i && pnpm format", + "ladle": "ladle serve" }, "dependencies": { "@emailjs/browser": "^4.4.1", diff --git a/src/stories/components/InputField.stories.tsx b/src/stories/components/InputField.stories.tsx new file mode 100644 index 00000000..918c93d5 --- /dev/null +++ b/src/stories/components/InputField.stories.tsx @@ -0,0 +1,59 @@ +import React from "react"; +import { Meta, Story } from "@ladle/react"; +import InputField, { InputProps } from "../../components/UI/InputField.component"; +import { useForm, FieldValues } from "react-hook-form"; + +export default { + title: "InputField", + component: InputField, +} as Meta; + +// Wrapper component to provide form context +const InputFieldWrapper = (props: Omit, "register">) => { + const { register } = useForm(); + return ; +}; + +const Template: Story, "register">> = (args) => ( + +); + +export const Default = Template.bind({}); +Default.args = { + name: "defaultInput", + label: "Default Input", + htmlFor: "defaultInput", +}; + +export const Required = Template.bind({}); +Required.args = { + name: "requiredInput", + label: "Required Input", + htmlFor: "requiredInput", + isRequired: true, +}; + +export const WithPattern = Template.bind({}); +WithPattern.args = { + name: "emailInput", + label: "Email Input", + htmlFor: "emailInput", + inputPattern: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, + title: "Please enter a valid email address", +}; + +export const TextArea = Template.bind({}); +TextArea.args = { + name: "textArea", + label: "Text Area", + htmlFor: "textArea", + type: "textarea", +}; + +export const WithError = Template.bind({}); +WithError.args = { + name: "errorInput", + label: "Input with Error", + htmlFor: "errorInput", + error: "This field has an error", +}; diff --git a/src/stories/components/Pill.stories.tsx b/src/stories/components/Pill.stories.tsx new file mode 100644 index 00000000..68d0f00f --- /dev/null +++ b/src/stories/components/Pill.stories.tsx @@ -0,0 +1,35 @@ +import React from "react"; +import { Meta, Story } from "@ladle/react"; +import Pill from "../../components/UI/Pill.component"; + +export default { + title: "Pill", + component: Pill, +} as Meta; + +const Template: Story> = (args) => ( + +); + +export const Default = Template.bind({}); +Default.args = { + text: "Default Pill", +}; + +export const CustomClass = Template.bind({}); +CustomClass.args = { + text: "Custom Styled Pill", + className: "bg-purple-600 bg-opacity-20 border-purple-800", +}; + +export const AsLink = Template.bind({}); +AsLink.args = { + text: "Link Pill", + href: "https://example.com", +}; + +export const WithClickHandler = Template.bind({}); +WithClickHandler.args = { + text: "Clickable Pill", + onClick: () => alert("Pill clicked!"), +}; From 9743a485afcb8faa1a7ad0790a811cbd222c482a Mon Sep 17 00:00:00 2001 From: w3bdesign <45217974+w3bdesign@users.noreply.github.com> Date: Wed, 4 Dec 2024 03:58:45 +0100 Subject: [PATCH 2/8] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20storybook=20examp?= =?UTF-8?q?les=20for=20PageHeader=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add comprehensive storybook stories showcasing various PageHeader usage scenarios including basic text, HTML elements, and long text content examples --- src/stories/components/PageHeader.stories.tsx | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/stories/components/PageHeader.stories.tsx diff --git a/src/stories/components/PageHeader.stories.tsx b/src/stories/components/PageHeader.stories.tsx new file mode 100644 index 00000000..57ff4ac1 --- /dev/null +++ b/src/stories/components/PageHeader.stories.tsx @@ -0,0 +1,29 @@ +import React from "react"; +import { Meta, Story } from "@ladle/react"; +import PageHeader, { IPageHeaderProps } from "../../components/UI/PageHeader.component"; + +export default { + title: "PageHeader", + component: PageHeader, +} as Meta; + +const Template: Story = (args) => ; + +export const BasicText = Template.bind({}); +BasicText.args = { + children: "Welcome to My Page", +}; + +export const WithHtmlElements = Template.bind({}); +WithHtmlElements.args = { + children: ( + <> + Welcome to My Page + + ), +}; + +export const LongText = Template.bind({}); +LongText.args = { + children: "This is a longer page header that demonstrates how the component handles more content", +}; From b2093f14257c0779fdc105824ddda3a71f1ada70 Mon Sep 17 00:00:00 2001 From: w3bdesign <45217974+w3bdesign@users.noreply.github.com> Date: Wed, 4 Dec 2024 04:00:05 +0100 Subject: [PATCH 3/8] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20story=20files=20f?= =?UTF-8?q?or=20SkipLink=20and=20Tabs=20components?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create comprehensive Storybook examples for accessibility-focused components, demonstrating various use cases and implementations for both SkipLink and Tabs to improve component documentation and testing capabilities. --- src/stories/components/SkipLink.stories.tsx | 41 +++++++++ src/stories/components/Tabs.stories.tsx | 97 +++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 src/stories/components/SkipLink.stories.tsx create mode 100644 src/stories/components/Tabs.stories.tsx diff --git a/src/stories/components/SkipLink.stories.tsx b/src/stories/components/SkipLink.stories.tsx new file mode 100644 index 00000000..e840c118 --- /dev/null +++ b/src/stories/components/SkipLink.stories.tsx @@ -0,0 +1,41 @@ +import React from "react"; +import { Meta, Story } from "@ladle/react"; +import SkipLink from "../../components/UI/SkipLink.component"; + +export default { + title: "SkipLink", + component: SkipLink, +} as Meta; + +// Basic template +const Template: Story = () => ; + +export const Default = Template.bind({}); + +// Story showing the skip link in context +export const WithContext = () => ( +
+ +
+ +
+
+

Main Content

+

This story demonstrates the SkipLink in context with a page layout.

+

Tab to focus on the SkipLink - it will appear at the top of the page.

+
+
+); + +// Story with focus styles visible +export const Focused = () => ( +
+
+ +
+

+ This story shows how the SkipLink appears when focused. + The skip link is permanently visible here for demonstration purposes. +

+
+); diff --git a/src/stories/components/Tabs.stories.tsx b/src/stories/components/Tabs.stories.tsx new file mode 100644 index 00000000..29f4c668 --- /dev/null +++ b/src/stories/components/Tabs.stories.tsx @@ -0,0 +1,97 @@ +import React from "react"; +import { Meta, Story } from "@ladle/react"; +import Tabs from "../../components/UI/Tabs.component"; + +export default { + title: "Tabs", + component: Tabs, +} as Meta; + +const Template: Story> = (args) => ( + +); + +// Sample content components +const TextContent = () => ( +
+

Text Content

+

+ This is a sample text content for the tab panel. It demonstrates how text + content is displayed within the tabs component. +

+
+); + +const ListContent = () => ( +
+

List Content

+
    +
  • First item in the list
  • +
  • Second item in the list
  • +
  • Third item in the list
  • +
+
+); + +const FormContent = () => ( +
+

Form Content

+
+
+ + +
+
+ + +
+
+
+); + +export const VerticalTabs = Template.bind({}); +VerticalTabs.args = { + orientation: "vertical", + tabs: [ + { id: "tab1", label: "Text", content: }, + { id: "tab2", label: "List", content: }, + { id: "tab3", label: "Form", content: }, + ], +}; + +export const HorizontalTabs = Template.bind({}); +HorizontalTabs.args = { + orientation: "horizontal", + tabs: [ + { id: "tab1", label: "Text", content: }, + { id: "tab2", label: "List", content: }, + { id: "tab3", label: "Form", content: }, + ], +}; + +export const ManyTabs = Template.bind({}); +ManyTabs.args = { + tabs: [ + { id: "tab1", label: "Tab 1", content: }, + { id: "tab2", label: "Tab 2", content: }, + { id: "tab3", label: "Tab 3", content: }, + { id: "tab4", label: "Tab 4", content: }, + { id: "tab5", label: "Tab 5", content: }, + ], +}; + +export const TwoTabs = Template.bind({}); +TwoTabs.args = { + tabs: [ + { id: "tab1", label: "First Tab", content: }, + { id: "tab2", label: "Second Tab", content: }, + ], +}; From 19a4afd62a8e1ad3daeb40d4a23468f1ed38f064 Mon Sep 17 00:00:00 2001 From: w3bdesign <45217974+w3bdesign@users.noreply.github.com> Date: Wed, 4 Dec 2024 04:05:38 +0100 Subject: [PATCH 4/8] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20BounceInScroll=20?= =?UTF-8?q?component=20story=20examples?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BounceInScroll story examples showcase various animation configurations, including instant animation, view triggers, and custom styling options. These examples help document component usage patterns. --- .../components/BounceInScroll.stories.tsx | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/stories/components/BounceInScroll.stories.tsx diff --git a/src/stories/components/BounceInScroll.stories.tsx b/src/stories/components/BounceInScroll.stories.tsx new file mode 100644 index 00000000..0714954c --- /dev/null +++ b/src/stories/components/BounceInScroll.stories.tsx @@ -0,0 +1,86 @@ +import React from "react"; +import { Meta, Story } from "@ladle/react"; +import BounceInScroll from "../../components/Animations/BounceInScroll.component"; +import { IAnimateBounceProps } from "../../components/Animations/types/Animations.types"; + +export default { + title: "Animations/BounceInScroll", + component: BounceInScroll, +} as Meta; + +const Template: Story = (args) => ( +
+
+ ⬇️ Scroll down to see the animation +
+ +
+); + +const Card = () => ( +
+

Animated Card

+

+ This card demonstrates the BounceInScroll animation component. +

+
+); + +export const Default = Template.bind({}); +Default.args = { + children: , + viewAmount: 0.2, +}; + +export const InstantAnimation = Template.bind({}); +InstantAnimation.args = { + children: , + instant: true, +}; + +export const FullViewTrigger = Template.bind({}); +FullViewTrigger.args = { + children: , + viewAmount: "all", +}; + +export const PartialViewTrigger = Template.bind({}); +PartialViewTrigger.args = { + children: , + viewAmount: "some", +}; + +export const CustomViewAmount = Template.bind({}); +CustomViewAmount.args = { + children: , + viewAmount: 0.5, +}; + +export const WithCustomClass = Template.bind({}); +WithCustomClass.args = { + children: , + cssClass: "max-w-md mx-auto", +}; + +export const LargeContent = Template.bind({}); +LargeContent.args = { + children: ( +
+ + + +
+ ), + viewAmount: 0.2, +}; + +export const TextContent = Template.bind({}); +TextContent.args = { + children: ( +
+

Welcome

+

This is a simple text animation example.

+
+ ), + viewAmount: 0.2, +}; From ab8f814eee4cf8c697c0ee653e563f242532df76 Mon Sep 17 00:00:00 2001 From: w3bdesign <45217974+w3bdesign@users.noreply.github.com> Date: Wed, 4 Dec 2024 04:10:44 +0100 Subject: [PATCH 5/8] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20matrix=20cursor?= =?UTF-8?q?=20stories=20for=20component=20visualization?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added comprehensive storybook stories for MatrixCursor component to showcase various interaction scenarios and use cases through interactive examples. --- .../components/MatrixCursor.stories.tsx | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/stories/components/MatrixCursor.stories.tsx diff --git a/src/stories/components/MatrixCursor.stories.tsx b/src/stories/components/MatrixCursor.stories.tsx new file mode 100644 index 00000000..3500382d --- /dev/null +++ b/src/stories/components/MatrixCursor.stories.tsx @@ -0,0 +1,116 @@ +import React, { useRef } from "react"; +import { Meta } from "@ladle/react"; +import MatrixCursor from "../../components/Animations/MatrixCursor.component"; +import "../../app/cursor.css"; + +export default { + title: "Animations/MatrixCursor", + component: MatrixCursor, +} as Meta; + +const DemoContainer = ({ children }: { children: React.ReactNode }) => { + const heroRef = useRef(null); + + return ( + <> +
+ {children} + +
+ + ); +}; + +export const Default = () => ( + +
+

Matrix Cursor Demo

+

Move your mouse around this container to see the matrix cursor effect.

+

The cursor will change and leave a trail of matrix characters.

+
+
+

Hover Area 1

+

+ Move your cursor here to see the effect in action +

+
+
+

Hover Area 2

+

+ Try moving between different areas to see the trail +

+
+
+
+
+); + +export const WithInteractiveElements = () => ( + +
+

+ Interactive Elements Demo +

+ +
+

+ The matrix cursor effect works seamlessly with interactive elements. + Try hovering over the buttons above. +

+
+
+
+); + +export const LargeArea = () => ( + +
+
+

Large Area Demo

+

+ This demo shows how the matrix cursor effect works in a larger area. +
+ Move your cursor around to create longer trails. +

+
+
+
+); + +export const WithContent = () => ( + +
+

Content Interaction

+
+ {[1, 2, 3].map((i) => ( +
+

Card {i}

+

+ Hover over this card to see how the matrix cursor interacts with content. +

+
+ ))} +
+
+

+ The matrix cursor effect adds a unique interactive element to your content. + Try moving between different cards to see how the trail follows your movement. +

+
+
+
+); From 51d76f78a6ada6a4046d54392876fcb14f78855f Mon Sep 17 00:00:00 2001 From: w3bdesign <45217974+w3bdesign@users.noreply.github.com> Date: Wed, 4 Dec 2024 04:12:39 +0100 Subject: [PATCH 6/8] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20GenericForm=20sto?= =?UTF-8?q?ries=20with=20multiple=20form=20variations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces Storybook stories for the GenericForm component, showcasing various form implementations including contact, subscribe, feedback, and simple forms. Each story demonstrates different schema validations and field configurations. --- .../components/GenericForm.stories.tsx | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 src/stories/components/GenericForm.stories.tsx diff --git a/src/stories/components/GenericForm.stories.tsx b/src/stories/components/GenericForm.stories.tsx new file mode 100644 index 00000000..fc3b1288 --- /dev/null +++ b/src/stories/components/GenericForm.stories.tsx @@ -0,0 +1,149 @@ +import React from "react"; +import { Meta } from "@ladle/react"; +import { z } from "zod"; +import GenericForm from "../../components/UI/GenericForm.component"; + +export default { + title: "GenericForm", + component: GenericForm, +} as Meta; + +// Example schemas +const contactSchema = z.object({ + name: z.string().min(2, "Name must be at least 2 characters"), + email: z.string().email("Invalid email address"), + message: z.string().min(10, "Message must be at least 10 characters"), +}); + +const subscribeSchema = z.object({ + email: z.string().email("Invalid email address"), + preferences: z.string().min(1, "Please select your preferences"), +}); + +const feedbackSchema = z.object({ + title: z.string().min(3, "Title must be at least 3 characters"), + rating: z.string().regex(/^[1-5]$/, "Rating must be between 1 and 5"), + feedback: z.string().min(20, "Feedback must be at least 20 characters"), +}); + +type FormData = z.infer | + z.infer | + z.infer | + { email: string }; + +// Example async submit handlers +const mockSubmit = async (data: FormData) => { + await new Promise((resolve) => setTimeout(resolve, 1000)); + console.log("Form submitted:", data); +}; + +// Contact Form Story +export const ContactForm = () => ( +
+

Contact Us

+ +
+); + +// Subscribe Form Story +export const SubscribeForm = () => ( +
+

Subscribe to Newsletter

+ +
+); + +// Feedback Form Story +export const FeedbackForm = () => ( +
+

Provide Feedback

+ +
+); + +// Simple Form Story +export const SimpleForm = () => ( +
+

Quick Contact

+ +
+); From b21b88384258693e9c9c9f64d2b16316a829414a Mon Sep 17 00:00:00 2001 From: w3bdesign <45217974+w3bdesign@users.noreply.github.com> Date: Wed, 4 Dec 2024 04:14:02 +0100 Subject: [PATCH 7/8] =?UTF-8?q?=F0=9F=8E=A8=20style:=20simplify=20matrix?= =?UTF-8?q?=20cursor=20story=20container=20structure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes unnecessary fragment wrapper and improves text formatting in storybook examples for better readability and maintainability of stories --- .../components/MatrixCursor.stories.tsx | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/stories/components/MatrixCursor.stories.tsx b/src/stories/components/MatrixCursor.stories.tsx index 3500382d..51151350 100644 --- a/src/stories/components/MatrixCursor.stories.tsx +++ b/src/stories/components/MatrixCursor.stories.tsx @@ -12,15 +12,13 @@ const DemoContainer = ({ children }: { children: React.ReactNode }) => { const heroRef = useRef(null); return ( - <> -
- {children} - -
- +
+ {children} + +
); }; @@ -28,7 +26,9 @@ export const Default = () => (

Matrix Cursor Demo

-

Move your mouse around this container to see the matrix cursor effect.

+

+ Move your mouse around this container to see the matrix cursor effect. +

The cursor will change and leave a trail of matrix characters.

@@ -94,21 +94,28 @@ export const LargeArea = () => ( export const WithContent = () => (
-

Content Interaction

+

+ Content Interaction +

{[1, 2, 3].map((i) => ( -
+

Card {i}

- Hover over this card to see how the matrix cursor interacts with content. + Hover over this card to see how the matrix cursor interacts with + content.

))}

- The matrix cursor effect adds a unique interactive element to your content. - Try moving between different cards to see how the trail follows your movement. + The matrix cursor effect adds a unique interactive element to your + content. Try moving between different cards to see how the trail + follows your movement.

From ca368bdf46b2cb141b46065a1f9f05c23fbe5929 Mon Sep 17 00:00:00 2001 From: w3bdesign <45217974+w3bdesign@users.noreply.github.com> Date: Wed, 4 Dec 2024 04:17:50 +0100 Subject: [PATCH 8/8] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20matrix=20animatio?= =?UTF-8?q?n=20stories=20and=20variants?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces comprehensive storybook examples for the matrix animation component, showcasing various configurations including custom colors, tile sizes, and animation speeds for improved component documentation. --- src/stories/components/Matrix.stories.tsx | 120 ++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/stories/components/Matrix.stories.tsx diff --git a/src/stories/components/Matrix.stories.tsx b/src/stories/components/Matrix.stories.tsx new file mode 100644 index 00000000..2d35299e --- /dev/null +++ b/src/stories/components/Matrix.stories.tsx @@ -0,0 +1,120 @@ +import React, { useEffect, useState } from "react"; +import { Meta } from "@ladle/react"; + +export default { + title: "Animations/Matrix", +} as Meta; + +// Client-side only wrapper component +const ClientOnlyMatrix = (props: any) => { + const [Matrix, setMatrix] = useState(null); + + useEffect(() => { + import("../../components/Animations/Matrix.component").then((mod) => { + setMatrix(() => mod.default); + }); + }, []); + + if (!Matrix) { + return
Loading Matrix...
; + } + + return ; +}; + +const Container = ({ children }: { children: React.ReactNode }) => ( +
+ {children} +
+); + +// Basic story with default props +export const Default = () => ( + + + +); + +// Story with custom colors +export const CustomColors = () => ( + + + +); + +// Story with larger tiles +export const LargeTiles = () => ( + + + +); + +// Story with smaller tiles +export const SmallTiles = () => ( + + + +); + +// Story with binary characters +export const BinaryMatrix = () => ( + + + +); + +// Story with slow fade effect +export const SlowFade = () => ( + + + +); + +// Story with blue theme +export const BlueTheme = () => ( + + + +); + +// Story with purple theme +export const PurpleTheme = () => ( + + + +);