Bläddra i källkod

Add basic components and more

Tatiana Inama 5 år sedan
förälder
incheckning
7291e6e13a
31 ändrade filer med 587 tillägg och 25 borttagningar
  1. 6 1
      next-recipes/.prettierrc.json
  2. 26 0
      next-recipes/components/Button/Button.tsx
  3. 5 0
      next-recipes/components/Button/ButtonGroup.tsx
  4. 70 0
      next-recipes/components/Button/button.module.css
  5. 2 0
      next-recipes/components/Button/index.ts
  6. 16 0
      next-recipes/components/Forms/Checkbox.tsx
  7. 25 0
      next-recipes/components/Forms/Chip.tsx
  8. 16 0
      next-recipes/components/Forms/Radio.tsx
  9. 17 0
      next-recipes/components/Forms/TextInput.tsx
  10. 17 0
      next-recipes/components/Forms/Textarea.tsx
  11. 117 0
      next-recipes/components/Forms/forms.module.css
  12. 5 0
      next-recipes/components/Forms/index.ts
  13. 9 0
      next-recipes/components/Icon/Icon.d.ts
  14. 1 0
      next-recipes/components/Icon/add.svg
  15. 1 0
      next-recipes/components/Icon/filter.svg
  16. 12 0
      next-recipes/components/Icon/heart.tsx
  17. 8 0
      next-recipes/components/Icon/time.tsx
  18. 38 0
      next-recipes/components/RecipeItem/RecipeItem.module.css
  19. 29 5
      next-recipes/components/RecipeItem/index.tsx
  20. 10 0
      next-recipes/components/Typography/Subtitle.tsx
  21. 1 0
      next-recipes/components/Typography/index.ts
  22. 8 0
      next-recipes/components/Typography/typography.module.css
  23. 5 0
      next-recipes/next.config.js
  24. 4 1
      next-recipes/package.json
  25. 51 0
      next-recipes/pages/index.tsx
  26. 12 4
      next-recipes/pages/recipes.tsx
  27. 12 6
      next-recipes/styles/globals.css
  28. 46 6
      next-recipes/tailwind.config.js
  29. 3 2
      next-recipes/tsconfig.json
  30. 5 0
      next-recipes/utils/Colors.ts
  31. 10 0
      next-recipes/yarn.lock

+ 6 - 1
next-recipes/.prettierrc.json

@@ -1 +1,6 @@
-{}
+{
+  "trailingComma": "es5",
+  "tabWidth": 4,
+  "semi": false,
+  "singleQuote": true
+}

+ 26 - 0
next-recipes/components/Button/Button.tsx

@@ -0,0 +1,26 @@
+import { ButtonHTMLAttributes, FunctionComponent, MouseEventHandler } from 'react';
+import classnames from 'classnames';
+import styles from './button.module.css';
+
+interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
+  color?: 'default' | 'primary' | 'secondary' | 'outline',
+  size?: 'small' | 'medium' | 'large',
+  onClick?: MouseEventHandler<HTMLButtonElement>,
+}
+
+export const Button: FunctionComponent<ButtonProps> = ({ children, onClick, color, size, type, ...props }) => (
+  <button
+    className={classnames(styles.button, styles[`${color}Color`], styles[`${size}Size`])}
+    onClick={onClick}
+    type={type}
+    {...props}
+  >
+    {children}
+  </button>
+);
+
+Button.defaultProps = {
+  color: 'default',
+  size: 'medium',
+  type: 'button'
+}

+ 5 - 0
next-recipes/components/Button/ButtonGroup.tsx

@@ -0,0 +1,5 @@
+import styles from './button.module.css';
+
+export const ButtonGroup = ({ children }) => (
+  <div className={styles.buttonGroup}>{children}</div>
+)

+ 70 - 0
next-recipes/components/Button/button.module.css

