initial commit

This commit is contained in:
2023-04-04 20:58:26 +02:00
parent 1259264531
commit b7034a0205
23 changed files with 8661 additions and 427 deletions

View File

@@ -1,3 +1,6 @@
{
"extends": "next/core-web-vitals"
"extends": [
"next/core-web-vitals",
"plugin:storybook/recommended"
]
}

5
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

6
.idea/jsLinters/eslint.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EslintConfiguration">
<option name="fix-on-save" value="true" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/next-storybook.iml" filepath="$PROJECT_DIR$/.idea/next-storybook.iml" />
</modules>
</component>
</project>

12
.idea/next-storybook.iml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

7
.idea/prettier.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PrettierConfiguration">
<option name="myRunOnSave" value="true" />
<option name="myRunOnReformat" value="true" />
</component>
</project>

0
.idea/sonarlint/issuestore/index.pb generated Normal file
View File

View File

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

26
.storybook/main.ts Normal file
View File

@@ -0,0 +1,26 @@
import type { StorybookConfig } from "@storybook/nextjs";
const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
{
name: "@storybook/addon-postcss",
options: {
postcssLoaderOptions: {
implementation: require("postcss"),
},
},
},
],
framework: {
name: "@storybook/nextjs",
options: {},
},
docs: {
autodocs: "tag",
},
};
export default config;

16
.storybook/preview.ts Normal file
View File

@@ -0,0 +1,16 @@
import type { Preview } from "@storybook/react";
import "../src/styles/globals.css";
const preview: Preview = {
parameters: {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
},
};
export default preview;

View File

@@ -6,17 +6,46 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
"dependencies": {
"@hookform/resolvers": "^3.0.0",
"@radix-ui/react-select": "^1.2.1",
"@storybook/addon-postcss": "^2.0.0",
"@types/node": "18.15.11",
"@types/react": "18.0.33",
"@types/react-dom": "18.0.11",
"clsx": "^1.2.1",
"eslint": "8.37.0",
"eslint-config-next": "13.2.4",
"next": "13.2.4",
"react": "18.2.0",
"react-dom": "18.2.0",
"typescript": "5.0.3"
"react-hook-form": "^7.43.9",
"typescript": "5.0.3",
"zod": "^3.21.4"
},
"devDependencies": {
"@storybook/addon-essentials": "^7.0.2",
"@storybook/addon-interactions": "^7.0.2",
"@storybook/addon-links": "^7.0.2",
"@storybook/addon-styling": "^0.3.2",
"@storybook/blocks": "^7.0.2",
"@storybook/nextjs": "^7.0.2",
"@storybook/react": "^7.0.2",
"@storybook/testing-library": "^0.0.14-next.2",
"autoprefixer": "^10.4.14",
"css-loader": "^6.7.3",
"eslint-plugin-storybook": "^0.6.11",
"postcss": "^8.4.21",
"postcss-loader": "^7.2.4",
"prettier": "^2.8.7",
"prettier-plugin-tailwindcss": "^0.2.6",
"sass-loader": "^13.2.2",
"storybook": "^7.0.2",
"style-loader": "^3.3.2",
"tailwindcss": "^3.3.1"
}
}

8402
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

6
postcss.config.js Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@@ -0,0 +1,17 @@
export const ChevronDown = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none">
<g clipPath="url(#a)">
<path
fill="#BDC1C7"
d="M5.51 9.46a1 1 0 0 1 1.64-.77l5.36 4.48 5.37-4.32A1 1 0 0 1 19.3 9a1 1 0 0 1-.15 1.46l-6 4.83a1 1 0 0 1-1.27 0l-6-5a1 1 0 0 1-.36-.83Z"
/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h24v24H0z" />
</clipPath>
</defs>
</svg>
);
};

View File

@@ -0,0 +1,28 @@
import { Select, SelectProps } from "../components/select";
import { Control, FieldValues, Path, useController } from "react-hook-form";
type SelectControlledProps<T extends FieldValues> = Omit<
SelectProps,
"onChange" | "value" | "name"
> & {
control: Control<T>;
name: Path<T>;
};
export const SelectControlled = <T extends FieldValues>({
control,
options,
name,
}: SelectControlledProps<T>) => {
const {
field: { value, onChange },
fieldState: { error },
} = useController({
control,
name,
});
return (
<Select options={options} onChange={onChange} value={value} name={name} />
);
};

0
src/components/index.ts Normal file
View File

View File

