Skip to content

Commit 2267d73

Browse files
trangdoan982claude
andauthored
ENG-906 Add node tag preview below tag input in settings (#967)
* ENG-906 Add node tag preview below tag input in settings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * pr comment --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 062f46a commit 2267d73

3 files changed

Lines changed: 55 additions & 39 deletions

File tree

apps/roam/src/components/settings/NodeConfig.tsx

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByPar
2424
import setInputSetting from "roamjs-components/util/setInputSetting";
2525
import { setDiscourseNodeSetting } from "~/components/settings/utils/accessors";
2626
import DiscourseNodeSuggestiveRules from "./DiscourseNodeSuggestiveRules";
27+
import { getNodeTagStyles } from "~/utils/getDiscourseNodeColors";
2728
import { isSyncEnabled } from "~/components/settings/utils/accessors";
2829
import {
2930
DiscourseNodeTextPanel,
@@ -180,19 +181,31 @@ const NodeConfig = ({
180181
parentUid={node.type}
181182
uid={shortcutUid}
182183
/>
183-
<DiscourseNodeTextPanel
184-
nodeType={node.type}
185-
title="Tag"
186-
description={`Designate a hashtag for marking potential ${node.text}.`}
187-
settingKeys={["tag"]}
188-
initialValue={node.tag}
189-
placeholder={generateTagPlaceholder(node)}
190-
error={tagError}
191-
onChange={setTagValue}
192-
order={2}
193-
parentUid={node.type}
194-
uid={tagUid}
195-
/>
184+
<div>
185+
<DiscourseNodeTextPanel
186+
nodeType={node.type}
187+
title="Tag"
188+
description={`Designate a hashtag for marking potential ${node.text}.`}
189+
settingKeys={["tag"]}
190+
initialValue={node.tag}
191+
placeholder={generateTagPlaceholder(node)}
192+
error={tagError}
193+
onChange={setTagValue}
194+
order={2}
195+
parentUid={node.type}
196+
uid={tagUid}
197+
/>
198+
{tagValue && (
199+
<div className="flex items-center gap-1.5 pl-1">
200+
<span className="text-xs italic text-gray-400">
201+
Preview:
202+
</span>
203+
<span style={color ? getNodeTagStyles(color) : undefined}>
204+
#{tagValue.replace(/^#/, "")}
205+
</span>
206+
</div>
207+
)}
208+
</div>
196209
<>
197210
<Label>
198211
Color

apps/roam/src/utils/getDiscourseNodeColors.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import { CSSProperties } from "react";
12
import { colord } from "colord";
23
import getPleasingColors from "@repo/utils/getPleasingColors";
34
import {
45
COLOR_ARRAY,
56
COLOR_PALETTE,
67
} from "~/components/canvas/DiscourseNodeUtil";
78
import getDiscourseNodes, { DiscourseNode } from "./getDiscourseNodes";
9+
import { formatHexColor } from "~/components/settings/DiscourseNodeCanvasSettings";
810

911
type GetDiscourseNodeColorsParams = {
1012
nodeType?: string;
@@ -39,3 +41,25 @@ export const getDiscourseNodeColors = ({
3941
const textColor = pleasingColors.text;
4042
return { backgroundColor, textColor };
4143
};
44+
45+
export const getNodeTagStyles = (color: string): CSSProperties | undefined => {
46+
const formattedColor = formatHexColor(color);
47+
if (!formattedColor) return undefined;
48+
const { background, text, border } = getPleasingColors(
49+
colord(formattedColor),
50+
);
51+
return {
52+
backgroundColor: background,
53+
color: text,
54+
border: `1px solid ${border}`,
55+
fontWeight: "500",
56+
padding: "2px 6px",
57+
borderRadius: "12px",
58+
margin: "0 2px",
59+
fontSize: "0.9em",
60+
whiteSpace: "nowrap",
61+
boxShadow: "0 1px 2px rgba(0, 0, 0, 0.05)",
62+
display: "inline-block",
63+
cursor: "pointer",
64+
};
65+
};

apps/roam/src/utils/initializeObserversAndListeners.ts

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,12 @@ import {
5050
} from "~/utils/renderTextSelectionPopup";
5151
import { renderNodeTagPopupButton } from "./renderNodeTagPopup";
5252
import { renderImageToolsMenu } from "./renderImageToolsMenu";
53-
import { formatHexColor } from "~/components/settings/DiscourseNodeCanvasSettings";
5453
import { getSetting } from "./extensionSettings";
5554
import { mountLeftSidebar } from "~/components/LeftSidebarView";
5655
import { getUidAndBooleanSetting } from "./getExportSettings";
5756
import { getFeatureFlag } from "~/components/settings/utils/accessors";
5857
import { getCleanTagText } from "~/components/settings/NodeConfig";
59-
import getPleasingColors from "@repo/utils/getPleasingColors";
60-
import { colord } from "colord";
58+
import { getNodeTagStyles } from "~/utils/getDiscourseNodeColors";
6159
import { renderPossibleDuplicates } from "~/components/VectorDuplicateMatches";
6260
import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle";
6361
import getPageTitleByPageUid from "roamjs-components/queries/getPageTitleByPageUid";
@@ -145,29 +143,10 @@ export const initObservers = async ({
145143
const normalizedNodeTag = node.tag ? getCleanTagText(node.tag) : "";
146144
if (normalizedTag === normalizedNodeTag) {
147145
renderNodeTagPopupButton(s, node, onloadArgs.extensionAPI);
148-
if (node.canvasSettings?.color) {
149-
const formattedColor = formatHexColor(node.canvasSettings.color);
150-
if (!formattedColor) {
151-
break;
152-
}
153-
const contrastingColor = getPleasingColors(
154-
colord(formattedColor),
155-
);
156-
157-
Object.assign(s.style, {
158-
backgroundColor: contrastingColor.background,
159-
color: contrastingColor.text,
160-
border: `1px solid ${contrastingColor.border}`,
161-
fontWeight: "500",
162-
padding: "2px 6px",
163-
borderRadius: "12px",
164-
margin: "0 2px",
165-
fontSize: "0.9em",
166-
whiteSpace: "nowrap",
167-
boxShadow: "0 1px 2px rgba(0, 0, 0, 0.05)",
168-
display: "inline-block",
169-
cursor: "pointer",
170-
});
146+
const color = node.canvasSettings?.color ?? "";
147+
const tagStyles = color ? getNodeTagStyles(color) : {};
148+
if (tagStyles) {
149+
Object.assign(s.style, tagStyles);
171150
}
172151
break;
173152
}

0 commit comments

Comments
 (0)