-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added TextInput component based on TipTap
- Loading branch information
1 parent
ad5c68d
commit 3d8d2ae
Showing
9 changed files
with
856 additions
and
2 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import ListKeymap from "@tiptap/extension-list-keymap"; | ||
import Placeholder from "@tiptap/extension-placeholder"; | ||
import StarterKit from "@tiptap/starter-kit"; | ||
|
||
export const extensions = [ | ||
StarterKit.configure({ | ||
paragraph: { | ||
HTMLAttributes: { | ||
class: "text-gray-800 dark:text-neutral-200", | ||
}, | ||
}, | ||
bold: { | ||
HTMLAttributes: { | ||
class: "font-bold", | ||
}, | ||
}, | ||
bulletList: { | ||
HTMLAttributes: { | ||
class: "list-disc list-inside text-gray-800 dark:text-white", | ||
}, | ||
}, | ||
orderedList: { | ||
HTMLAttributes: { | ||
class: "list-decimal list-inside text-gray-800 dark:text-white", | ||
}, | ||
}, | ||
blockquote: { | ||
HTMLAttributes: { | ||
class: "text-gray-800 sm:text-xl dark:text-white", | ||
}, | ||
}, | ||
}), | ||
Placeholder.configure({ | ||
placeholder: "Add a message, if you'd like.", | ||
emptyNodeClass: "text-gray-400 dark:text-neutral-200", | ||
}), | ||
ListKeymap, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.tiptap p.is-editor-empty:first-child::before { | ||
font-size: 14px; | ||
content: attr(data-placeholder); | ||
float: left; | ||
height: 0; | ||
pointer-events: none; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
import { TextInput } from "./TextInput"; | ||
|
||
export default { | ||
title: "Components/TextInput", | ||
component: TextInput, | ||
} as Meta; | ||
|
||
type Story = StoryObj<typeof TextInput>; | ||
|
||
export const Default: Story = { | ||
args: {}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import "@testing-library/jest-dom"; | ||
import { render, screen } from "@testing-library/react"; | ||
import { TextInput } from "./TextInput"; | ||
import userEvent from "@testing-library/user-event"; | ||
|
||
describe("TextInput", () => { | ||
it("should render", () => { | ||
render(<TextInput />); | ||
|
||
expect(screen.getByLabelText("Add a spark")).toBeInTheDocument(); | ||
}); | ||
|
||
it("should fire onSubmit", async () => { | ||
const user = userEvent.setup(); | ||
const onSubmit = vi.fn(); | ||
render(<TextInput onSubmit={onSubmit} />); | ||
|
||
const input = screen.getByLabelText("Add a spark"); | ||
|
||
await user.type(input, "Hello, world![Enter]"); | ||
expect(onSubmit).toHaveBeenCalledWith( | ||
'<p class="text-gray-800 dark:text-neutral-200">Hello, world!</p>', | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { EditorContent, useEditor, type Editor } from "@tiptap/react"; | ||
import { extensions } from "./TextInput.config"; | ||
import "./TextInput.css"; | ||
|
||
export type TextInputProps = { | ||
onSubmit?: (htmlValue: string) => void; | ||
}; | ||
|
||
let editor: Editor | null = null; | ||
|
||
export const TextInput = (props: TextInputProps) => { | ||
const { onSubmit } = props; | ||
editor = useEditor({ | ||
extensions: extensions, | ||
editorProps: { | ||
attributes: { | ||
"aria-label": "Add a spark", | ||
class: "p-4 block w-full border border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-900 dark:border-neutral-700 dark:text-neutral-400 dark:placeholder-neutral-500 dark:focus:ring-neutral-600", | ||
}, | ||
handleKeyDown: (view, event) => { | ||
if (!onSubmit) { | ||
return false; | ||
} | ||
if (event.key !== "Enter" || event.shiftKey) { | ||
return false; | ||
} | ||
const html = editor?.getHTML().trim() ?? ""; | ||
if (html === "") { | ||
return false; | ||
} | ||
onSubmit(html); | ||
return true; | ||
}, | ||
}, | ||
}); | ||
|
||
return ( | ||
<> | ||
<EditorContent editor={editor} /> | ||
</> | ||
); | ||
}; |