@@ -0,0 +1,70 @@
+/* Button Group */
+.buttonGroup {
+  @apply flex -mx-2 flex-wrap;
+}
+
+.buttonGroup .button {
+  @apply m-2;
+}
+
+/* Button */
+.button {
+  @apply font-semibold tracking-wider uppercase text-base border-3 px-2 transition-box-shadow;
+}
+
+/* Colors  */
+.defaultColor {
+  @apply bg-black text-white border-black;
+}
+
+.primaryColor {
+  @apply bg-primary-400 border-primary-400;
+}
+
+.secondaryColor {
+  @apply text-white bg-secondary-500 border-secondary-500;
+}
+
+/* States */
+.button:hover {
+  @apply transform -translate-y-0.5 -translate-x-0.5;
+}
+
+.button:focus {
+  @apply transform -translate-x-px -translate-y-px;
+}
+
+.button:disabled {
+  @apply cursor-not-allowed pointer-events-none bg-grey-300 text-black border-grey-300;
+}
+
+.defaultColor:hover {
+  @apply shadow-strong-primary;
+}
+
+.defaultColor:focus {
+  @apply outline-primary;
+}
+
+.primaryColor:hover,
+.secondaryColor:hover {
+  @apply shadow-strong;
+}
+
+.primaryColor:focus,
+.secondaryColor:focus {
+  @apply outline-default;
+}
+
+.outlineColor:hover {
+  @apply shadow-strong-secondary;
+}
+
+.outlineColor:focus {
+  @apply outline-secondary;
+}
+
+/* Sizes */
+.mediumSize {
+  @apply h-8;
+}

+ 2 - 0
next-recipes/components/Button/index.ts

@@ -0,0 +1,2 @@
+export * from './Button';
+export * from './ButtonGroup';

+ 16 - 0
next-recipes/components/Forms/Checkbox.tsx

@@ -0,0 +1,16 @@
+import classNames from "classnames";
+import { FunctionComponent, InputHTMLAttributes } from "react"
+import styles from './forms.module.css';
+
+interface CheckboxProps extends InputHTMLAttributes<HTMLInputElement> {
+  label: string
+}
+
+export const Checkbox: FunctionComponent<CheckboxProps> = ({ label, id, ...props }) => (
+  <div className={classNames(styles.input, styles.checkbox)}>
+    <label htmlFor={id}>
+      <input type='checkbox' id={id} {...props} />
+      <span>{label}</span>
+    </label>
+  </div>
+);

+ 25 - 0
next-recipes/components/Forms/Chip.tsx

@@ -0,0 +1,25 @@
+import classnames from 'classnames';
+import { FunctionComponent, InputHTMLAttributes } from "react"
+import styles from './forms.module.css';
+
+interface ChipProps extends InputHTMLAttributes<HTMLInputElement> {
+  label: string,
+  color?: 'default' | 'primary' | 'secondary'
+}
+
+export const Chip: FunctionComponent<ChipProps> = ({ label, color, id, ...props }) => (
+  <div className={classnames(styles.chip, styles[`${color}Color`])}>
+    <input type='checkbox' id={id || label} {...props} />
+    <label htmlFor={id || label}>{label}</label>
+  </div>
+);
+
+Chip.defaultProps = {
+  color: 'default'
+}
+
+export const ChipGroup: FunctionComponent = ({ children }) => (
+  <div className={styles.chipGroup}>
+    {children}
+  </div>
+);

+ 16 - 0
next-recipes/components/Forms/Radio.tsx

@@ -0,0 +1,16 @@
+import classNames from "classnames";
+import { FunctionComponent, InputHTMLAttributes } from "react"
+import styles from './forms.module.css';
+
+interface RadioProps extends InputHTMLAttributes<HTMLInputElement> {
+  label: string
+}
+
+export const Radio: FunctionComponent<RadioProps> = ({ label, id, ...props }) => (
+  <div className={classNames(styles.input, styles.radio)}>
+    <label htmlFor={id}>
+      <input type='radio' id={id} {...props} />
+      <span>{label}</span>
+    </label>
+  </div>
+);