@@ -0,0 +1,143 @@
import * as React from "react";
import * as SelectPrimitive from "@radix-ui/react-select";
import { clsx } from "clsx";
import { ChevronDown } from "../../assets/icons/chevron-down";
import { FC, forwardRef } from "react";
const SelectRoot = SelectPrimitive.Root;
const SelectGroup = SelectPrimitive.Group;
const SelectValue = SelectPrimitive.Value;
const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Trigger
ref={ref}
className={clsx(
"flex h-10 w-full items-center border-dark-100 justify-between rounded-md border bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-700 dark:text-slate-50 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900",
className
)}
{...props}
>
{children}
<ChevronDown />
</SelectPrimitive.Trigger>
));
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
ref={ref}
className={clsx(
"animate-in fade-in-80 relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white text-slate-700 shadow-md dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
className
)}
{...props}
>
<SelectPrimitive.Viewport className="p-1">
{children}
</SelectPrimitive.Viewport>
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
));
SelectContent.displayName = SelectPrimitive.Content.displayName;
const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Label
ref={ref}
className={clsx(
"py-1.5 pr-2 pl-8 text-sm font-semibold text-slate-900 dark:text-slate-300",
className
)}
{...props}
/>
));
SelectLabel.displayName = SelectPrimitive.Label.displayName;
const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Item
ref={ref}
className={clsx(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm font-medium outline-none focus:bg-slate-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-slate-700",
className
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator></SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
));
SelectItem.displayName = SelectPrimitive.Item.displayName;
const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Separator
ref={ref}
className={clsx(
"-mx-1 my-1 h-px bg-slate-100 dark:bg-slate-700 p-[11px]",
className,
props.title === "misha" && "bg-red-500"
)}
{...props}
/>
));
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
export type SelectProps = {
options: { label: string; value: string }[];
onChange: (value: string) => void;
value: string;
placeholder?: string;
name?: string;
};
// eslint-disable-next-line react/display-name
export const Select: FC<SelectProps> = forwardRef(
({ options, value, onChange, placeholder, name }, ref) => {
return (
<SelectRoot value={value} onValueChange={onChange} name={name}>
<SelectTrigger>
<SelectValue placeholder={placeholder} />
</SelectTrigger>
<SelectContent>
{options.map((option) => {
return (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
);
})}
</SelectContent>
</SelectRoot>
);
}
);
export {
SelectRoot,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectItem,
SelectSeparator,
};

View File

@@ -0,0 +1,86 @@
import { Select } from "./";
import { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { SelectControlled } from "../../components-controlled/select-controlled";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const meta: Meta<typeof Select> = {
title: "Components/Select",
component: Select,
};
type Story = StoryObj<typeof Select>;
const options = [
{ label: "Male", value: "MALE" },
{ label: "Female", value: "FEMALE" },
{ label: "Cat", value: "CAT" },
];
export const Default: Story = {
render: () => {
const [value, setValue] = useState("light");
console.log(value);
return (
<div className={"w-full h-64 grid place-items-center bg-dark-700"}>
<Select
options={options}
value={value}
onChange={setValue}
placeholder={"Select theme"}
/>
</div>
);
},
};
const formSchema = z.object({
username: z.string().optional(),
password: z.number(),
email: z.string().email({}),
gender: z.enum(["MALE", "FEMALE", "CAT"]),
});
export type FormSchema = z.infer<typeof formSchema>;
export const Form = {
render: () => {
const {
control,
register,
handleSubmit,
formState: { errors },
} = useForm<FormSchema>({
mode: "onChange",
resolver: zodResolver(formSchema),
});
console.log(errors);
return (
<form
className={"w-full h-64 grid place-items-center bg-dark-700"}
onSubmit={handleSubmit((data) => {
console.log(data);
})}
>
<input {...register("username")} />
<input
{...register("password", {
valueAsNumber: true,
})}
/>
<input {...register("email")} />
<SelectControlled options={options} control={control} name={"gender"} />
<button
type={"submit"}
className={"bg-light-300 text-dark-500 p-4 rounded"}
>
Submit
</button>
</form>
);
},
};
export default meta;

View File

@@ -1,7 +1,5 @@
import Head from 'next/head'
import Image from 'next/image'
import { Inter } from 'next/font/google'
import styles from '@/styles/Home.module.css'
import {Inter} from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
@@ -10,114 +8,13 @@ export default function Home() {
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="description" content="Gesnerated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<div className={styles.description}>
<p>
Get started by editing&nbsp;
<code className={styles.code}>src/pages/index.tsx</code>
</p>
<div>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
By{' '}
<Image
src="/vercel.svg"
alt="Vercel Logo"
className={styles.vercelLogo}
width={100}
height={24}
priority
/>
</a>
</div>
</div>
<div className={styles.center}>
<Image
className={styles.logo}
src="/next.svg"
alt="Next.js Logo"
width={180}
height={37}
priority
/>
<div className={styles.thirteen}>
<Image
src="/thirteen.svg"
alt="13"
width={40}
height={31}
priority
/>
</div>
</div>
<div className={styles.grid}>
<a
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2 className={inter.className}>
Docs <span>-&gt;</span>
</h2>
<p className={inter.className}>
Find in-depth information about Next.js features and&nbsp;API.
</p>
</a>
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2 className={inter.className}>
Learn <span>-&gt;</span>
</h2>
<p className={inter.className}>
Learn about Next.js in an interactive course with&nbsp;quizzes!
</p>
</a>
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2 className={inter.className}>
Templates <span>-&gt;</span>
</h2>
<p className={inter.className}>
Discover and deploy boilerplate example Next.js&nbsp;projects.
</p>
</a>
<a
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2 className={inter.className}>
Deploy <span>-&gt;</span>
</h2>
<p className={inter.className}>
Instantly deploy your Next.js site to a shareable URL
with&nbsp;Vercel.
</p>
</a>
</div>
</main>
<main>
<h1 className={'text-teal-600'}>Hello</h1>
</main>
</>
)
}

