[3][DEV NOTE] Create a form with tiptap and react-textarea-autosize
Tags: tailwindcss, nextjs, themes, react
Published: 2023-09-04 02:04:18

> This is dev note for this project: [turbo - nextjs - prisma - postgres blog](https://github.com/CodeForStartup/nextjs-prisma-postgres/)



Target of this part: 
- Integrate shadcn-ui 
- Minor update for postcss and tailwindcss
- Create a form with react-textarea-autosize and tiptap

## Install

### Integrate `shadcn-ui`

`shadcn-ui` is one of the most famous UI libraries now. So that I decide to integrate with my project. 
Just a simple command we can integrate shadcn as follow:
```
cd app/web
npx shadcn-ui@latest init
```
After initial shadcn-ui, we can see a lot of changes as this commit: [Initial shadcn-ui
](https://github.com/CodeForStartup/nextjs-prisma-postgres/pull/7/commits/4680a69bb72ce4c227e5c4ffd76f8a47a8d8f129).
These are some important changes:
- `tailwind.config.js` and `globals.css` are overrided
- folded `@/` is added

### Install `react-textarea-autosize` and `tiptap`

In the root folder, we will install: `react-textarea-autosize`, and `tip-tap` as follow:

```
pnpm add react-textarea-autosize --filter web
pnpm add @tiptap/extension-character-count @tiptap/extension-highlight @tiptap/extension-placeholder @tiptap/extension-task-item @tiptap/extension-task-list @tiptap/pm @tiptap/react @tiptap/starter-kit --filter web
```

I aslo will use `remixicon` for icons:
```
pnpm add remixicon --filter web
```

### Update post-css and tailwindcss
PostCss for build-time imports and postcss-nesting for nested declarations:
```
pnpm add -D postcss-nesting postcss-import
```

## Add Input title with `react-textarea-autosize`
`apps/web/@/molecules/InputTitle.tsx`

```
"use client";

import TextareaAutosize from "react-textarea-autosize";

type InputTitleProps = {
  title?: string;
  placeholder?: string;
};

const InputTitle: React.FunctionComponent<InputTitleProps> = ({
  title = "",
  placeholder = "",
}) => {
  return (
    <div className="w-full">
      <TextareaAutosize
        autoFocus
        value={title}
        placeholder={placeholder}
        className="w-full h-16 px-3 py-2 text-4xl font-bold text-gray-700 border-none placeholder-gray-500 border border-gray-300 rounded-md focus:outline-none"
      />
    </div>
  );
};

export default InputTitle;
```

## Add `tiptap` to nextjs

To integrate tip to nextjs we need to have many step, you can  refer in `apps/web/@/molecules/Editor` folder,

`apps/web/@/molecules/Editor/index.tsx`
```
"use client";

import React from "react";

import CharacterCount from "@tiptap/extension-character-count";
import { EditorContent, useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import Placeholder from "@tiptap/extension-placeholder";

import "./index.css";
import MenuBar from "./MenuBar";

type EditorProps = {
  content?: string;
  placeholder?: string;
};

export default ({ content = "", placeholder = "" }: EditorProps) => {
  const editor = useEditor({
    extensions: [
      StarterKit,
      CharacterCount.configure({
        limit: 10000,
      }),
      Placeholder.configure({
        placeholder,
      }),
    ],
    content,
  });

  return (
    <div className="w-full editor p-3 h-full">
      {editor && <MenuBar editor={editor} />}
      <EditorContent editor={editor} />
    </div>
  );
};
```

## Create post page
`apps/web/app/user/post/create/page.tsx`

```
"use client";

import React from "react";

import CharacterCount from "@tiptap/extension-character-count";
import { EditorContent, useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import Placeholder from "@tiptap/extension-placeholder";

import "./index.css";
import MenuBar from "./MenuBar";

type EditorProps = {
  content?: string;
  placeholder?: string;
};

export default ({ content = "", placeholder = "" }: EditorProps) => {
  const editor = useEditor({
    extensions: [
      StarterKit,
      CharacterCount.configure({
        limit: 10000,
      }),
      Placeholder.configure({
        placeholder,
      }),
    ],
    content,
  });

  return (
    <div className="w-full editor p-3 h-full">
      {editor && <MenuBar editor={editor} />}
      <EditorContent editor={editor} />
    </div>
  );
};
```

## Reference:

[1] Tiptap: I follow this example [collaborative-editing](https://tiptap.dev/examples/collaborative-editing)
[2] react-textarea-autosize: Quite simple, just follow the example [here](https://www.npmjs.com/package/react-textarea-autosize)
[3] [Post css preprocessor](https://tailwindcss.com/docs/using-with-preprocessors#nesting)

You can find the result in this PR: [[feat][UI] Create post page](https://github.com/CodeForStartup/nextjs-prisma-postgres/pull/7/files)