+ 17 - 0
next-recipes/components/Forms/TextInput.tsx

@@ -0,0 +1,17 @@
+import { FunctionComponent, InputHTMLAttributes } from "react"
+import styles from './forms.module.css';
+
+interface TextInputProps extends InputHTMLAttributes<HTMLInputElement> {
+  label?: string
+}
+
+export const TextInput: FunctionComponent<TextInputProps> = ({ label, id, ...props }) => (
+  <div className={styles.input}>
+    {label && <label htmlFor={id}>{label}</label>}
+    <input className={styles.textInput} id={id} {...props} />
+  </div>
+);
+
+TextInput.defaultProps = {
+  type: 'text',
+}

+ 17 - 0
next-recipes/components/Forms/Textarea.tsx

@@ -0,0 +1,17 @@
+import { FunctionComponent, TextareaHTMLAttributes } from "react"
+import styles from './forms.module.css';
+
+interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
+  label?: string
+}
+
+export const Textarea: FunctionComponent<TextareaProps> = ({ label, id, ...props }) => (
+  <div className={styles.input}>
+    {label && <label htmlFor={id}>{label}</label>}
+    <textarea className={styles.textInput} id={id} {...props} />
+  </div>
+);
+
+Textarea.defaultProps = {
+  rows: 5,
+}

+ 117 - 0
next-recipes/components/Forms/forms.module.css

@@ -0,0 +1,117 @@
+.input label {
+  @apply font-display font-bold;
+}
+
+.input+.input {
+  @apply mt-4;
+}
+
+.checkbox+.checkbox,
+.radio+.radio {
+  @apply mt-2;
+}
+
+.textInput {
+  @apply bg-grey-50 text-sm px-2 w-full text-black tracking-wide;
+  min-height: 2.25rem;
+}
+
+.textInput::placeholder {
+  @apply italic;
+}
+
+.textInput:focus {
+  @apply outline-default shadow-strong-primary;
+}
+
+textarea.textInput {
+  @apply pt-2;
+}
+
+.input.checkbox label,
+.input.radio label {
+  @apply flex items-center;
+}
+
+.checkbox input,
+.radio input {
+  @apply appearance-none h-6 w-6 border-black border-2 mr-2;
+}
+
+.radio input {
+  @apply rounded-full;
+}
+
+.checkbox input:checked,
+.radio input:checked {
+  @apply bg-primary;
+}
+
+.checkbox input:focus {
+  @apply outline-default-small;
+}
+
+.checkbox input:focus+span,
+.radio input:focus+span {
+  text-shadow: 1px 1px rgb(250, 204, 21);
+}
+
+.radio input:focus {
+  @apply outline-none border-3;
+}
+
+.chipGroup {
+  @apply flex flex-wrap -mx-2;
+}
+
+.chipGroup .chip {
+  @apply m-2;
+}
+
+.chip input {
+  @apply appearance-none;
+}
+
+.chip label {
+  @apply text-xs uppercase font-semibold tracking-widest px-2 py-1.5 cursor-pointer select-none;
+}
+
+.chip input:focus:not(:checked)+label {
+  @apply outline-black;
+}
+
+.chip.defaultColor label {
+  @apply bg-grey-100;
+}
+
+.chip.primaryColor label {
+  @apply bg-primary-100;
+}
+
+.chip.secondaryColor label {
+  @apply bg-secondary-100;
+}
+
+.chip.defaultColor:hover label {
+  @apply bg-grey-200;
+}
+
+.chip.primaryColor:hover label {
+  @apply bg-primary-200;
+}
+
+.chip.secondaryColor:hover label {
+  @apply bg-secondary-200;
+}
+
+.chip.defaultColor input:checked+label {
+  @apply bg-grey-300;
+}
+
+.chip.primaryColor input:checked+label {
+  @apply bg-primary-300;
+}
+
+.chip.secondaryColor input:checked+label {
+  @apply bg-secondary-300 text-white;
+}

