Skip to content

Commit

Permalink
add sample components
Browse files Browse the repository at this point in the history
  • Loading branch information
apella1 committed Apr 5, 2024
1 parent 1612d64 commit f35578d
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 8 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@

- Run `yarn` to install the dependencies.
- Run `yarn start` to start the development server.

## Running Tests

- Run `yarn test` to run all the tests on the terminal.
- Run `yarn test:ui` to run all the tests both on the terminal and using Vitest UI.
4 changes: 2 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import HelloWorld from "./components/HelloWorld";

function App() {
return (
<section className="flex flex-col justify-center items-center min-h-screen">
<div>
<section className="flex flex-col justify-center items-center min-h-screen px-8 md:px-16 lg:px-24 xl:px-44 2xl:px-60">
<div className="flex flex-col space-y-8 w-full">
<HelloWorld />
</div>
</section>
Expand Down
10 changes: 10 additions & 0 deletions src/components/BasicList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default function BasicList({ items }: { items: string[] }) {
if (items.length === 0) return <p>No items provided.</p>;
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}
31 changes: 31 additions & 0 deletions src/components/Form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { ChangeEvent, useState } from "react";
import CustomInput from "./ui/Input";
import Button from "./ui/Button";

export default function Form() {
const [firstName, setFirstName] = useState("");

const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const { value } = e.target;
setFirstName(value);
};

return (
<form action="" className="flex flex-col space-y-5">
<div className="self-center flex flex-col space-y-5">
<CustomInput
input={{
type: "text",
name: "firstName",
label: "First Name",
inputId: "first-name",
value: firstName,
onChange: handleChange,
placeholder: "Enter First Name",
}}
/>
<Button button={{ text: "Submit", type: "submit" }} />
</div>
</form>
);
}
4 changes: 2 additions & 2 deletions src/components/HelloWorld.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export default function HelloWorld({ text }: { text?: string }) {
if (text) return <h1 className="text-2xl font-medium">{text}</h1>;
if (text) return <h1 className="text-2xl font-medium self-center">{text}</h1>;
return (
<p role="paragraph" className="text-2xl font-medium">
<p role="paragraph" className="text-2xl font-medium self-center">
Providing a sample text would&apos;ve been great.
</p>
);
Expand Down
13 changes: 13 additions & 0 deletions src/components/ImagesList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default function ImagesList({ imageUrls }: { imageUrls: string[] }) {
if (imageUrls.length === 0) return null;

return (
<ul>
{imageUrls.map((url) => (
<li key={url}>
<img src={url} alt="" />
</li>
))}
</ul>
);
}
38 changes: 38 additions & 0 deletions src/components/ProductDescriptionToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useState } from "react";
import Button from "./ui/Button";

export default function ProductDescriptionToggle({
description,
}: {
description: string;
}) {
const [isFullDescriptionVisible, setIsFullDescriptionVisible] =
useState(true);

const toggleDescription = () => {
setIsFullDescriptionVisible(!isFullDescriptionVisible);
};

return (
<div className="flex flex-col space-y-4">
<h4 className="text-3xl font-medium self-center">Product Description</h4>
<div className="text-base flex flex-col space-y-5 text-center">
{description.length < 150 ? (
<p>{description}</p>
) : isFullDescriptionVisible ? (
<p>{description}</p>
) : (
<div>
<p>{description.substring(0, 150)}... </p>
</div>
)}
<Button
button={{
text: isFullDescriptionVisible ? "Read Less" : "Read More",
onClick: toggleDescription,
}}
/>
</div>
</div>
);
}
35 changes: 35 additions & 0 deletions src/components/UserAgreement.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useState } from "react";
import Button from "./ui/Button";

export default function UserAgreement() {
const [hasAgreed, setHasAgreed] = useState(false);

const handleAgreementChange = () => {
setHasAgreed(!hasAgreed);
};

return (
<div className="flex flex-col space-y-5">
<h1 className="self-center text-3xl font-medium text-black">
User Agreement
</h1>
<p className="text-base text-blue-700 self-center">
Please review the following agreement before proceeding. This agreement
outlines the terms and conditions for using our service.
</p>
<div className="pb-3 self-center">
<label htmlFor="agree">
<input
type="checkbox"
id="agree"
checked={hasAgreed}
onChange={handleAgreementChange}
className="mr-1"
/>
I agree to the terms and conditions.
</label>
</div>
<Button button={{ text: "Continue", disabled: !hasAgreed }} />
</div>
);
}
16 changes: 14 additions & 2 deletions src/components/ui/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
export default function Button() {
return <button className="">Button</button>;
import { ButtonProps } from "../../types/components";

export default function Button({ button }: { button: ButtonProps }) {
const { onClick, text, type, disabled } = button;
return (
<button
disabled={disabled ?? false}
type={type}
onClick={onClick}
className="bg-purple-600 disabled:bg-gray-400 px-36 py-2 text-sm lg:text-lg font-medium text-white rounded-xl w-fit self-center"
>
{text}
</button>
);
}
37 changes: 35 additions & 2 deletions src/components/ui/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
export default function Input() {
return <input className="" type="" />;
import { InputProps } from "../../types/components";

export default function CustomInput({ input }: { input: InputProps }) {
const {
inputId,
type,
name,
placeholder,
value,
label,
onChange,
disabled,
} = input;
return (
<div className={`${label ? "flex flex-col space-y-3" : ""}`}>
{label && (
<label
htmlFor={inputId}
className="text-onSurface text-base font-medium"
>
{label}
</label>
)}
<input
disabled={disabled ?? false}
type={type}
name={name}
id={inputId}
placeholder={placeholder}
value={value}
onChange={onChange}
className="w-full border border-surface py-3 px-4 xl:py-5 text-onSurface text-sm rounded-lg placeholder:text-onSurface-light placeholder:text-sm"
/>
</div>
);
}
40 changes: 40 additions & 0 deletions src/types/components.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
type InputType =
| "button"
| "checkbox"
| "color"
| "date"
| "datetime-local"
| "email"
| "hidden"
| "image"
| "month"
| "number"
| "password"
| "radio"
| "range"
| "reset"
| "search"
| "submit"
| "tel"
| "text"
| "time"
| "url"
| "week";

export interface InputProps {
inputId: string;
type: InputType;
placeholder: string;
value: string | number | undefined;
label?: string;
name: string;
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
disabled?: boolean;
}

export interface ButtonProps {
onClick?: () => void;
text: string;
type?: "submit" | "button" | "reset";
disabled?: boolean;
}

0 comments on commit f35578d

Please sign in to comment.