Skip to content

Commit

Permalink
Added TextInput component based on TipTap
Browse files Browse the repository at this point in the history
  • Loading branch information
derwebcoder committed Aug 29, 2024
1 parent ad5c68d commit 3d8d2ae
Show file tree
Hide file tree
Showing 9 changed files with 856 additions and 2 deletions.
709 changes: 709 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
"@astrojs/check": "^0.9.3",
"@astrojs/react": "^3.6.2",
"@astrojs/tailwind": "^5.1.0",
"@tiptap/extension-list-keymap": "^2.6.6",
"@tiptap/extension-placeholder": "^2.6.6",
"@tiptap/pm": "^2.6.6",
"@tiptap/react": "^2.6.6",
"@tiptap/starter-kit": "^2.6.6",
"astro": "^4.14.3",
"dexie": "^4.0.8",
"preline": "^2.4.1",
Expand Down
4 changes: 2 additions & 2 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ export default defineConfig({
reuseExistingServer: !process.env.CI,
},

timeout: 6000,
timeout: 3000,
expect: {
timeout: 6000,
timeout: 3000,
},
});
15 changes: 15 additions & 0 deletions src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ import Layout from "../layouts/BaseLayout.astro";
<Layout title="Sparktags Demo Page">
<main>
<h1>Sparktag - Under Construction</h1>

<div>
<label>
<span>New spark</span>
<input type="text" />
</label>
<input type="button" value="Add" />
<div>
<span>Sparks</span>
<ul>
<li>Hello, world!</li>
</ul>
</div>
</div>

<p>sparktag@derwebcoder.de</p>
</main>
</Layout>
38 changes: 38 additions & 0 deletions src/ui/components/TextInput/TextInput.config.tsx
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,
];
7 changes: 7 additions & 0 deletions src/ui/components/TextInput/TextInput.css
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;
}
13 changes: 13 additions & 0 deletions src/ui/components/TextInput/TextInput.stories.tsx
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: {},
};
25 changes: 25 additions & 0 deletions src/ui/components/TextInput/TextInput.test.tsx
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>',
);
});
});
42 changes: 42 additions & 0 deletions src/ui/components/TextInput/TextInput.tsx
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} />
</>
);
};

0 comments on commit 3d8d2ae

Please sign in to comment.