+ 5 - 0
next-recipes/components/Forms/index.ts

@@ -0,0 +1,5 @@
+export * from './TextInput';
+export * from './Textarea';
+export * from './Checkbox';
+export * from './Radio';
+export * from './Chip';

+ 9 - 0
next-recipes/components/Icon/Icon.d.ts

@@ -0,0 +1,9 @@
+import { FunctionComponent } from 'react';
+
+export type IconProps = {
+  size?: number,
+  filled?: boolean,
+  color?: 'primary' | 'secondary' | 'default'
+}
+
+export type IconComponent = FunctionComponent<IconProps>;

+ 1 - 0
next-recipes/components/Icon/add.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>

+ 1 - 0
next-recipes/components/Icon/filter.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><path d="M0,0h24 M24,24H0" fill="none"/><path d="M7,6h10l-5.01,6.3L7,6z M4.25,5.61C6.27,8.2,10,13,10,13v6c0,0.55,0.45,1,1,1h2c0.55,0,1-0.45,1-1v-6 c0,0,3.72-4.8,5.74-7.39C20.25,4.95,19.78,4,18.95,4H5.04C4.21,4,3.74,4.95,4.25,5.61z"/><path d="M0,0h24v24H0V0z" fill="none"/></g></svg>

+ 12 - 0
next-recipes/components/Icon/heart.tsx