View File

@@ -1,107 +1,3 @@
:root {
--max-width: 1100px;
--border-radius: 12px;
--font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
--primary-glow: conic-gradient(
from 180deg at 50% 50%,
#16abff33 0deg,
#0885ff33 55deg,
#54d6ff33 120deg,
#0071ff33 160deg,
transparent 360deg
);
--secondary-glow: radial-gradient(
rgba(255, 255, 255, 1),
rgba(255, 255, 255, 0)
);
--tile-start-rgb: 239, 245, 249;
--tile-end-rgb: 228, 232, 233;
--tile-border: conic-gradient(
#00000080,
#00000040,
#00000030,
#00000020,
#00000010,
#00000010,
#00000080
);
--callout-rgb: 238, 240, 241;
--callout-border-rgb: 172, 175, 176;
--card-rgb: 180, 185, 188;
--card-border-rgb: 131, 134, 135;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
--primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
--secondary-glow: linear-gradient(
to bottom right,
rgba(1, 65, 255, 0),
rgba(1, 65, 255, 0),
rgba(1, 65, 255, 0.3)
);
--tile-start-rgb: 2, 13, 46;
--tile-end-rgb: 2, 5, 19;
--tile-border: conic-gradient(
#ffffff80,
#ffffff40,
#ffffff30,
#ffffff20,
#ffffff10,
#ffffff10,
#ffffff80
);
--callout-rgb: 20, 20, 20;
--callout-border-rgb: 108, 108, 108;
--card-rgb: 100, 100, 100;
--card-border-rgb: 200, 200, 200;
}
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,
body {
max-width: 100vw;
overflow-x: hidden;
}
body {
color: rgb(var(--foreground-rgb));
background: linear-gradient(
to bottom,
transparent,
rgb(var(--background-end-rgb))
)
rgb(var(--background-start-rgb));
}
a {
color: inherit;
text-decoration: none;
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
}
@tailwind base;
@tailwind components;
@tailwind utilities;

53
tailwind.config.js Normal file
View File

@@ -0,0 +1,53 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
colors: {
primary: {
100: "#73A5FF",
300: "#4C8DFF",
500: "#397DF6",
700: "#2F68CC",
900: "#234E99",
},
success: {
100: "#80FFBF",
300: "#22E584",
500: "#14CC70",
700: "#0F9954",
900: "#0A6638",
},
danger: {
100: "#FF8099",
300: "#F23D61",
500: "#CC1439",
700: "#990F2B",
900: "#660A1D",
},
warning: {
100: "#FFD073",
300: "#E5AC39",
500: "#D99000",
700: "#996600",
900: "#664400",
},
dark: {
100: "#4C4C4C",
300: "#333333",
500: "#171717",
700: "#0D0D0D",
900: "#000000",
},
light: {
100: "#FFFFFF",
300: "#F7FBFF",
500: "#EDF3FA",
700: "#D5DAE0",
900: "#BDC1C7",
},
},
},
},
plugins: [],
};