Skip to content

Commit e4c62f7

Browse files
Add icon argument to smartblock buttons (#134)
* Add icon customization for SmartBlock buttons with Blueprint icons Co-authored-by: mclicks <mclicks@gmail.com> * Update documentation for SmartBlock icon parameter and refactor icon handling in code - Corrected capitalization of the `icon` parameter to `Icon` in documentation. - Enhanced examples to reflect the updated parameter name. - Refactored icon handling logic in the code to validate Blueprint icon names and improve icon display logic. - Adjusted default icon display behavior based on the new parameter structure. * 1.11.0 * Update SmartBlock icon examples in documentation to reflect actual Blueprint.js icons * Update SmartBlock icon documentation to clarify Blueprint.js icon names --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
1 parent 4983f74 commit e4c62f7

File tree

4 files changed

+71
-25
lines changed

4 files changed

+71
-25
lines changed

docs/060-alternative-methods.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ The caption of the button is also available in the SmartBlock workflow under the
5050

5151
## Predefined Variables
5252

53-
There are currently 5 predefined variables: `RemoveButton`, `Order`, `TargetRef`, `Clear`, and `Sibling`.
53+
There are currently 6 predefined variables: `RemoveButton`, `Order`, `TargetRef`, `Clear`, `Sibling`, and `Icon`.
5454

5555
### Remove Button
5656

@@ -110,6 +110,25 @@ This button will not remove the Smartblock button, clear existing text on the bl
110110

111111
https://github.com/RoamJS/smartblocks/assets/3792666/eed8027b-179d-437b-a0be-c88b1d577c6a
112112

113+
### Icon
114+
115+
By default, SmartBlock buttons display a lego icon. You can customize or disable this icon using the `Icon` parameter:
116+
117+
**Examples**
118+
119+
- `{{Today:SmartBlock:myWorkflow:Icon=false}}` - No icon will be displayed
120+
- `{{Today:SmartBlock:myWorkflow:Icon=none}}` - No icon will be displayed
121+
- `{{Today:SmartBlock:myWorkflow:Icon=clipboard}}` - Display a Blueprint.js clipboard icon
122+
- `{{Today:SmartBlock:myWorkflow:Icon=refresh}}` - Display a Blueprint.js refresh icon
123+
124+
The Icon parameter accepts:
125+
126+
- `false` or `none` - Hides the icon completely
127+
- Any valid [Blueprint.js icon name](https://blueprintjs.com/docs/versions/3/#icons) - Displays that Blueprint icon instead of the default lego icon
128+
- When omitted - Shows the default lego icon
129+
130+
Note: The global "Hide Button Icon" setting overrides the `Icon` parameter.
131+
113132
# Bulk Trigger
114133

115134
You can run multiple SmartBlock workflows across multiple pages. In the Roam command palette, there will be an option called "Run Multiple SmartBlocks", which will open this dialog on click:

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "smartblocks",
3-
"version": "1.10.0",
3+
"version": "1.11.0",
44
"description": "Create custom and programmable templates from within Roam!",
55
"main": "./build/main.js",
66
"scripts": {

src/index.ts

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import DailyConfigComponent from "./components/DailyConfigComponent";
4545
import { runDaily } from "./utils/scheduleNextDailyRun";
4646
import getFullTreeByParentUid from "roamjs-components/queries/getFullTreeByParentUid";
4747
import { zCommandOutput } from "./utils/zodTypes";
48+
import { IconNames } from "@blueprintjs/icons";
4849

4950
const getLegacy42Setting = (name: string) => {
5051
const settings = Object.fromEntries(
@@ -556,11 +557,21 @@ export default runExtension(async ({ extensionAPI }) => {
556557
[0]: full,
557558
} = match;
558559
const [workflowName, args = ""] = buttonText.split(":");
560+
const variables = Object.fromEntries(
561+
args
562+
.replace(/\[\[[^\]]+\]\]/g, (m) => m.replace(/,/g, "ESCAPE_COMMA"))
563+
.split(",")
564+
.filter((s) => !!s)
565+
.map((v) => v.replace(/ESCAPE_COMMA/g, ",").split("="))
566+
.map(([k, v = ""]) => [k, v])
567+
);
568+
variables["ButtonContent"] = buttonContent;
559569
const clickListener = () => {
560570
const workflows = getCustomWorkflows();
561571
const availableWorkflows = getCleanCustomWorkflows(workflows);
562572
const { uid: srcUid } =
563573
availableWorkflows.find(({ name }) => name === workflowName) || {};
574+
564575
if (!srcUid) {
565576
createBlock({
566577
node: {
@@ -570,18 +581,6 @@ export default runExtension(async ({ extensionAPI }) => {
570581
parentUid,
571582
});
572583
} else {
573-
const variables = Object.fromEntries(
574-
args
575-
.replace(/\[\[[^\]]+\]\]/g, (m) =>
576-
m.replace(/,/g, "ESCAPE_COMMA")
577-
)
578-
.split(",")
579-
.filter((s) => !!s)
580-
.map((v) => v.replace(/ESCAPE_COMMA/g, ",").split("="))
581-
.map(([k, v = ""]) => [k, v])
582-
);
583-
variables["ButtonContent"] = buttonContent;
584-
585584
const keepButton =
586585
/false/i.test(variables["RemoveButton"]) ||
587586
/false/i.test(variables["42RemoveButton"]);
@@ -710,20 +709,48 @@ export default runExtension(async ({ extensionAPI }) => {
710709
}
711710
}
712711
};
712+
713713
el.addEventListener("click", clickListener);
714-
if (!hideButtonIcon && !hideIcon) {
715-
const img = new Image();
716-
img.src =
717-
"https://raw.githubusercontent.com/RoamJS/smartblocks/main/src/img/lego3blocks.png";
718-
img.width = 17;
719-
img.height = 14;
720-
img.style.marginRight = "7px";
721-
el.insertBefore(img, el.firstChild);
714+
715+
const iconSetting = variables["Icon"]?.toLowerCase();
716+
717+
const shouldHideIcon =
718+
hideButtonIcon ||
719+
hideIcon ||
720+
iconSetting === "false" ||
721+
iconSetting === "none";
722+
723+
const isValidBlueprintIcon = (
724+
name: string
725+
): name is (typeof IconNames)[keyof typeof IconNames] =>
726+
Object.values(IconNames).includes(name as any);
727+
728+
if (!shouldHideIcon) {
729+
let iconElement: HTMLElement | null = null;
730+
731+
if (iconSetting && isValidBlueprintIcon(iconSetting)) {
732+
iconElement = document.createElement("span");
733+
iconElement.className = `bp3-icon bp3-icon-${iconSetting}`;
734+
iconElement.style.marginRight = "7px";
735+
iconElement.style.marginLeft = "0px";
736+
} else {
737+
// Default lego icon
738+
const img = new Image();
739+
img.src =
740+
"https://raw.githubusercontent.com/RoamJS/smartblocks/main/src/img/lego3blocks.png";
741+
img.style.marginRight = "7px";
742+
img.width = 17;
743+
img.height = 14;
744+
iconElement = img;
745+
}
746+
747+
el.insertBefore(iconElement, el.firstChild);
722748
return () => {
723-
img.remove();
749+
iconElement?.remove();
724750
el.removeEventListener("click", clickListener);
725751
};
726752
}
753+
727754
return () => {
728755
el.removeEventListener("click", clickListener);
729756
};

0 commit comments

Comments
 (0)