Skip to content

Commit

Permalink
feat(luna): impl. input component
Browse files Browse the repository at this point in the history
  • Loading branch information
neuodev committed Aug 7, 2024
1 parent 934be31 commit 27ee460
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 60 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ jobs:
- name: Pull Luna from Vercel
run: yarn vercel:ci pull "luna" "luna/" --token=${{ secrets.VERCEL_TOKEN }}
- name: Build Luna using Vercel
run: yarn build:luna:vercel
run: yarn build:luna:vercel --prod
- name: Deploy Luna to Vercel
run: yarn deploy:luna:vercel --token=${{ secrets.VERCEL_TOKEN }}
run: yarn deploy:luna:vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
# Nebula Deployment
- name: Pull Nebula from Vercel
run: yarn vercel:ci pull "nebula" "nebula/" --token=${{ secrets.VERCEL_TOKEN }}
Expand Down
20 changes: 12 additions & 8 deletions luna/src/components/Input/Input.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import type { Meta, StoryObj } from "@storybook/react";

import { Input } from "@/components/Input";
import { Form } from "@/components/Form";
import React, { ComponentProps } from "react";
import { Direction } from "@/components/Direction";
import ar from "@/locales/ar-eg.json";

const Wrapper: React.FC<ComponentProps<typeof Input>> = (props) => {
return (
<Direction>
<div className="ui-w-80">
<Form>
<Input {...props} />
</Form>
<div className="ui-w-[40rem]">
<Input {...props} />
</div>
</Direction>
);
Expand All @@ -21,16 +18,23 @@ const Wrapper: React.FC<ComponentProps<typeof Input>> = (props) => {
const meta: Meta<typeof Input> = {
title: "Input",
component: Wrapper,
parameters: {
layout: "centered",
parameters: { layout: "centered" },
};

export const Idle: StoryObj<typeof Wrapper> = {
args: {
id: "name",
label: ar["global.form.email.label"],
placeholder: ar["global.form.email.placeholder"],
},
};

export const Primary: StoryObj<typeof Wrapper> = {
export const Error: StoryObj<typeof Wrapper> = {
args: {
id: "name",
label: ar["global.form.email.label"],
placeholder: ar["global.form.email.placeholder"],
error: ar["errors.email.invlaid"],
},
};

Expand Down
84 changes: 38 additions & 46 deletions luna/src/components/Input/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useMemo } from "react";
import { FieldValues, RegisterOptions, useFormContext } from "react-hook-form";
import React from "react";
import { ChangeHandler } from "react-hook-form";
import { motion, AnimatePresence } from "framer-motion";
import cn from "classnames";

Expand All @@ -9,67 +9,59 @@ export const Input: React.FC<{
placeholder?: string;
autoComplete?: string;
type: "text" | "password";
validation?: RegisterOptions<FieldValues>;
}> = ({ label, type, id, placeholder, autoComplete, validation }) => {
const {
register,
formState: { errors },
} = useFormContext();

const error = errors[id];

const errorMessage = useMemo(() => {
if (!error) return null;
const mesage = error.message;
if (!mesage || typeof mesage !== "string") return null;
return mesage;
}, [error]);

onChange?: ChangeHandler;
onBlur?: ChangeHandler;
name?: string;
error?: string | null;
}> = ({
label,
type,
id,
placeholder,
autoComplete,
onChange,
onBlur,
name,
error,
}) => {
return (
<div className="ui-flex ui-flex-col ui-w-full ui-gap-2">
<div className="ui-flex ui-flex-row">
<label
htmlFor={id}
className={cn("ui-font-semibold", {
"ui-text-red-400": !!error,
"ui--text-gray-800": !error,
})}
>
{label}
</label>
<AnimatePresence mode="wait" initial={false}>
{errorMessage ? (
<InputError message={errorMessage} key={label} />
) : null}
</AnimatePresence>
</div>
<div className="ui-flex ui-flex-col ui-w-full">
<label
htmlFor={id}
className={cn(
"ui-text-dark-100 ui-font-cairo ui-font-bold ui-text-arxl ui-leading-normal ui-mb-xl"
)}
>
{label}
</label>
<input
id={id}
type={type}
name={name}
autoComplete={autoComplete}
onChange={onChange}
onBlur={onBlur}
className={cn(
"ui-w-full ui-p-2 ui-font-medium ui-border ui-rounded-md ui-placeholder:opacity-60 focus:ui-outline-none focus:ui-ring-1",
"ui-bg-inputbg ui-py-[10px] ui-px-lg ui-rounded-2xl ui-h-[72px] ui-font-cairo placeholder:ui-text-arxl placeholder:ui-font-medium ui-leading-normal",
"ui-text-arxl ui-font-bold ui-leading-normal ui-border focus:ui-outline-none focus:ui-border-blue-normal",
{
"ui-border-red-400 ui-placeholder-red-400 ui-ring-red-400": !!error,
"ui-border-slate-300 ui-ring-slate-600": !error,
"ui-bg-red-light ui-border-red-border focus:ui-border-red-border":
!!error,
"ui-border-transparent": !error,
}
)}
placeholder={placeholder}
{...register(id, validation)}
/>
<AnimatePresence mode="wait" initial={false}>
{error ? <InputError message={error} key={label} /> : null}
</AnimatePresence>
</div>
);
};

const InputError: React.FC<{ message: string }> = ({ message }) => {
return (
<motion.p
className="ui-flex ui-items-center ui-italic ui-text-sm ui-text-red-400"
{...framerError}
>
<span className={cn("ui-mx-1 ui-inline-block ui-text-red-400")}>
&mdash;
</span>
<motion.p className="ui-text-arsm ui-text-red-400" {...framerError}>
{message}
</motion.p>
);
Expand Down
2 changes: 1 addition & 1 deletion luna/src/locales/ar-eg.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"page.select.type.options.student": "انا ارغب في تعلم الانجليزية",
"page.select.gender.title": "أنا....",
"global.form.email.label": "الايميــــــل/البريد الإلكـــــــتروني",
"global.form.email.placeholder": "مثل: mohamed@google.com",
"global.form.email.placeholder": "example@gmail.com",
"global.form.password.label": "كلــــــمة الســـــــر",
"global.logout": "تسجيـــــــل خــــروج",
"errors.invalid": "خطـــــــــــأ",
Expand Down
2 changes: 1 addition & 1 deletion luna/src/tailwind.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import url("https://fonts.googleapis.com/css2?family=Mada:wght@200..900&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Cairo:wght@200..1000&display=swap");

@tailwind base;
@tailwind components;
Expand Down
20 changes: 18 additions & 2 deletions luna/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@ import { violet, blackA, mauve, green } from "@radix-ui/colors";
/** @type {import('tailwindcss').Config} */
export default {
corePlugins: {
preflight: false,
preflight: true,
},
prefix: "ui-",
content: ["./src/**/*.{ts,tsx}"],
theme: {
fontFamily: {
mada: ["Mada", "sans-serif"],
cairo: ["Cairo", "sans-serif"],
},
extend: {
colors: {
...mauve,
...violet,
...green,
...blackA,
"dark-100": "#181B22",
inputbg: "rgba(235, 237, 242, 0.32)",
"blue-normal": "#3A5BAA",
"red-light": "rgba(238, 48, 36, 0.08)",
"red-border": "#EE3024",
},
keyframes: {
overlayShow: {
Expand All @@ -35,6 +40,17 @@ export default {
overlayShow: "overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1)",
contentShow: "contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1)",
},
fontSize: {
arsm: "0.875rem",
arxl: "1.125rem",
},
lineHeight: {
normal: "13px",
},
spacing: {
lg: "16px",
xl: "24px",
},
},
},
plugins: [],
Expand Down

0 comments on commit 27ee460

Please sign in to comment.