# lotion
**Repository Path**: mirrors_trending/lotion
## Basic Information
- **Project Name**: lotion
- **Description**: An open-source Notion UI built with Vue 3.
- **Primary Language**: Unknown
- **License**: GPL-3.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 2
- **Created**: 2022-07-30
- **Last Updated**: 2026-05-02
## Categories & Tags
**Categories**: webui
**Tags**: None
## README
🧴 Lotion
An open-source Notion UI built with Vue 3.
Try demo
> We shared about Lotion and recreating the Notion UI during [CityJS Singapore's pre-conference meetup on 27th July](https://twitter.com/dashibase/status/1554070309224861696?s=20&t=f9pkIgoxYUCgAL5tRTxK4Q)!
## Features
- [x] Block-based editor
- [x] Drag to reorder blocks
- [x] Basic Markdown-parsing including bold, italic, headings and divider
- [x] Type '/' for command menu and shortcuts
- [x] Register your own blocks
- [x] Read-only mode
## Getting Started
**1. Install package**
```bash
npm i @dashibase/lotion
```
**2. Basic Lotion editor**
The following Vue component will initialize a basic Lotion editor.
```javascript
```
**3. Create custom components**
See `examples/CustomBlock.vue` for an example of a custom block.
The custom block component can accept the following props:
- `block`: A `Block` object. See `src/utils/types.ts` for details.
- `readonly`: A boolean, which sets whether the block/editor is in read-only mode.
The custom block component can also optionally expose the following methods (remember to call `defineExpose`):
- `onSet`: This is triggered when a user converts any block into this blocktype. It is called before the blocktype is changed.
- `onUnset`: This is triggered when a user converts this block into any blocktype. It is called before the blocktype is changed.
```javascript
🧴
```
**4. Register custom components**
See `examples/Example.vue` for an example of registering a custom block.
After creating the custom component, register it as follows:
```javascript
import CustomBlock from './CustomBlock.vue'
import { addIcons } from "oh-vue-icons"
import { FaPumpSoap } from "oh-vue-icons/icons"
import { registerBlock } from '@dashibase/lotion'
// Add the icon (from oh-vue-icons.js.org/)
addIcons(FaPumpSoap)
// Register the block
// registerBlock('', '', , 'BLOCK_ICON')
registerBlock('LOTION', 'Moisturize', CustomBlock, 'fa-pump-soap')
```
After that, you should be able to see the custom block when the user opens the menu to switch to different blocks.
## Contributing
**1. Clone this repository, go to the root directory and install packages**
```bash
git clone https://github.com/dashibase/lotion
cd lotion
npm i
```
**2. Run dev**
```bash
npm run dev
```
If you head to http://localhost:5173 on your browser, you should see what looks like the screenshot above.
**3. Contribute!**
Lotion is quite limited for now but we hope it serves as a good starting point for other folks looking to build their own editors.
We would love to make Lotion more extensible and welcome any suggestions or contributions!
See CONTRIBUTING.md for details.
## Acknowledgements
This was made much easier with the following libraries and frameworks, thank you!
- [vue-draggable-next](https://github.com/anish2690/vue-draggable-next)
- [tiptap](https://tiptap.dev/) and [ProseMirror](https://prosemirror.net/)
- [Vue 3](https://vuejs.org/)
- [Vite](https://vitejs.dev/)
- [TypeScript](https://www.typescriptlang.org/)
- [Tailwind CSS](https://tailwindcss.com/)
- [Headless UI](https://headlessui.dev/)
- [Oh, Vue Icons!](https://oh-vue-icons.js.org/)
- [Vitest](https://vitest.dev/)
- [Playwright](https://playwright.dev/)