Hey guys,
I made a simple little color picker tool/widget (twidget?) using space-lua
Once activated, the tool lets you quickly visualize the color of any valid hex code that is currently selected.
Features
- Visualize Hex Colors: Instantly see the color of any selected hex code
- Color Palettes: Add new color pickers on the fly using the “Add Color” button. This will add a new color picker item to the current list and you can modify each one independently
- No External Dependencies: The complete functionality—from local Lua functions to command definitions—is contained within a single
space‑lua
script block. This keeps everything compact and prevents polluting your user space. - (Chromium) Eyedropper Tool: If you’re using a Chromium based browser - you can easily sample colors using the browser’s built-in eyedropper tool.
- Hex Code Flexibility: Supports hex codes with or without a leading
#
and also supports 3-character hex codes.
Note
- Because the tool makes use of the HTML
<input>
tag the actual underlying color picker implementation and feature set is browser dependent. - For example, Firefox does not have an eyedropper tool
Install
Since this tool was fully implemented in space-lua
, you can just copy the space-lua
code below and pate it directly in a space-lua
code block on any page.
Then reload your system and widgets (${[System: Reload]}
) for the ColorPicker script to take effect.
local function getSelectedtext()
local text = space.readPage(editor.getCurrentPage())
local cursorSelectionRange = editor.getSelection()
local extractedText = string.sub(text, cursorSelectionRange.from + 1, cursorSelectionRange.to)
return extractedText
end
-- Check if a string is a valid 3- or 6-digit hex color (with or without a leading '#')
local function isHex(s)
local txtMatch = (string.match(s, '^#?[A-Za-z0-9][A-Za-z0-9][A-Za-z0-9]$') or string.match(s, '^#?[A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9]$')) ~= nil
return txtMatch
end
local function expandHex36(hex)
-- Duplicate each character to form the 6-digit code
local r = string.sub(hex, 1, 1)
local g = string.sub(hex, 2, 2)
local b = string.sub(hex, 3, 3)
return r .. r .. g .. g .. b .. b
end
local function openSidePanelWContent(htmlContent)
-- js script to update color value on change
local jsScript = [[
const CP_ROOT = "colorp"
const CP_ID = "First"
const COLOR_PICKER_ID = `${CP_ROOT}${CP_ID}`
const COLOR_PICKER_LBL_ID = `${CP_ROOT}${CP_ID}Lbl`
const COLOR_PICKER_ADD_BTN_ID = `${CP_ROOT}AddColor`
const COLOR_PICKER_OL_ID = `${CP_ROOT}List`
const colorPicker = document.getElementById(COLOR_PICKER_ID)
const colorPickerLbl = document.getElementById(COLOR_PICKER_LBL_ID)
const colorPickerList = document.getElementById(COLOR_PICKER_OL_ID)
const addColorBtn = document.getElementById(COLOR_PICKER_ADD_BTN_ID)
var currentColorIndex = 0;
var lastSetColor = colorPickerLbl.innerText;
colorPicker.addEventListener("input", watchColorPicker, false);
colorPicker.addEventListener("change", watchColorPicker, false);
addColorBtn.addEventListener("click", addNewColor, false);
function watchColorPicker(event) {
colorPickerLbl.innerText = event.target.value;
lastSetColor = event.target.value
}
function watchColorPickerAll(event) {
const colorLabelID = event.target.id + "Lbl";
document.getElementById(colorLabelID).innerHTML = " " + event.target.value;
lastSetColor = event.target.value;
}
function addNewColor(event) {
const newColorID = `${CP_ROOT}Li${currentColorIndex}`;
// create list item
var li = document.createElement("li");
var odiv = document.createElement("div");
var colorBtn = document.createElement("input");
colorBtn.type = "color";
colorBtn.id = newColorID;
colorBtn.name = newColorID;
colorBtn.value = lastSetColor;
colorBtn.oninput = watchColorPickerAll;
var colorLbl = document.createElement("label");
colorLbl.id = `${newColorID}Lbl`;
colorLbl.for = newColorID;
colorLbl.innerHTML = " " + lastSetColor;
odiv.appendChild(colorBtn);
odiv.appendChild(colorLbl);
// append div to list item object and update list
li.appendChild(odiv)
colorPickerList.appendChild(li);
currentColorIndex++;
}
]]
-- Inject script and show the html content in the panl
editor.showPanel("rhs", 1, htmlContent, jsScript)
end
local function closeSidePanelWContent()
editor.hidePanel("rhs")
end
local function buildHTMLColorPicker(hex)
local html = "<div>" ..
"<input type='color' id='colorpFirst' value=#" .. hex .. ">" ..
"<label id='colorpFirstLbl' for='colorpFirst'>#" .. hex .. "</label>" ..
"<div>" ..
"<button id='colorpAddColor'>Add Color</button>" ..
"<hr/>" ..
"<ol id='colorpList'>" ..
"</ol>" ..
"</div>" ..
"</div>"
return html
end
command.define {
name = "ColorPicker - Show",
key = "Alt-p",
run = function()
local txt = getSelectedtext()
if isHex(txt) then
local hexVal = string.gsub(txt, '^#', '')
if string.len(hexVal) == 3 then
hexVal = expandHex36(hexVal)
end
local html = buildHTMLColorPicker(hexVal)
openSidePanelWContent(html)
editor.flashNotification(hexVal)
else
local defaultHex = "000000"
local html = buildHTMLColorPicker(defaultHex)
openSidePanelWContent(html)
editor.flashNotification(defaultHex)
end
end
}
command.define {
name = "ColorPicker - Hide",
key = "Escape",
run = function()
closeSidePanelWContent()
end
}
Usage
- Select a HEX Code
For example, select one of these:#3E56DA
d20
- Activate the Color Picker (while still selected)
- via. Keyboard Shortcut: (Win)
Alt - p
- via. Keyboard Shortcut: (Mac)
Opt - p
- via. Command Menu: Search for “ColorPicker - Show”
- via. Keyboard Shortcut: (Win)
- Deactivate the Color Picker:
- via. Keyboard Shortcut:
Escape
- via. Command Menu: Search for “ColorPicker - Hide”
- via. Keyboard Shortcut:
Demo Usage
Chromium
Firefox
Housekeeping
- If you wanna keep things a little more tidy, you can tag the page as
#meta
so it does not show up in your Page Navigation menu.- Then to access the page later you can use
ctrl-shift-k
and search for whatever you called it
- Then to access the page later you can use
- You can place the script in a page pretty much anywhere in your space and it should work. But to keep things from getting too messy, you should create a separate file for the Color Picker
- For example. I have my ColorPicker file located at:
Library/Custom/Libs/ColorPicker/ColorPicker.md
- For example. I have my ColorPicker file located at:
Color Picker Components
- Local Lua Functions: For tasks such as extracting the currently selected text, building HTML components, and injecting JavaScript event handlers, etc.
- Panel Management: Uses
editor.showPanel
andeditor.hidePanel
to display the color picker’s HTML content with custom JS. - Command Definitions: Utilizes
command.define
to create custom commands (and keyboard shortcuts) for activating and deactivating the Color Picker.
Some Background
The idea for this came about when I was trying out the super cool onespaceman theme for sb, but I really wanted to visualize and tweak some of the base theme colors without leaving SB.
Aside from the actual color picking functionality, I also wanted something that was extremely small and minimal so that it can be easily traced, understood and extended.
The color picker tool initially started out as a traditional plugin, but then I discovered space-lua
. And oh my god.
space-lua is going to change everything.
Todo:
- Export palette as csv
- Better UI tools (copy hex code)
- Simple color palette generator based on existing colors
Hopefully some of you get some good use out of it! Keen to hear any thoughts and suggestions.
Cheers,
Jay