# Make ActionButtons editable

**URL:** <https://community.silverbullet.md/t/make-actionbuttons-editable/2535>\
**Category:** Ideas\
**Created:** [June 23, 2025, 3:25pm UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535 "2025-06-23T15:25:57Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![zeus-web](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zeus-web/32/571_2.png) [@zeus-web](https://community.silverbullet.md/u/zeus-web)\
**Post date:** [June 23, 2025, 3:25pm UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/1 "2025-06-23T15:25:57Z")

</div>

I just tried out the “forcedROMode” described in the docs in the ActionButtons section.

While implementing a “RO-Toggle” command, my demand came up: I’d like to edit the Action-Buttons “on-the-fly” to change a button/icon to represent the current status.

Would be nice, if the “actionbutton.define” function would get an “actionbutton.update” equivalent 🙂  
(or maybe an “actionbutton.delete” to remove a button to create it new)

Dont’t know, if changing buttons at runtime is possible, anyway…

---

<div class="post-metadata">

**Author:** ![22rw](https://community.silverbullet.md/user_avatar/community.silverbullet.md/22rw/32/659_2.png) [@22rw](https://community.silverbullet.md/u/22rw)\
**Post date:** [June 29, 2025, 10:28am UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/2 "2025-06-29T10:28:45Z")

</div>

How about something like this:

```lua
actionButton.define {
  icon = (editor.getUiOption("forcedROMode") and "eye-off") or "eye",
  run = function()
    local mode = editor.getUiOption("forcedROMode")
    editor.setUiOption("forcedROMode", not mode)
    editor.rebuildEditorState()
    editor.reloadConfigAndCommands()
  end
}

```

---

<div class="post-metadata">

**Author:** ![zeus-web](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zeus-web/32/571_2.png) [@zeus-web](https://community.silverbullet.md/u/zeus-web)\
**Post date:** [June 29, 2025, 5:04pm UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/3 "2025-06-29T17:04:08Z")

</div>

Sounds great. Good Idea, i will try that as soon as possible 🙂

---

<div class="post-metadata">

**Author:** ![mjf](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mjf/32/654_2.png) [@mjf](https://community.silverbullet.md/u/mjf)\
**Post date:** [June 30, 2025, 6:01am UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/4 "2025-06-30T06:01:42Z")

</div>

It works, thanks! 🙂

---

<div class="post-metadata">

**Author:** ![mjf](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mjf/32/654_2.png) [@mjf](https://community.silverbullet.md/u/mjf)\
**Post date:** [June 30, 2025, 6:17am UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/5 "2025-06-30T06:17:31Z")

</div>

The only thing that the top bar mini-editor does not reflect the mode. It would be nice if it also can be turned to read only mode somehow. Any ideas?

---

<div class="post-metadata">

**Author:** ![zeus-web](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zeus-web/32/571_2.png) [@zeus-web](https://community.silverbullet.md/u/zeus-web)\
**Post date:** [June 30, 2025, 9:02am UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/6 "2025-06-30T09:02:31Z")

</div>

Tried it and it works like a charm! Thanks again!  
In fact, that basically is exactly what I tried to achieve.

The puzzle piece I was missing obviously is the “actionbutton.define” function.  
Until now I used the "config.set { actionbuttons = … } definition.

And thanks for the idea to simply reload the config/UI. Did not see the forest for the trees here… 😉

Only thing I have to figure out now is how to define the position of the button, as via “actionbuttons.define”, the button is placed at the end (which is only a cosmetic issue for me…)

---

<div class="post-metadata">

**Author:** ![22rw](https://community.silverbullet.md/user_avatar/community.silverbullet.md/22rw/32/659_2.png) [@22rw](https://community.silverbullet.md/u/22rw)\
**Post date:** [July 1, 2025, 8:02pm UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/7 "2025-07-01T20:02:26Z")

</div>

Glad that worked 😃  
Looking at the implementation, the `config.set { actionbuttons = ... }` method should still work, as `actionbutton.define` is just a wrapper for that. I think what’s changed is that instead of the `command` key you’d use the `run` key with a function value. That way you can still control the order in wich the buttons are placed. Didn’t try that yet though.

---

<div class="post-metadata">

**Author:** ![22rw](https://community.silverbullet.md/user_avatar/community.silverbullet.md/22rw/32/659_2.png) [@22rw](https://community.silverbullet.md/u/22rw)\
**Post date:** [July 1, 2025, 8:26pm UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/8 "2025-07-01T20:26:30Z")

</div>

Don’t think there’s a build-in way, but I found a way to do it with dom-manipulation:

```js
js.window.document.querySelector(".sb-mini-editor .cm-content").contentEditable = false

```

What I ended up with:

```lua
local ro = editor.getUiOption("forcedROMode")
actionButton.define {
  mobile = true,
  icon = (ro and "edit2") or "eye",
  run = function()
    local cursor = editor.getCursor()
    editor.setUiOption("forcedROMode", not ro)
    editor.rebuildEditorState()
    editor.reloadConfigAndCommands()
    js.window.document.querySelector(".sb-mini-editor .cm-content").contentEditable = ro
    editor.moveCursor(cursor, true)
  end
}

```

---

<div class="post-metadata">

**Author:** ![mjf](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mjf/32/654_2.png) [@mjf](https://community.silverbullet.md/u/mjf)\
**Post date:** [July 2, 2025, 6:38am UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/9 "2025-07-02T06:38:47Z")

</div>

This is for the `CONFIG` if somebody needs it…

````lua
```space-lua
config.set {
  actionButtons = {
    -- some buttons
    {
      -- mobile: true,
      icon = editor.getUiOption('forcedROMode') and 'edit' or 'eye',
      run = function()
        local ro = editor.getUiOption('forcedROMode')
        local cur = editor.getCursor()
        editor.setUiOption('forcedROMode', not ro)
        editor.rebuildEditorState()
        editor.reloadConfigAndCommands()
        js.window.document.querySelector('.sb-mini-editor .cm-content').contentEditable = ro
        editor.moveCursor(cur, true)
      end,
      description = 'Toggle read-only mode'
   },
   -- other buttons
}
```

````

The `mobile: true` causes it will apply on mobile device only and the button will be invisible on non-mobile device.

---

<div class="post-metadata">

**Author:** ![zeus-web](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zeus-web/32/571_2.png) [@zeus-web](https://community.silverbullet.md/u/zeus-web)\
**Post date:** [July 2, 2025, 7:31am UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/10 "2025-07-02T07:31:53Z")

</div>

Thanks a lot!! This is great!!  
This way it is even possible to define the positions of the icons.

---

<div class="post-metadata">

**Author:** ![mjf](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mjf/32/654_2.png) [@mjf](https://community.silverbullet.md/u/mjf)\
**Post date:** [July 2, 2025, 9:55am UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/11 "2025-07-02T09:55:43Z")

</div>

~~Some support for ordering is needed for `actionButton.define{}`. I’ve no time to inspect now, but perhaps there is some already. It would be weird a little to not allow ordering of the buttons in the first plan. 🙂~~

---

<div class="post-metadata">

**Author:** ![mjf](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mjf/32/654_2.png) [@mjf](https://community.silverbullet.md/u/mjf)\
**Post date:** [July 2, 2025, 11:25am UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/12 "2025-07-02T11:25:05Z")

</div>

**UPDATE** Of course there IS the priority already! 😃

Example:

```lua
actionButton.define {
  priority = 1000,
  -- the rest
}

```

> - `priority` (optional): determines priority of button (the higher, the earlier in the list)

Also see `Library/Std/Action Button.md`.

---

<div class="post-metadata">

**Author:** ![zeus-web](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zeus-web/32/571_2.png) [@zeus-web](https://community.silverbullet.md/u/zeus-web)\
**Post date:** [July 2, 2025, 12:03pm UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/13 "2025-07-02T12:03:33Z")

</div>

This is a pro and a con of [silverbullet.md](http://silverbullet.md) at the same time.  
It has so many hidden gems!  
Sometimes you only have to find them 🙂

(And sometimes you have to have the idea to search for them in the first place 😉 )

---

<div class="post-metadata">

**Author:** ![mjf](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mjf/32/654_2.png) [@mjf](https://community.silverbullet.md/u/mjf)\
**Post date:** [July 9, 2025, 7:44am UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/14 "2025-07-09T07:44:41Z")

</div>

I found one more thing that should not be “editable” in read-only mode. Tasks can still be clicked and edited. ☹ (I hit this one accidentaly while on mobile where I use this primarily.)

Also, it would be nice if we can hide the edit icon for `${}` queries. 🙂

Anything else? It will be splendid if we hack all of this together to achieve truly safe read-only mode to be used while rumbling on public transportation vehicles, won’t it? 😃

---

<div class="post-metadata">

**Author:** ![zeus-web](https://community.silverbullet.md/user_avatar/community.silverbullet.md/zeus-web/32/571_2.png) [@zeus-web](https://community.silverbullet.md/u/zeus-web)\
**Post date:** [July 9, 2025, 12:31pm UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/15 "2025-07-09T12:31:35Z")

</div>

Well, from my point of view I like it exacty the way it is now.  
For example:  
I write my shopping list to a note at home. Then I switch to readonly.  
Later in the shop I can still check my purchased items, but it prevents editing of the list itself.

Before I discovered readonly, I had several times, that I deleted some text by mistake instead of checking.

So, we might need two different read-only modes 😉

---

<div class="post-metadata">

**Author:** ![mjf](https://community.silverbullet.md/user_avatar/community.silverbullet.md/mjf/32/654_2.png) [@mjf](https://community.silverbullet.md/u/mjf)\
**Post date:** [July 9, 2025, 2:52pm UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/16 "2025-07-09T14:52:34Z")

</div>

I destroyed many things historicaly while using SB in weird and rushy situations that I would rather be safe on mobile. Just looking for a way to do it. The effort is also worth as example of what can be done using the more advanced APIs. And, it’s just a Lua function in the end. Put whatever suit you best in it. 🙂

---

<div class="post-metadata">

**Author:** ![Thaurin](https://community.silverbullet.md/letter_avatar_proxy/v4/letter/t/dbc845/32.png) [@Thaurin](https://community.silverbullet.md/u/Thaurin)\
**Post date:** [September 5, 2025, 12:44pm UTC](https://community.silverbullet.md/t/make-actionbuttons-editable/2535/17 "2025-09-05T12:44:25Z")

</div>

So I extended this with all of the above and some extra features like persistence, and made it easily configurable. You can now also (optionally):

- Disable the checkboxes!
- Remember the read-only mode across sessions and set it on reload, so that for example on mobile it will stay on read-only mode

This is what I’ve got now and it works great!

```space-lua
-- Must be set before actionButtons
config.set {
  readOnly = {
    mobileOnlyActionButton = false,
    disableCheckboxes = true,
    shortcut = 'Ctrl-alt-t',
    persistent = true,
    enabledIcon = 'edit',
    disabledIcon = 'eye'
  }
}

config.set {
  actionButtons = {
    -- Your other action buttons here...
    {
      mobile = config.get('readOnly').mobileOnlyActionButton,
      icon = editor.getUiOption("forcedROMode") and config.get('readOnly').enabledIcon or config.get('readOnly').disabledIcon,
      description = editor.getUiOption("forcedROMode") and "Enable edit mode" or "Enable read-only mode",
      run = function()
        editor.invokeCommand("Toggle Read-Only Mode")
      end
    }
  }
}

--
-- Read-only mode implementation

function toggleReadOnlyMode()
  local cursor = editor.getCursor()
  local mode = editor.getUiOption('forcedROMode')

  editor.setUiOption('forcedROMode', not mode)
  editor.rebuildEditorState()
  editor.reloadConfigAndCommands()
  js.window.document.querySelector('.sb-mini-editor .cm-content').contentEditable = mode

  if config.get('readOnly').persistent then
    clientStore.set('readOnly', not mode)
  end

  if mode == false and config.get('readOnly').disableCheckboxes then
    js.window.document.head.insertAdjacentHTML('beforeend',
      '<style id="readonly-checkbox-css">' ..
      '.sb-checkbox input[type="checkbox"] { pointer-events: none; cursor: default; opacity: 0.5; }' ..
      '</style>'
    )
  else
    checkbox_css = js.window.document.getElementById('readonly-checkbox-css')
    if checkbox_css ~= nil then
      checkbox_css.remove()
    end
  end

  editor.moveCursor(cursor, true)
end

command.define {
  name = 'Toggle Read-Only Mode',
  key = config.get('readOnly').shortcut,
  run = function()
    toggleReadOnlyMode()
  end
}

event.listen {
  name = 'system:ready',
  run = function(e)
    if config.get('readOnly').persistent
     
      then
      local readOnlyConfig = clientStore.get('readOnly')
      local readOnlyCurrent = editor.getUiOption('forcedROMode')
  
      if readOnlyConfig and not readOnlyCurrent then
        toggleReadOnlyMode()
      end
    end
  end
}

```
