Add documentation for using Milkdown with various frameworks
- Created a new document for using components in Milkdown. - Added a guide for using plugins in Milkdown, including toggling plugins programmatically and listing official plugins. - Introduced a recipe for integrating Milkdown with Angular, including installation steps and component creation. - Added a recipe for using Milkdown with Next.js, detailing installation and component setup. - Created a guide for integrating Milkdown with NuxtJS, including installation and component creation. - Added a comprehensive guide for using Milkdown with React, covering both Crepe and core Milkdown usage. - Introduced a recipe for SolidJS integration with Milkdown, including installation and component creation. - Added a guide for using Milkdown with Svelte, detailing installation and component setup. - Created a comprehensive guide for integrating Milkdown with Vue, covering both Crepe and core Milkdown usage. - Added a recipe for using Milkdown with Vue2, including installation and component creation.
This commit is contained in:
140
milkdown-docs/plugin/example-tooltip-plugin.md
Normal file
140
milkdown-docs/plugin/example-tooltip-plugin.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# Example: Tooltip Plugin
|
||||
|
||||
This guide walks you through creating and using **tooltip-based plugins** in Milkdown.
|
||||
You will learn how the low-level `@milkdown/plugin-tooltip` works and how to build richer experiences on top of it in **vanilla TypeScript**, **React**, and **Vue**.
|
||||
|
||||
> **TL;DR** – A tooltip in Milkdown is nothing more than a ProseMirror plugin created by `tooltipFactory(id)`.
|
||||
> It receives position information from the editor and renders any DOM of your choice.
|
||||
> Everything else (buttons, inputs, styling, framework bindings) can be composed on top of that.
|
||||
|
||||
## 1. Anatomy of a Tooltip
|
||||
|
||||
---
|
||||
|
||||
At its core the tooltip plugin exported from `@milkdown/plugin-tooltip` contains two helpers:
|
||||
|
||||
1. **`TooltipProvider`** – An utility class powered by [floating-ui](https://floating-ui.com/) to calculate the tooltip position.
|
||||
2. **`tooltipFactory(id)`** – A factory that returns a pair of Milkdown plugin slices which wire the provider into the editor.
|
||||
|
||||
The factory is extremely small (≈40 lines):
|
||||
|
||||
```ts
|
||||
import { tooltipFactory } from "@milkdown/plugin-tooltip";
|
||||
|
||||
// Create a tooltip identified by the string "my".
|
||||
export const [myTooltipSpec, myTooltipPlugin] = tooltipFactory("my");
|
||||
```
|
||||
|
||||
The first element (`myTooltipSpec`) is a **ctx slice** that stores a `PluginSpec`, while the second one (`myTooltipPlugin`) is the real ProseMirror plugin which consumes that spec.
|
||||
|
||||
## 2. A Minimal Vanilla Tooltip
|
||||
|
||||
---
|
||||
|
||||
Below is the complete code for a tooltip that shows the **length of the current selection**.
|
||||
|
||||
```ts
|
||||
import { Editor } from "@milkdown/kit/core";
|
||||
import { commonmark } from "@milkdown/kit/preset/commonmark";
|
||||
import { TooltipProvider, tooltipFactory } from "@milkdown/plugin-tooltip";
|
||||
|
||||
// 1) Prepare DOM that we will mount into the page.
|
||||
const el = document.createElement("div");
|
||||
el.className = "selection-length";
|
||||
el.style.cssText = `
|
||||
pointer-events:none;
|
||||
background:#333;color:#fff;padding:2px 6px;border-radius:4px;font-size:12px;
|
||||
`;
|
||||
|
||||
// 2) Build a provider which updates the content.
|
||||
const provider = new TooltipProvider({
|
||||
content: el,
|
||||
shouldShow: (view) => !!view.state.selection.content().size,
|
||||
});
|
||||
|
||||
// 3) Bridge provider & editor.
|
||||
const tooltip = tooltipFactory("sel-length");
|
||||
const tooltipConfig = (ctx: Ctx) => {
|
||||
ctx.set(selectionTooltipSpec.key, {
|
||||
view: () => ({
|
||||
update: provider.update,
|
||||
destroy: provider.destroy,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
Editor.make().config(tooltipConfig).use(commonmark).use(tooltip).create();
|
||||
```
|
||||
|
||||
Key points:
|
||||
|
||||
- We **create** any DOM element we like (`el`).
|
||||
- `TooltipProvider` tracks the editor position and moves the element.
|
||||
- `tooltipFactory` wraps the provider into a pluggable slice.
|
||||
|
||||
## 3. Framework Examples
|
||||
|
||||
---
|
||||
|
||||
Sometimes building UI is easier in your favourite framework.
|
||||
Because the tooltip provider only deals with **DOM elements**, you can freely render React, Vue or Svelte components and pass their root node to the provider.
|
||||
|
||||
### React
|
||||
|
||||
::iframe{src="https://stackblitz.com/github/Milkdown/examples/tree/main/react-tooltip"}
|
||||
|
||||
The React example shows how to:
|
||||
|
||||
1. Create a React component (`<SelectionTooltip/>`).
|
||||
2. Render it into a portal and give the root HTML element to `TooltipProvider`.
|
||||
3. Re-use React state/hooks while Milkdown takes care of positioning.
|
||||
|
||||
### Vue
|
||||
|
||||
::iframe{src="https://stackblitz.com/github/Milkdown/examples/tree/main/vue-tooltip"}
|
||||
|
||||
The Vue example follows the same pattern with `defineComponent` and `teleport`.
|
||||
|
||||
## 4. Real-world Examples
|
||||
|
||||
---
|
||||
|
||||
### 4-1. Link Tooltip (_@milkdown/component/link-tooltip_)
|
||||
|
||||
The [link tooltip](https://github.com/Milkdown/milkdown/tree/main/packages/components/src/link-tooltip) demonstrates how to:
|
||||
|
||||
- Maintain UI **state** (`preview` vs `edit`) in ctx slices.
|
||||
- Communicate with the editor through an **API slice** (add / edit / remove links).
|
||||
- Render framework-agnostic UI inside a tooltip provider.
|
||||
|
||||
Have a look at the files below to see those techniques in action:
|
||||
|
||||
```text
|
||||
packages/components/src/link-tooltip/
|
||||
├── slices.ts # state & API slices
|
||||
├── tooltips.ts # preview & edit providers
|
||||
└── component.tsx # (framework examples)
|
||||
```
|
||||
|
||||
### 4-2. Toolbar Feature (_@milkdown/crepe/feature/toolbar_)
|
||||
|
||||
The toolbar in the [crepe](https://github.com/Milkdown/milkdown/tree/main/packages/crepe) package pushes the idea further by:
|
||||
|
||||
- Using multiple tooltip instances (one per button group).
|
||||
- Rendering the UI with Vue _inside_ the provider.
|
||||
- Sharing configuration via ctx slices so that every button is extensible by third-party plugins.
|
||||
|
||||
You can browse the implementation starting from
|
||||
|
||||
```text
|
||||
packages/crepe/src/feature/toolbar/component.tsx
|
||||
```
|
||||
|
||||
## 5. Summary & Next Steps
|
||||
|
||||
---
|
||||
|
||||
- `@milkdown/plugin-tooltip` offers **just enough** abstraction: positioning & lifecycle.
|
||||
- Everything else – **state, styling, framework integration** – is totally up to you.
|
||||
|
||||
Try to customise one of the examples above, then ship your own tooltip-powered features 🤟.
|
||||
Reference in New Issue
Block a user