diff --git a/ivette/src/dome/renderer/text/richtext.tsx b/ivette/src/dome/renderer/text/richtext.tsx
index ecea1ee55b44f991b4588ab5d2f004ca99cd2a50..057c71993768491f35e04e2b1fbc4734c872c37a 100644
--- a/ivette/src/dome/renderer/text/richtext.tsx
+++ b/ivette/src/dome/renderer/text/richtext.tsx
@@ -38,14 +38,54 @@ export function byDepth(a : Range, b : Range): number
   return (a.length - b.length) || (b.offset - a.offset);
 }
 
+/* -------------------------------------------------------------------------- */
+/* --- Code Mirror Utils                                                  --- */
+/* -------------------------------------------------------------------------- */
+
+type View = CM.EditorView | null;
+
+class Field<A> {
+  readonly extension : CS.Extension;
+  readonly field : CS.StateField<A>;
+  private readonly annot : CS.AnnotationType<A>;
+
+  constructor(init: A) {
+    const annot = CS.Annotation.define<A>();
+    const field = CS.StateField.define<A>({
+      create: () => init,
+      update: (fd: A, tr: CS.Transaction) => tr.annotation(annot) ?? fd,
+    });
+    this.annot = annot;
+    this.field = field;
+    this.extension = [ field ];
+  }
+
+  get(view: View) : A | undefined {
+    return view?.state.field(this.field);
+  }
+
+  set(view: View, value?: A): void {
+    if (view && value !== undefined) {
+      view.dispatch({ annotations: this.annot.of(value) });
+    }
+  }
+
+}
+
+/* -------------------------------------------------------------------------- */
+/* --- Read Only                                                          --- */
+/* -------------------------------------------------------------------------- */
+
+const ReadOnly = new Field(false);
+
 /* -------------------------------------------------------------------------- */
 /* --- Editor View                                                        --- */
 /* -------------------------------------------------------------------------- */
 
 function createView(parent: Element): CM.EditorView {
   const extensions : CS.Extension[] = [
-    //CS.EditorState.readOnly.of(false),
-  ]
+    ReadOnly, CS.EditorState.readOnly.from(ReadOnly.field)
+  ];
   const state = CS.EditorState.create({ extensions });
   return new CM.EditorView({ state, parent });
 }
@@ -55,29 +95,33 @@ function createView(parent: Element): CM.EditorView {
 /* -------------------------------------------------------------------------- */
 
 export interface RichTextProps {
+  readOnly?: boolean;
   className?: string;
   style?: CSSProperties;
 }
 
 export function RichText(props: RichTextProps) : JSX.Element {
-  type View = CM.EditorView | null;
-  const parent = React.useRef(null);
-  const editor = React.useRef<View>(null);
+  const [view, setView] = React.useState<View>(null);
+
+  // ---- Updates
+  const { readOnly } = props;
+  React.useEffect(() => ReadOnly.set(view, readOnly), [view, readOnly]);
+
+  // ---- Mount & Unmount Editor
+  const [nodeRef, setRef] = React.useState<Element | null>(null);
   React.useEffect(() => {
-    const div = parent.current;
-    if (!div) return;
-    const view = createView(div);
-    editor.current = view;
-    return () => {
-      editor.current = null;
-      view.destroy();
-    };
-  }, []);
+    if (!nodeRef) return;
+    const view = createView(nodeRef);
+    setView(view);
+    return () => { setView(null); view.destroy(); };
+  }, [nodeRef]);
+
+  // ---- Editor DIV
   const className = classes(
     'cm-global-box',
     props.className
   );
-  return <div className={className} style={props.style} ref={parent} />;
+  return <div className={className} style={props.style} ref={setRef} />;
 }
 
 /* -------------------------------------------------------------------------- */
diff --git a/ivette/src/sandbox/text.tsx b/ivette/src/sandbox/text.tsx
index 95453ba7f21ef64437ac716d85d1e0a6ac5e12b0..521cdabb2121f2ded66e40fe48314b6463b5ba6a 100644
--- a/ivette/src/sandbox/text.tsx
+++ b/ivette/src/sandbox/text.tsx
@@ -26,6 +26,8 @@
 /* -------------------------------------------------------------------------- */
 
 import React from 'react';
+import { Hbox } from 'dome/layout/boxes';
+import { Checkbox } from 'dome/controls/buttons';
 import { RichText } from 'dome/text/richtext';
 import { registerSandbox } from 'ivette';
 
@@ -34,7 +36,15 @@ import { registerSandbox } from 'ivette';
 /* -------------------------------------------------------------------------- */
 
 function UseText(): JSX.Element {
-  return <RichText />;
+  const [readOnly, setReadOnly] = React.useState(false);
+  return (
+    <>
+      <Hbox>
+        <Checkbox label="Read Only" value={readOnly} onChange={setReadOnly} />
+      </Hbox>
+      <RichText readOnly={readOnly}/>
+    </>
+  );
 }
 
 /* -------------------------------------------------------------------------- */