GithubHelp home page GithubHelp logo

draft-js's Introduction



Build Status npm version

Live Demo


THIS PROJECT IS CURRENTLY IN MAINTENANCE MODE. It will not receive any feature updates, only critical security bug patches. On 31st December 2022 the repo will be fully archived.

For users looking for an open source alternative, Meta have been working on migrating to a new framework, called Lexical. It's still experimental, and we're working on adding migration guides, but, we believe, it provides a more performant and accessible alternative.

Draft.js is a JavaScript rich text editor framework, built for React and backed by an immutable model.

  • Extensible and Customizable: We provide the building blocks to enable the creation of a broad variety of rich text composition experiences, from basic text styles to embedded media.
  • Declarative Rich Text: Draft.js fits seamlessly into React applications, abstracting away the details of rendering, selection, and input behavior with a familiar declarative API.
  • Immutable Editor State: The Draft.js model is built with immutable-js, offering an API with functional state updates and aggressively leveraging data persistence for scalable memory usage.

Learn how to use Draft.js in your own project.

Draft.js is used in production on Facebook, including status and comment inputs, Notes, and

API Notice

Before getting started, please be aware that we recently changed the API of Entity storage in Draft.

Previously, the old API was set to be removed in v0.11.0. Since, the plans have changed— v0.11.0 still supports the old API and v0.12.0 will remove it. Refer to the docs for more information and information on how to migrate.

Getting Started

npm install --save draft-js react react-dom


yarn add draft-js react react-dom

Draft.js depends on React and React DOM which must also be installed.

Using Draft.js

import React from 'react';
import ReactDOM from 'react-dom';
import {Editor, EditorState} from 'draft-js';

