diff --git a/docs/src/pages/components/Editor.svx b/docs/src/pages/components/Editor.svx
new file mode 100644
index 00000000..c82e3c88
--- /dev/null
+++ b/docs/src/pages/components/Editor.svx
@@ -0,0 +1,42 @@
+---
+components: ["Editor", "EditorSkeleton"]
+---
+
+
+
+`Editor` is keyed for performance reasons.
+
+
+ html
attribute contains pure html.
+
+
+### Default
+
+
+
+### Extra-large size
+
+
+
+### Small size
+
+
+
+### Invalid state
+
+
+
+### Warning state
+
+
+
+### Disabled state
+
+
+
+### Skeleton
+
+
\ No newline at end of file
diff --git a/src/Editor/Editor.svelte b/src/Editor/Editor.svelte
new file mode 100644
index 00000000..1ab22c10
--- /dev/null
+++ b/src/Editor/Editor.svelte
@@ -0,0 +1,114 @@
+
+
+{#if titleText}
+
+{/if}
+{#if disabled}
+ {@html html}
+{:else}
+
+{/if}
+{#if invalid}
+ {invalidText}
+{/if}
+{#if !invalid && warn}
+ {warnText}
+{/if}
+{#if !invalid && !warn && helperText}
+
+ {helperText}
+
+{/if}
+{invalidText}
+
+
diff --git a/src/Editor/EditorSkeleton.svelte b/src/Editor/EditorSkeleton.svelte
new file mode 100644
index 00000000..76588c07
--- /dev/null
+++ b/src/Editor/EditorSkeleton.svelte
@@ -0,0 +1,19 @@
+
+
+
+
+ {#if !hideLabel}
+
+ {/if}
+
+
diff --git a/src/Editor/index.js b/src/Editor/index.js
new file mode 100644
index 00000000..4b448254
--- /dev/null
+++ b/src/Editor/index.js
@@ -0,0 +1,3 @@
+export { default as Editor } from "./Editor.svelte";
+export { default as EditorSkeleton } from "./EditorSkeleton.svelte";
+export { quill } from "./quill";
diff --git a/src/Editor/quill.js b/src/Editor/quill.js
new file mode 100644
index 00000000..140a84c6
--- /dev/null
+++ b/src/Editor/quill.js
@@ -0,0 +1,32 @@
+// https://github.com/lagden/svelte-editor-quill
+
+import Quill from "quill";
+
+export function quill(node, params) {
+ const quill = new Quill(node, {
+ ...params.options,
+ });
+
+ if (params.html) {
+ const delta = quill.clipboard.convert(params.html);
+ quill.setContents(delta, "silent");
+ }
+
+ const onTextChange = () => {
+ const customEvent = new CustomEvent("text-change", {
+ detail: {
+ html: quill.root.innerHTML,
+ text: quill.getText(),
+ },
+ });
+ node.dispatchEvent(customEvent);
+ };
+
+ quill.on("text-change", onTextChange);
+
+ return {
+ destroy() {
+ quill.off("text-change", onTextChange);
+ },
+ };
+}
diff --git a/types/Editor/Editor.svelte.d.ts b/types/Editor/Editor.svelte.d.ts
new file mode 100644
index 00000000..3852fd79
--- /dev/null
+++ b/types/Editor/Editor.svelte.d.ts
@@ -0,0 +1,83 @@
+///
+import type { SvelteComponentTyped } from "svelte";
+
+export interface EditorProps {
+ /**
+ * Set to `true` to disable the dropdown
+ * @default false
+ */
+ disabled?: boolean;
+
+ /**
+ * Specify the title text
+ * @default ""
+ */
+ titleText?: string;
+
+ /**
+ * Set to `true` to indicate an invalid state
+ * @default false
+ */
+ invalid?: boolean;
+
+ /**
+ * Specify the invalid state text
+ * @default ""
+ */
+ invalidText?: string;
+
+ /**
+ * Set to `true` to indicate an warning state
+ * @default false
+ */
+ warn?: boolean;
+
+ /**
+ * Specify the warning state text
+ * @default ""
+ */
+ warnText?: string;
+
+ /**
+ * Specify the helper text
+ * @default ""
+ */
+ helperText?: string;
+
+ /**
+ * Set to `true` to visually hide the label text
+ * @default false
+ */
+ hideLabel?: boolean;
+
+ /**
+ * Set an id for the list box component
+ * @default "ccs-" + Math.random().toString(36)
+ */
+ id?: string;
+
+ /**
+ * Specify the placeholder text
+ * @default null
+ */
+ placeholder?: undefined;
+
+ /**
+ * Specify the html
+ * @default undefined
+ */
+ html?: string;
+
+ /**
+ * Specify the text
+ * @default undefined
+ */
+ text?: string;
+
+ /**
+ * @default { modules: { toolbar }, theme: 'snow', placeholder }
+ */
+ options?: { modules: { toolbar }; theme: "snow"; placeholder };
+}
+
+export default class Editor extends SvelteComponentTyped {}
diff --git a/types/Editor/EditorSkeleton.svelte.d.ts b/types/Editor/EditorSkeleton.svelte.d.ts
new file mode 100644
index 00000000..692f83ff
--- /dev/null
+++ b/types/Editor/EditorSkeleton.svelte.d.ts
@@ -0,0 +1,22 @@
+///
+import type { SvelteComponentTyped } from "svelte";
+
+export interface EditorSkeletonProps
+ extends svelte.JSX.HTMLAttributes {
+ /**
+ * Set to `true` to hide the label text
+ * @default false
+ */
+ hideLabel?: boolean;
+}
+
+export default class EditorSkeleton extends SvelteComponentTyped<
+ EditorSkeletonProps,
+ {
+ click: WindowEventMap["click"];
+ mouseover: WindowEventMap["mouseover"];
+ mouseenter: WindowEventMap["mouseenter"];
+ mouseleave: WindowEventMap["mouseleave"];
+ },
+ {}
+> {}