@@ -0,0 +1,12 @@
+import { IconComponent } from "./Icon";
+import { COLORS } from '@/utils/Colors';
+
+const Heart: IconComponent = ({ size = 24, filled, color = 'default' }) => (
+  <svg xmlns="http://www.w3.org/2000/svg" height={size} viewBox="0 0 24 24" width={size} fill={COLORS[color]}>
+    {filled ?
+      <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" /> :
+      <path d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z" />}
+  </svg>
+);
+
+export default Heart;

+ 8 - 0
next-recipes/components/Icon/time.tsx

@@ -0,0 +1,8 @@
+import { IconComponent } from "./Icon";
+import { COLORS } from '@/utils/Colors';
+
+const Time: IconComponent = ({ size = 18, filled, color = 'default' }) => (
+  <svg xmlns="http://www.w3.org/2000/svg" height={size} viewBox="0 0 24 24" width={size} fill={COLORS[color]}><path d="M0 0h24v24H0V0z" fill="none" /><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z" /></svg>
+);
+
+export default Time;

+ 38 - 0
next-recipes/components/RecipeItem/RecipeItem.module.css

@@ -0,0 +1,38 @@
+.recipeItem {
+  @apply bg-grey-50 flex py-2 pr-4;
+}
+
+.recipeItem.recipeItemClickeable {
+  @apply cursor-pointer;
+}
+
+.recipeItem.recipeItemClickeable:hover {
+  @apply bg-grey-100;
+}
+
+.recipeItem.recipeItemClickeable:active,
+.recipeItem.recipeItemClickeable:focus {
+  @apply bg-grey-200;
+}
+
+.recipeItemMedia {
+  @apply bg-grey-200 mr-4 relative;
+  width: 100px;
+  height: 56px;
+}
+
+.recipeItemContent {
+  @apply flex-1 truncate mr-4;
+}
+
+.recipeItemContentDescription svg {
+  @apply inline mr-1;
+}
+
+.recipeItemAction {
+  @apply self-center;
+}
+
+.recipeItem+.recipeItem {
+  @apply my-2;
+}

+ 29 - 5
next-recipes/components/RecipeItem/index.tsx

@@ -1,17 +1,41 @@
+import { FC, MouseEventHandler } from 'react';
+import Image from 'next/image';
 import { Recipe } from '@/types/recipes';
-import { FC } from 'react';
+import Heart from '@/components/Icon/heart';
+import { Subtitle } from '@/components/Typography';
+import dayjs from 'dayjs';
+import duration from 'dayjs/plugin/duration';
+
 import styles from './RecipeItem.module.css';
+import Time from '../Icon/time';
+import classNames from 'classnames';
+
+dayjs.extend(duration);
 
 type RecipeItemProps = {
   tagName?: keyof JSX.IntrinsicElements,
-  recipe: Recipe
+  onClick?: MouseEventHandler,
+  recipe: Recipe,
 };
 
-export const RecipeItem: FC<RecipeItemProps> = ({ tagName, recipe }) => {
+export const RecipeItem: FC<RecipeItemProps> = ({ tagName, recipe, onClick }) => {
   const Tag = tagName as keyof JSX.IntrinsicElements;
   return (
-    <Tag>
-      <h3>{recipe.name}</h3>
+    <Tag className={classNames(styles.recipeItem, {
+      [styles.recipeItemClickeable]: !!onClick,
+    })} onClick={onClick}>
+      <div className={styles.recipeItemMedia}>
+        {recipe.image && <Image src={`http://localhost:3000/${recipe.image}`} alt={recipe.name} layout='fill' />}
+      </div>
+      <div className={styles.recipeItemContent}>
+        <Subtitle alternative>{recipe.name}</Subtitle>
+        <p className={styles.recipeItemContentDescription}>
+          <Time />
+          {`${dayjs.duration(recipe.details.cookingTime).add(recipe.details.preparationTime).asMinutes()}'` || '-'}</p>
+      </div>
+      <div className={styles.recipeItemAction}>
+        <Heart />
+      </div>
     </Tag>
   )
 };

+ 10 - 0
next-recipes/components/Typography/Subtitle.tsx

@@ -0,0 +1,10 @@
+import { FC } from 'react';
+import styles from './typography.module.css';
+
+type SubtitleProps = {
+  alternative?: boolean,
+};
+
+export const Subtitle: FC<SubtitleProps> = ({ alternative, children }) => (
+  <h6 className={alternative ? styles.subtitleAlt : styles.subtitle}>{children}</h6>
+)

+ 1 - 0
next-recipes/components/Typography/index.ts

@@ -0,0 +1 @@
+export * from './Subtitle';

+ 8 - 0
next-recipes/components/Typography/typography.module.css

@@ -0,0 +1,8 @@
+.subtitle {
+  @apply text-lg font-extrabold normal-case font-display;
+
+}
+
+.subtitleAlt {
+  @apply text-lg normal-case tracking-comfy;
+}

+ 5 - 0
next-recipes/next.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  images: {
+    domains: ['localhost', 'localhost:3000', '192.168.2.116', '192.168.2.116:3000']
+  }
+}

+ 4 - 1
next-recipes/package.json

@@ -5,9 +5,12 @@
   "scripts": {
     "dev": "next dev -p 3005",
     "build": "next build",
-    "start": "next start"
+    "start": "next start",
+    "clean": "rm -rf .next/"
   },
   "dependencies": {
+    "classnames": "^2.3.1",
+    "dayjs": "^1.10.4",
     "next": "10.2.0",
     "postcss-import": "^14.0.1",
     "react": "17.0.2",

+ 51 - 0
next-recipes/pages/index.tsx

@@ -1,8 +1,59 @@
+import { ButtonGroup, Button } from "@/components/Button";
+import { Checkbox, Chip, ChipGroup, Radio, Textarea, TextInput } from "@/components/Forms";
+import Heart from "@/components/Icon/heart";
+import { Subtitle } from "@/components/Typography";
 import Layout from "components/Layout";
 
 export default function Home() {
   return (
     <Layout>
+      <div style={{ margin: '16px 0' }}>
+        <Subtitle>Buttons</Subtitle>
+        <ButtonGroup>
+          <Button>Default</Button>
+          <Button color='primary'>Primary</Button>
+          <Button color='secondary'>Secondary</Button>
+          <Button color='outline'>outline</Button>
+        </ButtonGroup>
+        <ButtonGroup>
+          <Button disabled>Default</Button>
+          <Button disabled color='primary'>Primary</Button>
+          <Button disabled color='secondary'>Secondary</Button>
+          <Button disabled color='outline'>outline</Button>
+        </ButtonGroup>
+      </div>
+      <div style={{ margin: '16px 0', width: '50vw' }}>
+        <Subtitle>Inputs</Subtitle>
+        <TextInput label='Text Input' id='text-input' placeholder='Placeholder' />
+        <Textarea label='Textarea' id='textarea' placeholder='Placeholder' />
+      </div>
+      <div style={{ margin: '16px 0' }}>
+        <Subtitle>Checkboxes</Subtitle>
+        <Checkbox label='Checkbox 1' id='checkbox-1' value='1' />
+        <Checkbox label='Checkbox 2' id='checkbox-2' value='2' />
+      </div>
+      <div style={{ margin: '16px 0' }}>
+        <Subtitle>Radios</Subtitle>
+        <Radio label='Radio 1' name='radio' />
+        <Radio label='Radio 2' name='radio' />
+      </div>
+      <div style={{ margin: '16px 0' }}>
+        <Subtitle>Chips (Checkbox)</Subtitle>
+        <ChipGroup>
+          <Chip label='Dinner' />
+          <Chip label='Snack' color='primary' />
+          <Chip label='Dessert' color='secondary' />
+          <Chip label='Lunch' />
+        </ChipGroup>
+      </div>
+      <div style={{ display: 'flex' }}>
+        <Heart size={40} />
+        <Heart size={40} color='primary' />
+        <Heart size={40} color='secondary' />
+        <Heart size={40} filled={true} color='default' />
+        <Heart size={40} filled={true} color='primary' />
+        <Heart size={40} filled={true} color='secondary' />
+      </div>
       <h1>H1 Headline!!</h1>
       <h2>H2 Headline</h2>
       <h3>H3 Headline</h3>

+ 12 - 4
next-recipes/pages/recipes.tsx

@@ -1,7 +1,9 @@
 import Layout from "@/components/Layout";
 import { GetStaticProps, InferGetStaticPropsType } from "next";
 import { Recipe } from "types/recipes";
+import { Subtitle } from 'components/Typography';
 import RecipeItem from "components/RecipeItem";
+import { TextInput } from "@/components/Forms";
 
 export const getStaticProps = async () => {
   const res = await fetch("http://localhost:3000/recipes/all/");
@@ -19,11 +21,17 @@ const Recipes = ({
   return (
     <Layout>
       <div>
+        <TextInput placeholder='search' id='recipe-search' />
+      </div>
+      <div>
+        <Subtitle>Favorites</Subtitle>
+      </div>
+      <div>
+        <Subtitle>All</Subtitle>
+        {recipeList.map((recipe, index) => (
+          <RecipeItem recipe={recipe} key={index} onClick={() => console.log(recipe.name)} />
+        ))}
       </div>
-      <h1>Recipes</h1>
-      {recipeList.map((recipe, index) => (
-        <RecipeItem recipe={recipe} key={index} />
-      ))}
     </Layout>
   );
 };

+ 12 - 6
next-recipes/styles/globals.css

@@ -1,3 +1,5 @@
+@tailwind base;
+
 html,
 body {
   @apply m-0;
@@ -37,29 +39,33 @@ body {
 }
 
 h1 {
-  @apply font-display text-7xl leading-none;
+  @apply font-bold font-display text-7xl;
 }
 
 h2 {
-  @apply font-display text-6xl leading-none tracking-tight;
+  @apply font-bold font-display text-6xl tracking-tight;
 }
 
 h3 {
-  @apply font-display;
+  @apply font-bold font-display;
   font-size: 3.375rem;
 }
 
 h4 {
-  @apply font-display tracking-wide;
+  @apply font-bold font-display tracking-wide;
   font-size: 2.375rem;
 }
 
 h5 {
-  @apply font-default font-medium;
+  @apply font-medium;
   font-size: 1.75rem;
 }
 
 h6 {
-  @apply font-default font-semibold uppercase text-xl;
+  @apply font-semibold uppercase text-xl;
   letter-spacing: 0.75px;
+}
+
+::selection {
+  @apply bg-primary text-black;
 }

+ 46 - 6
next-recipes/tailwind.config.js

@@ -1,13 +1,37 @@
 const colors = require("tailwindcss/colors");
-const defaultTheme = require("tailwindcss/defaultTheme");
 
 module.exports = {
   purge: ["./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"],
   darkMode: false, // or 'media' or 'class'
   theme: {
     colors: {
-      primary: colors.yellow,
-      secondary: colors.purple,
+      black: colors.black,
+      white: colors.white,
+      grey: {
+        ...colors.coolGray,
+        'DEFAULT': colors.coolGray[300],
+      },
+      primary: {
+        ...colors.yellow,
+        'DEFAULT': colors.yellow[400],
+      },
+      secondary: {
+        '50': '#efe9ff',
+        '100': '#d5c9fe',
+        '200': '#b8a5fe',
+        '300': '#987fff',
+        'DEFAULT': '#5b44fd',
+        '400': '#7B61FF',
+        '500': '#5b44fd',
+        '600': '#4c3ff6',
+        '700': '#3237ed',
+        '800': '#0031e7',
+        '900': '#0026d8'
+      },
+    },
+    borderWidth: {
+      '2': '2px',
+      '3': '3px'
     },
     fontFamily: {
       default: ["Raleway", "sans-serif"],
@@ -22,13 +46,29 @@ module.exports = {
       widest: "1.5px",
     },
     extend: {
+      spacing: {
+        '1.5': '0.375rem'
+      },
       fontSize: {
         "7xl": "5rem",
       },
+      boxShadow: {
+        strong: '4px 4px 0 0 #000000',
+        'strong-primary': '4px 4px 0 0 rgb(250, 204, 21)',
+        'strong-primary-dark': '4px 4px 0 0 rgb(202, 138, 4)',
+        'strong-secondary': '4px 4px 0 0 #987fff',
+      },
+      outline: {
+        white: '2px solid #FFFFFF',
+        primary: '2px solid rgb(250, 204, 21)',
+        secondary: '2px solid #987fff',
+        default: '2px solid #000000',
+        'default-small': '1px solid #000000'
+      },
+      transitionProperty: {
+        'box-shadow': 'transform, box-shadow'
+      }
     },
   },
-  variants: {
-    extend: {},
-  },
   plugins: [],
 };

+ 3 - 2
next-recipes/tsconfig.json

@@ -5,7 +5,8 @@
     "baseUrl": ".",
     "paths": {
       "@/components/*": ["components/*"],
-      "@/types/*": ["types/*"]
+      "@/types/*": ["types/*"],
+      "@/utils/*": ["utils/*"]
     },
     "allowJs": true,
     "skipLibCheck": true,
@@ -19,6 +20,6 @@
     "isolatedModules": true,
     "jsx": "preserve"
   },
-  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
+  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "next.config.js"],
   "exclude": ["node_modules"]
 }

+ 5 - 0
next-recipes/utils/Colors.ts

@@ -0,0 +1,5 @@
+export const COLORS = {
+  default: '#000000',
+  primary: '#facc15',
+  secondary: '#5b44fd'
+};

+ 10 - 0
next-recipes/yarn.lock

@@ -576,6 +576,11 @@ classnames@2.2.6:
   resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
   integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
 
+classnames@^2.3.1:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
+  integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
+
 color-convert@^1.9.0, color-convert@^1.9.1:
   version "1.9.3"
   resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
@@ -754,6 +759,11 @@ data-uri-to-buffer@3.0.1:
   resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636"
   integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==
 
+dayjs@^1.10.4:
+  version "1.10.4"
+  resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2"
+  integrity sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw==
+
 debug@2:
   version "2.6.9"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"