function MyEditor() {

  constructor(props) {
    this.state = {editorState: EditorState.createEmpty()};
    this.onChange = (editorState) => this.setState({editorState});
    this.setEditor = (editor) => {
      this.editor = editor;
    this.focusEditor = () => {
      if (this.editor) {

  componentDidMount() {

  render() {
    return (
      <div style={styles.editor} onClick={this.focusEditor}>

const styles = {
  editor: {
    border: '1px solid gray',
    minHeight: '6em'

  <MyEditor />,

Since the release of React 16.8, you can use Hooks as a way to work with EditorState without using a class.

import React from "react";
import { Editor, EditorState } from "draft-js";
import "draft-js/dist/Draft.css";

export default function MyEditor() {
  const [editorState, setEditorState] = React.useState(() =>

  const editor = React.useRef(null);
  function focusEditor() {

  return (
      style={{ border: "1px solid black", minHeight: "6em", cursor: "text" }}
        placeholder="Write something!"

Note that the editor itself is only as tall as its contents. In order to give users a visual cue, we recommend setting a border and a minimum height via the .DraftEditor-root CSS selector, or using a wrapper div like in the above example.

Because Draft.js supports unicode, you must have the following meta tag in the <head> </head> block of your HTML file:

<meta charset="utf-8" />

Further examples of how Draft.js can be used are provided in the /examples directory of this repo.

Building Draft.js

Draft.js is built with Yarn v1. Using other package managers mgiht work, but is not officially supported.

To clone and build, run:

git clone
cd draft-js
yarn install
yarn run build


To run the examples in the /examples directory, first build Draft.js locally as described above. Then, open the example HTML files in your browser.

Browser Support

IE / Edge
IE / Edge
iOS Safari
iOS Safari
Chrome for Android
Chrome for Android
IE11, Edge [1, 2] last 2 versions last 2 versions last 2 versions not fully supported [3] not fully supported [3]

[1] May need a shim or a polyfill for some syntax used in Draft.js (docs).

[2] IME inputs have known issues in these browsers, especially Korean (docs).

[3] There are known issues with mobile browsers, especially on Android (docs).

Resources and Ecosystem

Check out this curated list of articles and open-sourced projects/utilities: Awesome Draft-JS.

Discussion and Support

Join our Slack team!


We welcome pull requests. Learn how to contribute.


Draft.js is MIT licensed.

Examples provided in this repository and in the documentation are separately licensed.

draft-js's People


flarnie avatar mrkev avatar mitermayer avatar sophiebits avatar zpao avatar niveditc avatar Daniel15 avatar pieterv avatar calebmer avatar davidchang avatar dsainati1 avatar gkz avatar tylercraft avatar yangshun avatar dependabot[bot] avatar johanneslumpe avatar miorel avatar Kiwka avatar steveluscher avatar tasti avatar mmmoussa avatar NoamELB avatar pakoito avatar bradzacher avatar jbrown215 avatar sebmarkbage avatar aadsm avatar remko avatar juliankrispel avatar existentialism avatar


Emeka Orji avatar Dima avatar Mikuto Matsuo avatar  avatar liupai avatar Yurii Rybak avatar Seth Dimmer avatar Joe Du avatar Dong Zhou avatar CommandS avatar 张树源 avatar GouLaoliu avatar Serhan Elmalı avatar  avatar Reyu Hero avatar RosApr avatar Guilherme Daniel avatar  avatar daoleno avatar 彧衡 avatar Syed Umair avatar Mehrdad Moradizadeh avatar Lúdio Oliveira avatar Sanni avatar Ashutosh Sajan avatar Ramazan SANCAR avatar a6un avatar Bokang Huang avatar 江辰 avatar 汥坳赵 avatar Gil Creque avatar  avatar Sidharth Baby avatar Denis avatar Umerrpogrammer avatar  avatar 耿可可 avatar Miftah Shidiq avatar hoshide avatar lcopilot avatar Shenenkaka avatar  avatar aiello avatar Max avatar  avatar Gekson avatar Hiram avatar  avatar  avatar Dan Sikes avatar  avatar lyqline avatar Keiji Miyake avatar FrankQiu avatar  avatar Rafael Pereira avatar Minhaz Halim (Zim) avatar zhangyanling77 avatar Abhay K Vincent avatar Mitsuru Ogawa avatar  avatar  avatar Giliam Verheide avatar Vitor Daniel avatar Yasin Can avatar kiyoshion avatar  avatar Charon-Fan avatar Sora Ichigo avatar Marco Klein avatar Kevin Mingtarja avatar lizhiyu avatar  avatar Cédric Bahirwe avatar moon avatar Miki Leskinen avatar  avatar Siam Rahman avatar Jeremy Jay avatar Igor Kowalczyk avatar Roopesh Saravanan avatar  avatar  avatar Fahd Arhalai avatar  avatar Ramez Mahmoud  avatar eaxe avatar  avatar Winz avatar tahar belghitri avatar  avatar Çağrı Atalay avatar Abdullah Al Hommada avatar Wlad avatar MAPKIN avatar Mr.kouhadi (**朋友叫我布莱恩) avatar Chen Han avatar Kripu Khadka avatar  avatar Zhazha_JiaYiZhen avatar


B.E. Henriksen avatar Sophie Alpert avatar Deepak Kannan avatar Chris Barna avatar Miguel Senquiz avatar James Rowe avatar Abhik Khanra avatar Christian avatar Linces Marques avatar Michael Borejdo avatar Mcarena avatar Panayiotis Tzagkarakis avatar Zachary Berry avatar gittmaan avatar Alexandre Magno avatar lifesinger avatar Supriyo Sinha avatar Andrey Lunyov avatar  avatar Sebastian Schlatow avatar davidwei_001 avatar junlei zhang avatar nant avatar evandrix avatar Stephan Wirsich avatar Jeremy Moore avatar yury avatar Scott Bulua avatar Mustafa Dikici avatar Karuppasamy M avatar Amadou Cisse avatar  avatar Ting Kuei avatar Ram Ravuri avatar Richard Hess avatar  avatar Fred avatar Yin Xiaoyu avatar Sylvain Bannier avatar ney chang avatar Peter Zakin avatar SPARK avatar Andrew Hubbell avatar HoNooD avatar Stan Pam avatar alfa avatar Jasmine Hegman avatar Aleksey Hohulin avatar Daniel Mahadi avatar kimhou avatar Tadas Domarkas avatar may ang avatar Xiaonan Cui avatar Victor Chen avatar Prashant Andani avatar  avatar timelyportfolio avatar James Cloos avatar luismahou avatar Qiang Han avatar Ilnur Khalilov avatar Al Geas avatar Günay Mert Karadoğan avatar FD2008 avatar Nima Mehanian avatar Steve Armstrong avatar Mehmet Ali Kıpçak avatar  avatar vincent guo avatar wangxiaolei avatar  avatar Gordon Dent avatar aurimas avatar Mitermayer Reis avatar Aaron Kushner avatar Flarnie Marchan avatar  avatar home3k avatar Viacheslav Shabelnyk avatar Zhe Feng avatar Firdaus Ramlan avatar Sergii Bezliudnyi avatar Laima Tazmin avatar echo avatar moro-programmer avatar aleksandr.rakov avatar Fernando Diaz avatar  avatar  avatar  avatar Le Anh Tung avatar NoScripter avatar Tony Brown avatar rferrari avatar Jeffrey Sun avatar Alsmile avatar GreyWolf avatar Andrei Arkhipov avatar  avatar chuter avatar

draft-js's Issues

More examples

I'd love to see a few more examples of usage:

  • Custom blocks containing text (maybe tables? related to #41)
  • Media (Images, videos or simply colored divs, I struggle with having those behave like a part of the document, like deleting them or adding a new line after them; drag&drop (#40) and cut/copy/paste would be even better)
  • Selection tracking (something like inline toolbars, related to #45)

Separate "Model" and "Components" into separate modules (and repos)?

Currently, draft-js has its dependencies listed as 'React' and 'ReactDOM' but it appears that only the "components" need those dependencies.

As somebody who would like to leverage the "model" features of this framework inside of a library other than React and ReactDOM, I would like to have the ability to include just the "model" code as a dependency in my project.

I'm curious what your thoughts are regarding splitting this framework into two separate modules, presumably one being the "model" layer and the other being the (react) "components" (which will depend on the model).

If it is decided that this change makes sense, I'm open to helping out via pull-requests, ect...

Please let me know what I can do to help.

Context-oriented behaviour

Hello and thank you for your yet another awesome solution.

Just watched the demo on project page and noticed it doesn't have context-oriented behaviour. What does it mean?

  • When I switch to H1-H5 mode I'd like to turn off this mode by Enter (new line) key.
  • When I switch to list mode I'd like to create a new level by Tab key.

It seems the good example for improving UX is focusing on Apple Pages to get good ideas and inherit user expectations.

The final space is `nbsp` (ascii 160), internal spaces are ascii 20

if you type a b and call editorState.getCurrentContent().getPlainText() the internal space is a normal space but the final space is ascii 160. This causes problems if you want to match this text against other strings. I fixed it externally with the code below, but maybe this fix should be handled internally?

  cleanPlainText(editorState) {
    const text = editorState.getCurrentContent().getPlainText();
    const nbsp = String.fromCharCode(160);
    const regex = new RegExp(`${nbsp}`, 'g');
    return text.replace(regex, ' ');

Export DraftPasteProcessor, or better access to its methods

For use cases in which I have fragments of pre-existing HTML that I need to load into an editor as the initial content, my impression is that I'd need to make use of the built-in DraftPasteProcessor that is part of the paste handling.

Something like this is working for me:

import Draft from 'draft-js';

const {Editor, EditorState, RichUtils, ContentState} = Draft;
import DraftPasteProcessor from 'draft-js/lib/DraftPasteProcessor';

const htmlFragment = '<div><p>Hello <b>world!</b></p><ul><li>again</li></ul></div>';

class RichEditorExample extends React.Component {
  constructor(props) {

    const processedHTML = DraftPasteProcessor.processHTML(htmlFragment);
    const initialState = ContentState.createFromBlockArray(processedHTML);

    this.state = {editorState: EditorState.createWithContent(initialState)};

But it would appear that DraftPasteProcessor isn't exported along with the built package, so the import syntax is less than ideal, and I cannot use it if including only the dist file on the front-end.

Is there a better method for loading pre-existing HTML content, or could the paste-cleaning tools be included as part of the exported dist?

expected "5.6.0" to satisfy "4.x"

I got this error:

11:18 $ npm run build

> [email protected] prebuild /Users/cheng/Dev/draft-js
> node node_modules/fbjs-scripts/node/check-dev-engines.js package.json

  throw new assert.AssertionError({
AssertionError: Current node version is not supported for development, expected "5.6.0" to satisfy "4.x".
    at Object.<anonymous> (/Users/cheng/Dev/draft-js/node_modules/fbjs-scripts/node/check-dev-engines.js:39:3)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Function.Module.runMain (module.js:447:10)
    at startup (node.js:140:18)
    at node.js:1001:3

The line which caused the error:

node node_modules/fbjs-scripts/node/check-dev-engines.js package.json

My node version is 5.6.0 (I am using nvm) which is what the error message expects:

11:20 $ node --version

Any ideas of what I missed?


A component is `contentEditable` and contains `children` managed by React warning

When integrating draft-js into an existing project I get

Warning: A component is contentEditable and contains children managed by React. It is now your responsibility to guarantee that none of those nodes are unexpectedly modified or duplicated. This is probably not intentional.

I am using the rich text example, and that gives me this warnings:

Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of BlockStyleControls. See for more information.

Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of InlineStyleControls.

using the rich.htmlexample from the repository

Recommended way to create styles on-the-fly?

In a previous project similar to Draft.js I used JSS to create a dynamic stylesheet that I could manage classes and styles in real-time. Primarily for things like changing text color to a user-selected color, or changing font-size to something the user selects. This allowed for a lot of flexibility, but also meant that the styles didn’t have to be created up front. They were created on-the-fly, as the user selected them.

Is there a recommended way to create classes and/or styles (mostly inline) on-the-fly and applying to the selection?

Visually retaining selection after blur

How would you recommend visually retaining the text selection even when the editor is blurred? My initial thought was to use inline styles but I'd like to get a second opinion.

See the example below. I'd like the selection to still show when changing text properties from an input.

screen shot 2016-02-24 at 10 43 45 am
screen shot 2016-02-24 at 10 43 48 am

content.findEntityRanges() fails to find Entities after calling Modifier.applyEntity().

I'm using Draft to highlight hashtags in a readonly block of text (I understand Draft might not be the right tool for the job considering I don't require selection).

From what I understand, the correct approach should be:

  • map over each contentBlock
  • for each contentBlock find (start, end) ranges for each hashtag
  • for each hashtag, create an Entity and a SelectionState for the tag
  • apply that Entity using Modifier.applyEntity for the given SelectionState.

Here's what that looks like

const contentState = ContentState.createFromText(content);
contentState.getBlockMap().map(contentBlock => {
  this._findWithRegex(HASHTAG_REGEX, contentBlock, (start, end) => {
    let selectionState = SelectionState.createEmpty(contentBlock.getKey());
    selectionState = selectionState.merge({
      anchorOffset: start,
      focusKey: contentBlock.getKey(),
      focusOffset: end,

    const tag = contentBlock.getText().slice(start, end);
    const key = Entity.create('HASHTAG', 'MUTABLE', {tag: tag});

    Modifier.applyEntity(contentState, selectionState, key);

where this._findWithRegex is the same function from the tweet example.

After doing this, I expect to be able to apply a decorator strategy using the following:

_findHashtagEntitiesStrategy(contentBlock, callback) {
    (character) => {
      const entityKey = character.getEntity();
      return (
        entityKey !== null &&
        Entity.get(entityKey).getType() === 'HASHTAG'

However it seems that contentBlock.findEntityRanges fails to find any Entitys for the any of the ContentBlocks.

Unable to delete blockquote if its the top element

screen shot 2016-02-22 at 9 54 16 pm

Video reproducing the issue

Steps to reproduce

I am using node v4.3.1

  1. Build the project and open examples/rich.html
  2. Click Blockquote
  3. Hit Enter to create another blockquote
  4. Use the arrow keys (or mouse) to go up one line to the top blockquote
  5. Hit Delete



The blockquote would delete allowing you to add new text type(s) to the line


The blockquote does not delete if there are other blockquotes below it, making it difficult to
go back and add lines above it.

The issue only occurs if the topmost line is a blockquote.

Support for tables

Is there any plans for adding support for tables to draft.js? I can't find any mention of it in the documentation.

Aggressive Warning

Warning: A component is contentEditable and contains children managed by React. It is now your responsibility to guarantee that none of those nodes are unexpectedly modified or duplicated. This is probably not intentional.

Is this needed for every onChange? Seems to do justice just on the component mounting.

Ps. This project made my day.

Missing doc on undo redo

The EditorState's push() method seems really important since it controls all state changes. I'm looking to get a mental map of which EditorChangeType strings to use on EditorState after the various Modifier methods (e.g. "insert-character" or what).

There's a reference of an advanced topic doc on undo/redo but it 404s. I don't see a doc in the repo to my knowledge.

Any chance it got missed on accident?

Current selection DOM element

I am trying to get the current selection element so that I can calculate the offset from the top of the document. I would like to position buttons on the left of the cursor like used in Facebook Note editor.

screenshot 2016-02-23 09 18 26

Is there an easy way to get the selected dom element?

Doesn't currently work in IE11

On IE11, doesn't show the editor. Similarly for a basic editor running locally.

if (!query.startsWith(name)) --> Object doesn't support property or method 'startsWith'

[Chrome] Issue when inserting space as the last character

When inserting a final space, the space is dropped, and when manually enterring text at the end, the enterred character is inserted after the cursor.

The following code reproduce the issue:

class MySpaceTestEditor extends React.Component {

  constructor(props) {
    this.state = {
      editorState: EditorState.createEmpty(),

  onChange = (editorState) => {

  onAdd = (value) => {
    let editorState = this.state.editorState;
    let contentState = editorState.getCurrentContent();

    contentState = Modifier.replaceText(
      ', ',
    editorState = EditorState.push(editorState, contentState, 'add-coma');

    this.setState({editorState: editorState});

  render() {
    const {editorState} = this.state;
    return (

Warning: A component is `contentEditable` and contains `children` managed by React

The following is an example editor component

import React from 'react';
import {Editor, EditorState} from 'draft-js';

export default class MyEditor extends React.Component {

constructor(props) {

    this.state = {
        editorState: EditorState.createEmpty()

onChange = (editorState) => {

render() {
    const {editorState} = this.state;
    return <Editor editorState={editorState} onChange={this.onChange} />;


And in my parent component

import MyEditor from './MyEditor'

.... // in the render() method
render() {
let error = this.getError();

    return (
        <form className="post__form">
            <div className="form-group">
                <label htmlFor="title">Title</label>
                <input type="text" ref="title" className="form-control" id="title" placeholder="Title" />
            <div className="form-group">
                <label htmlFor="description">Description</label>

                <MyEditor />

            <button type="submit" onClick={this.onClickHandler.bind(this)} className="btn btn-default">Submit</button>


And I see this warning

Warning: A component is contentEditable and contains children managed by React. It is now your responsibility to guarantee that none of those nodes are unexpectedly modified or duplicated. This is probably not intentional.

Initial rendered data

Can we feed initial content data for initialization? If so, does it accept html as a format?

The reason is that I am seeking to find answers on how to convert an already existing project that was made with tinymce and access a possible migration to draft-js.

Plain text support

If there any flag or API to turn off the rich text saving of this component. We have an editor that we need to allow the user to view the source/html tags as well as the WYSIWYG output.


convertFromRaw returns Array and not ContentState

From the documentation

convertFromRaw(rawState: RawDraftContentState): ContentState
Given a raw state, convert it to ContentState object. This is useful when restoring contents to use within a Draft editor.

From my testing, convertFromRaw actually returns an Array of ContentBlock objects. To convert this back to a ContentState you must do the following:


Failed at the [email protected] prebuild script


I get an error on npm run build with latest node and npm release

throw new assert.AssertionError({
AssertionError: Current node version is not supported for development, expected "5.7.0" to satisfy "4.x".

npm ERR! Darwin 15.3.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "build"
npm ERR! node v5.7.0
npm ERR! npm  v3.7.3

How to append text to the end

  _insertText() {
    const editorState = this.state.editorState;
    const selection = editorState.getSelection();
    const contentState = editorState.getCurrentContent();
    const ncs = Modifier.insertText(contentState, selection, "wefoiwjoefjwoiefjoiwjefio");
    const es = EditorState.push(editorState, ncs, 'insert-fragment');

With above codes, i can't get the wef.... to be append to the end. I have work on this problem for hours, but still can't found the solution. The above code is written according to Tex sample.

Backspace and content editing broken on Pale Moon

For a while now, content editing and especially backspacing over text (one has to press backspace one key at a time with pauses between presses) in the Pale Moon browser has been broken. With the editor having been released as open source here now, we've finally been able to get more details about the apparent cause of the issue.

Holding down or rapidly pressing the key inserts control characters apparently instead of actually acting on the control characters as expected.

Reference post and thread:

The demo page has the same issue as the live Facebook production site, and displays the following behavior:

Upon loading first the following is thrown in the console:

[] "Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `BlockStyleControls`. See for more information."
[] "Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `InlineStyleControls`. See for more information."

With every keypress, another warning is spawned in the console:

[] "Warning: A component is `contentEditable` and contains `children` managed by React. It is now your responsibility to guarantee that none of those nodes are unexpectedly modified or duplicated. This is probably not intentional."

Inserting content through an extension causes a duplication issue.

Hi, I'm working on a chrome extension that lets you input text through it. Unfortunately Draft.js breaks when inputting in a standard way.

Steps to reproduce:

  1. Load
  2. Open Chrome Dev Tools
  3. Select the Draft.js input box so that the input caret is present
  4. execute document.execCommand("insertHTML", false, "X"); in the dev tools console

Result expected:
X is added to the input box

Actual result:
X is added to the input box twice. You're able to delete one of the instances, but the other one is undeletable but is selectable.

Note: Once at least one character has been typed into the Draft.js input the command works as expected.

Screenshot of the result:
screen shot 2016-02-22 at 8 09 26 pm

Perisisting / Displaying Draft.js content

Great project, exactly what I'm looking for, after playing around I understand how to get a raw js representation of the content from the editorState


Is this Raw state what your are persisting to a DB?

Coupled with that - how are you handling display of the content? Are there any utilities to convert this to a viewable format e.g. HTML? It's fine if the answer is 'you need to write your own parsers for the raw format' but would be good to have some pointers to how best to parse Draft.js raw into other formats?

I guess you must be doing something kind of conversion at FB, but maybe that's a wrong assumption, any guidance would be much appreciated.

Drag & Drop

I'd love to know what the ideal way to implement drag&drop of blocks, like the latex component in the tex example, would be. I see that the facebook notes editor does not provide such a feature for images. Any info on that?

RichUtils.toggleInlineStyle() running a bit slow locally

I’m using the Rich example as a starting point for some testing. When I run the example locally it responds to interaction quickly, but when I drop it into an existing app the inline style actions begin to slow down noticeably.

Here is a video illustrating the difference in response times between block- and inline-style toggles:

You’ll see there is a noticeable lag time when clicking any of the inline style buttons.

I’ve stripped the component down to nothing but Draft, but it still lags. Sometimes even >1 second. Any suggestion on what to look for, or common issues that cause this kind of behavior?

convertFromRaw returns an Array of ContentBlocks not a ContentState

Hi there,

As documented here the function convertFromRaw should return a ContentState object.

However it returns an array of ContentBlock objects.

This works:

var data = '{"entityMap":{},"blocks":[{"key":"4oah6","text":"Dieser Test","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":7,"length":4,"style":"BOLD"},{"offset":0,"length":11,"style":"CODE"},{"offset":0,"length":6,"style":"ITALIC"}],"entityRanges":[]}]}'

var json = JSON.parse(data)

var blockArray = convertFromRaw(json);

var contentState = ContentState.createFromBlockArray(blockArray);

var editorState = EditorState.createWithContent(contentState);

However this throws an error:

var contentState = convertFromRaw(json);

var editorState = EditorState.createWithContent(contentState);

screen shot 2016-02-23 at 00 56 54

Is this a mistake in the docs or a bug?

Export FlowTypes in npm package

I tried to use Flow in combination with Draft, but couldn't get it up & running. Maybe I missed something, but there seem not any flow related files when downloading the package on npm.

As Draft has flowtypes it should be just a change in the build process. Im happy to do a PR in case you would want to see this as well.

Background info:

Block-type changes can affect adjacent sibling block


  • Navigate to the Draft.js homepage
  • Add a few blocks of text
  • Triple-click a block of text
    • This will select the entire block
  • Change the block type to H1


  • The block type for the selected line changes to a heading


  • The block type for the selected line and the following line changes to a heading


As I typed this bug with Github Markdown editor, I noticed it also demonstrates this behavior (triple-clicking a line and applying bold will drop the trailing ** at the beginning of the next line). Maybe this is out of the hands of Draft. However, I do believe that fixing the issue would lead to more reasonable UX.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.