diff --git a/src/components/BlogSection/BlogSection.js b/src/components/BlogSection/BlogSection.js
new file mode 100644
index 0000000..584f4eb
--- /dev/null
+++ b/src/components/BlogSection/BlogSection.js
@@ -0,0 +1,152 @@
+import React from "react";
+
+import PropTypes from "prop-types";
+
+function classNames(...classes) {
+ return classes.filter(Boolean).join(" ");
+}
+
+export default function BlogSection({
+ title,
+ subtitle,
+ posts = [],
+ variants = "grid-image",
+ orientation = "row",
+}) {
+ const containerClasses = classNames(
+ "bg-white py-20 sm:py-28",
+ orientation === "column" ? "max-w-2xl lg:max-w-4xl" : "max-w-7xl"
+ );
+
+ const headerClasses = classNames(
+ "text-balance text-4xl font-semibold tracking-tight text-gray-900 sm:text-5xl",
+ orientation !== "column" && "text-center"
+ );
+
+ const gridClasses = classNames(
+ orientation === "column"
+ ? "mt-10 space-y-16 border-t border-gray-200 pt-10 sm:mt-16 sm:pt-16"
+ : "mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-x-8 gap-y-20 lg:mx-0 lg:max-w-none lg:grid-cols-3",
+ variants === "grid-text" && "border-t border-gray-200"
+ );
+
+ return (
+
+
+
+
{title}
+ {subtitle && (
+
{subtitle}
+ )}
+
+
+ {posts?.map((post) => (
+
+ {variants === "grid-image" && (
+
+

+
+
+ )}
+
+
+
+
+
+ {post.description}
+
+
+
+

+
+
+
+
+ ))}
+
+
+
+ );
+}
+
+BlogSection.propTypes = {
+ title: PropTypes.string.isRequired,
+ subtitle: PropTypes.string,
+ posts: PropTypes.arrayOf(
+ PropTypes.shape({
+ id: PropTypes.number.isRequired,
+ title: PropTypes.string.isRequired,
+ href: PropTypes.string.isRequired,
+ description: PropTypes.string.isRequired,
+ imageUrl: PropTypes.string.isRequired,
+ date: PropTypes.string.isRequired,
+ datetime: PropTypes.string.isRequired,
+ category: PropTypes.shape({
+ title: PropTypes.string.isRequired,
+ href: PropTypes.string.isRequired,
+ }).isRequired,
+ author: PropTypes.shape({
+ name: PropTypes.string.isRequired,
+ role: PropTypes.string.isRequired,
+ href: PropTypes.string.isRequired,
+ imageUrl: PropTypes.string.isRequired,
+ }).isRequired,
+ })
+ ).isRequired,
+ variants: PropTypes.oneOf(["grid-image", "grid-text"]),
+ orientation: PropTypes.oneOf(["row", "column"]),
+};
+
+// ImageGrid.defaultProps = {
+// subtitle: "",
+// variants: "grid-image",
+// orientation: "row",
+// };
diff --git a/src/components/BlogSection/BlogSection.stories.js b/src/components/BlogSection/BlogSection.stories.js
new file mode 100644
index 0000000..a63b142
--- /dev/null
+++ b/src/components/BlogSection/BlogSection.stories.js
@@ -0,0 +1,97 @@
+import BlogSection from "./BlogSection";
+import { fn } from "@storybook/test";
+
+export default {
+ title: "Marketing/BlogSection",
+ component: BlogSection,
+ argTypes: {
+ title: { control: "text" },
+ subtitle: { control: "text" },
+ variants: {
+ control: {
+ type: "select",
+ options: ["grid-image", "grid-text"], // Define available options
+ },
+ description: "Choose between displaying a grid of images or text.",
+ },
+ orientation: {
+ control: {
+ type: "select",
+ options: ["row", "column"], // Define available options
+ },
+ description: "Set the layout orientation for the grid.",
+ },
+ },
+ tags: ["autodocs"],
+};
+
+const posts = [
+ {
+ id: 1,
+ title: "Boost your conversion rate",
+ href: "#",
+ description:
+ "Illo sint voluptas. Error voluptates culpa eligendi. Hic vel totam vitae illo. Non aliquid explicabo necessitatibus unde. Sed exercitationem placeat consectetur nulla deserunt vel. Iusto corrupti dicta.",
+ imageUrl:
+ "https://images.unsplash.com/photo-1496128858413-b36217c2ce36?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3603&q=80",
+ date: "Mar 16, 2020",
+ datetime: "2020-03-16",
+ category: { title: "Marketing", href: "#" },
+ author: {
+ name: "Michael Foster",
+ role: "Co-Founder / CTO",
+ href: "#",
+ imageUrl:
+ "https://images.unsplash.com/photo-1519244703995-f4e0f30006d5?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80",
+ },
+ },
+ {
+ id: 2,
+ title: "How to use search engine optimization to drive sales",
+ href: "#",
+ description:
+ "Optio cum necessitatibus dolor voluptatum provident commodi et. Qui aperiam fugiat nemo cumque.",
+ imageUrl:
+ "https://images.unsplash.com/photo-1496128858413-b36217c2ce36?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3603&q=80",
+ date: "Mar 10, 2020",
+ datetime: "2020-03-16",
+ category: { title: "Sales", href: "#" },
+ author: {
+ name: "Michael Foster",
+ role: "Co-Founder / CTO",
+ href: "#",
+ imageUrl:
+ "https://images.unsplash.com/photo-1547586696-ea22b4d4235d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80",
+ },
+ },
+ {
+ id: 3,
+ title: "Boost your conversion rate",
+ href: "#",
+ description:
+ "Illo sint voluptas. Error voluptates culpa eligendi. Hic vel totam vitae illo. Non aliquid explicabo necessitatibus unde. Sed exercitationem placeat consectetur nulla deserunt vel. Iusto corrupti dicta.",
+ imageUrl:
+ "https://images.unsplash.com/photo-1492724441997-5dc865305da7?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80",
+ date: "Mar 16, 2020",
+ datetime: "2020-03-16",
+ category: { title: "Marketing", href: "#" },
+ author: {
+ name: "Michael Foster",
+ role: "Co-Founder / CTO",
+ href: "#",
+ imageUrl:
+ "https://images.unsplash.com/photo-1519244703995-f4e0f30006d5?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80",
+ },
+ },
+ // More posts...
+];
+
+export const Primary = {
+ args: {
+ title: "From the blog",
+ subtitle: "Learn how to grow your business with our expert advice.",
+ posts: posts,
+ variants: "grid-text",
+ orientation: "column",
+ },
+};
diff --git a/src/components/Input/Input.js b/src/components/Input/Input.js
new file mode 100644
index 0000000..026d20e
--- /dev/null
+++ b/src/components/Input/Input.js
@@ -0,0 +1,151 @@
+import { ExclamationCircleIcon } from "@heroicons/react/20/solid";
+import PropTypes from "prop-types";
+import React from "react";
+
+/**
+ * @typedef {Object} InputFieldProps
+ * @property {string} [label]
+ * @property {string} [helperText]
+ * @property {string} [placeholder]
+ * @property {string} [type]
+ * @property {string} [value]
+ * @property {boolean} [isError]
+ * @property {boolean} [disabled]
+ * @property {string} [labelHint]
+ * @property {React.ReactNode} [leadingIcon]
+ * @property {React.ReactNode} [trailingIcon]
+ * @property {(e: React.ChangeEvent) => void} [onChange]
+ */
+
+const inputClass = {
+ error: "text-red-900 ring-red-300 focus:ring-red-500",
+ default: "text-gray-900 ring-gray-300 focus:ring-primary-600",
+};
+
+const helperTextClass = {
+ error: "text-red-600",
+ default: "text-gray-500",
+};
+
+/**
+ * @param {InputFieldProps} props
+ */
+
+export default function InputField({
+ label,
+ helperText,
+ isError,
+ disabled,
+ labelHint,
+ leadingIcon,
+ trailingIcon,
+ placeholder,
+ value,
+ type,
+ onChange,
+}) {
+ return (
+
+
+ {label && (
+
+ )}
+ {labelHint && (
+
+ {labelHint}
+
+ )}
+
+
+
+ {leadingIcon && (
+
+ {leadingIcon}
+
+ )}
+
+
+ {isError && (
+
+ )}
+ {!isError && trailingIcon && (
+
+ {trailingIcon}
+
+ )}
+
+
+ {helperText && (
+
+ {helperText}
+
+ )}
+
+ );
+}
+
+InputField.propTypes = {
+ /** The text label displayed above the input field */
+ label: PropTypes.string,
+
+ /** A short helper text displayed below the input field for additional information */
+ helperText: PropTypes.string,
+
+ /** Placeholder text displayed inside the input field when it's empty */
+ placeholder: PropTypes.string,
+
+ /** The type of input field, e.g., 'text', 'password', etc. */
+ type: PropTypes.string,
+
+ /** The current value of the input field */
+ value: PropTypes.string,
+
+ /** If true, displays the input field in an error state */
+ isError: PropTypes.bool,
+
+ /** If true, disables the input field, making it non-interactive */
+ disabled: PropTypes.bool,
+
+ /** Additional hint text displayed next to the label */
+ labelHint: PropTypes.string,
+
+ /** An optional icon component displayed at the beginning of the input field */
+ leadingIcon: PropTypes.element,
+
+ /** An optional icon component displayed at the end of the input field */
+ trailingIcon: PropTypes.element,
+
+ /** Callback function triggered when the input field's value changes */
+ onChange: PropTypes.func,
+};
diff --git a/src/components/Input/Input.stories.js b/src/components/Input/Input.stories.js
new file mode 100644
index 0000000..d72e297
--- /dev/null
+++ b/src/components/Input/Input.stories.js
@@ -0,0 +1,125 @@
+import {
+ EnvelopeIcon,
+ QuestionMarkCircleIcon,
+} from "@heroicons/react/20/solid";
+import InputField from "./Input";
+import { fn } from "@storybook/test";
+
+export default {
+ title: "Atom/Input",
+ component: InputField,
+ argTypes: {
+ label: { control: "text" },
+ helperText: { control: "text" },
+ placeholder: { control: "text" },
+ type: { control: "text" },
+ value: { control: "text" },
+ labelHint: { control: "text" },
+ isError: { control: "boolean" },
+ disabled: { control: "boolean" },
+ leadingIcon: {
+ control: "object",
+ },
+ trailingIcon: {
+ control: "object",
+ },
+ },
+ args: { onChange: fn() },
+ tags: ["autodocs"],
+};
+
+export const Primary = {
+ args: {
+ label: "Email",
+ helperText: "We'll only use this for spam.",
+ placeholder: "say something",
+ isError: false,
+ disabled: false,
+ labelHint: "Optional",
+ type: "email",
+ onChange: fn(),
+ leadingIcon: (
+
+ ),
+ trailingIcon: (
+
+ ),
+ },
+};
+
+export const Input_with_label = {
+ args: {
+ label: "Email",
+ placeholder: "say something",
+ },
+};
+
+export const Input_with_help_text = {
+ args: {
+ label: "Email",
+ placeholder: "say something",
+ helperText: "We'll only use this for spam.",
+ },
+};
+
+export const Input_with_validation_error = {
+ args: {
+ label: "Email",
+ placeholder: "say something",
+ helperText: "Not a valid email address.",
+ value: "adityacom",
+ isError: true,
+ },
+};
+
+export const Input_with_disabled_state = {
+ args: {
+ label: "Email",
+ placeholder: "say something",
+ value: "you@example.com",
+ disabled: true,
+ },
+};
+
+export const Input_without_label = {
+ args: {
+ value: "you@example.com",
+ },
+};
+
+export const Input_with_label_hint = {
+ args: {
+ label: "Email",
+ placeholder: "say something",
+ value: "you@example.com",
+ labelHint: "Optional",
+ },
+};
+
+export const Input_with_leading_icon = {
+ args: {
+ label: "Email",
+ placeholder: "say something",
+ value: "you@example.com",
+ leadingIcon: (
+
+ ),
+ },
+};
+
+export const Input_with_trailing_icon = {
+ args: {
+ label: "Email",
+ placeholder: "say something",
+ value: "you@example.com",
+ trailingIcon: (
+
+ ),
+ },
+};