Getting Started
To get started, you can install the package with the following command:
npm install @vueup/vue-quill@latest --save
Usage
Basic
Here is a basic example of how to use the Quill component. We are using a technique called Slot Forwarding
so that if the developer wants to create a component and pass through the toolbar
slot, they can do so.
Toolbar
We can add our custom toolbar configuration by using the toolbar
prop.
Slot - Toolbar
Another way of customizing the toolbar is by using the toolbar
slot. This way, we can create a custom toolbar with our own components.
Bubble Theme
We can pass the bubble
value to the theme
prop to use the snow theme.
You have to select something in the editor to see the toolbar.
Module
We can pass an object or an array of objects to the module
prop to use any Quill module.
Something like this:
import BlotFormatter from "quill-blot-formatter";
type SingleModule = {
name: string;
module: any;
options?: any;
};
type ModuleObject = SingleModule | SingleModule[];
const modules: ModuleObject = {
name: "blotFormatter",
module: BlotFormatter,
options: {
/* options */
},
};
Upload an image to see the module in action.
CSS
In order to make the editor match the design of this website (and the whole shadcn/ui theme), I had to add this css file: You should copy this and add it to your project.
@import "@vueup/vue-quill/dist/vue-quill.snow.css";
@import "@vueup/vue-quill/dist/vue-quill.bubble.css";
.ql-toolbar {
&.ql-snow {
@apply rounded-t-md border-border font-sans;
}
&.ql-snow {
.ql-stroke {
@apply stroke-muted-foreground;
}
.ql-fill {
@apply fill-muted-foreground;
}
button {
@apply mx-0.5 rounded hover:bg-muted hover:text-foreground;
&:hover {
.ql-fill {
@apply fill-foreground;
}
.ql-stroke {
@apply stroke-foreground;
}
}
.ql-stroke {
@apply stroke-muted-foreground;
}
&.ql-active {
@apply bg-primary text-primary-foreground;
.ql-stroke {
@apply stroke-primary-foreground;
}
.ql-fill {
@apply fill-primary-foreground;
}
}
}
.ql-formats {
svg,
.ql-picker-label,
.ql-picker {
@apply text-muted-foreground;
}
button {
@apply mx-0.5 rounded hover:bg-muted hover:text-foreground;
&:hover {
.ql-fill {
@apply fill-foreground;
}
.ql-stroke {
@apply stroke-foreground;
}
}
.ql-fill {
@apply fill-muted-foreground;
}
.ql-stroke {
@apply stroke-muted-foreground;
}
&.ql-active {
@apply bg-primary text-primary-foreground;
.ql-fill {
@apply fill-primary-foreground;
}
.ql-stroke {
@apply stroke-primary-foreground;
}
}
}
.ql-picker {
@apply rounded;
.ql-picker-options {
@apply mt-1 rounded border-border bg-card p-1;
.ql-picker-item {
@apply rounded hover:bg-muted hover:text-foreground;
&.ql-selected {
@apply bg-primary text-primary-foreground;
}
}
}
}
.ql-align,
.ql-color-picker {
&:hover {
.ql-fill {
@apply fill-foreground;
}
.ql-stroke {
@apply stroke-foreground;
}
}
.ql-picker-options {
@apply mt-1 rounded border-border bg-card p-1;
.ql-picker-item {
&.ql-selected {
@apply bg-primary text-primary-foreground;
.ql-stroke {
@apply stroke-primary-foreground;
}
}
}
}
}
.ql-picker-label {
@apply hover:rounded hover:bg-muted hover:text-foreground;
&.ql-active {
@apply rounded bg-primary text-primary-foreground;
.ql-stroke {
@apply stroke-primary-foreground;
}
}
}
.ql-stroke {
@apply stroke-muted-foreground;
}
.ql-expanded {
.ql-picker-label {
@apply rounded border-border;
}
}
}
}
}
.ql-container {
@apply min-h-[150px] font-sans text-sm;
&.ql-snow {
a {
@apply text-sky-500 hover:text-sky-500;
}
@apply rounded-b-md border-border;
}
.ql-editor {
@apply min-h-[150px];
.ql-font-monospace {
@apply font-mono;
}
&.ql-blank {
&:before {
@apply not-italic text-muted-foreground;
}
}
}
.ql-tooltip {
@apply z-[9999] rounded border-border bg-card px-4 py-2 text-sm text-card-foreground shadow before:cursor-pointer before:font-medium;
input[type="text"] {
@apply h-8 w-[200px] rounded border-border bg-muted/30 p-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-ring;
}
.ql-preview {
@apply text-sm leading-[26px] underline underline-offset-2;
}
.ql-remove {
@apply text-destructive hover:text-destructive;
}
}
}
.ql-container.ql-bubble {
@apply rounded-md border;
.ql-tooltip {
@apply z-[9999] rounded-lg border border-border bg-card px-4 py-2 text-sm text-card-foreground shadow before:cursor-pointer before:font-medium;
input[type="text"] {
@apply h-8 w-[200px] rounded border-border bg-muted/30 p-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-ring;
}
.ql-preview {
@apply text-sm leading-[26px] underline underline-offset-2;
}
.ql-remove {
@apply text-destructive hover:text-destructive;
}
&:not(.ql-flip) .ql-tooltip-arrow {
@apply border-b-border;
}
.ql-toolbar {
.ql-stroke {
@apply stroke-muted-foreground;
}
.ql-fill {
@apply fill-muted-foreground;
}
button {
@apply mx-0.5 rounded hover:bg-muted hover:text-foreground;
&:hover {
.ql-fill {
@apply fill-foreground;
}
.ql-stroke {
@apply stroke-foreground;
}
}
.ql-stroke {
@apply stroke-muted-foreground;
}
&.ql-active {
@apply bg-primary text-primary-foreground;
.ql-stroke {
@apply stroke-primary-foreground;
}
.ql-fill {
@apply fill-primary-foreground;
}
}
}
.ql-formats {
svg,
.ql-picker-label,
.ql-picker {
@apply text-muted-foreground;
}
button {
@apply mx-0.5 rounded hover:bg-muted hover:text-foreground;
&:hover {
.ql-fill {
@apply fill-foreground;
}
.ql-stroke {
@apply stroke-foreground;
}
}
.ql-fill {
@apply fill-muted-foreground;
}
.ql-stroke {
@apply stroke-muted-foreground;
}
&.ql-active {
@apply bg-primary text-primary-foreground;
.ql-fill {
@apply fill-primary-foreground;
}
.ql-stroke {
@apply stroke-primary-foreground;
}
}
}
.ql-picker {
@apply rounded;
.ql-picker-options {
@apply mt-1 rounded border border-border bg-card p-1;
.ql-picker-item {
@apply rounded px-1 hover:bg-muted hover:text-foreground;
&.ql-selected {
@apply bg-primary text-primary-foreground;
}
}
}
}
.ql-align,
.ql-color-picker {
&:hover {
.ql-fill {
@apply fill-foreground;
}
.ql-stroke {
@apply stroke-foreground;
}
}
.ql-picker-options {
@apply mt-1 rounded border border-border bg-card p-1;
.ql-picker-item {
&.ql-selected {
@apply bg-primary text-primary-foreground;
.ql-stroke {
@apply stroke-primary-foreground;
}
}
}
}
}
.ql-picker-label {
@apply hover:rounded hover:bg-muted hover:text-foreground;
&.ql-active {
@apply rounded bg-primary text-primary-foreground;
.ql-stroke {
@apply stroke-primary-foreground;
}
}
}
.ql-stroke {
@apply stroke-muted-foreground;
}
.ql-expanded {
.ql-picker-label {
@apply rounded border-border;
}
}
}
}
}
}