diff --git a/src/components/markdown/__tests__/markdoc.test.tsx b/src/components/markdown/__tests__/markdoc.test.tsx
index f5967cca9..f02ae04a2 100644
--- a/src/components/markdown/__tests__/markdoc.test.tsx
+++ b/src/components/markdown/__tests__/markdoc.test.tsx
@@ -123,4 +123,42 @@ console.log('Hello');
expect(screen.getByText('Bold text')).toBeInTheDocument();
expect(screen.getByText('italic text')).toBeInTheDocument();
});
+
+ it('renders style tag with color', () => {
+ const content = '{% style color="red" %}red text{% /style %}';
+ render();
+
+ const styledEl = screen.getByText('red text');
+ expect(styledEl).toBeInTheDocument();
+ expect(styledEl).toHaveStyle({ color: 'red' });
+ });
+
+ it('renders style tag with background color', () => {
+ const content = '{% style bg="yellow" %}highlighted text{% /style %}';
+ render();
+
+ const styledEl = screen.getByText('highlighted text');
+ expect(styledEl).toBeInTheDocument();
+ expect(styledEl).toHaveStyle({ backgroundColor: 'yellow' });
+ });
+
+ it('renders style tag with both color and background', () => {
+ const content =
+ '{% style color="white" bg="blue" %}styled text{% /style %}';
+ render();
+
+ const styledEl = screen.getByText('styled text');
+ expect(styledEl).toBeInTheDocument();
+ expect(styledEl).toHaveStyle({ color: 'white', backgroundColor: 'blue' });
+ });
+
+ it('renders nested style tags', () => {
+ const content =
+ '{% style color="blue" %}outer {% style color="red" %}inner{% /style %}{% /style %}';
+ render();
+
+ const innerEl = screen.getByText('inner');
+ expect(innerEl).toBeInTheDocument();
+ expect(innerEl).toHaveStyle({ color: 'red' });
+ });
});
diff --git a/src/components/markdown/markdoc-components/index.ts b/src/components/markdown/markdoc-components/index.ts
index 55e6d7904..5d1fb597a 100644
--- a/src/components/markdown/markdoc-components/index.ts
+++ b/src/components/markdown/markdoc-components/index.ts
@@ -6,6 +6,7 @@ import InlineCode from './inline-code/inline-code';
import List from './list/list';
import SignalButton from './signal-button/signal-button';
import StartWorkflowButton from './start-workflow-button/start-workflow-button';
+import Style from './style/style';
// Export all components that Markdoc can use
export const markdocComponents = {
@@ -17,6 +18,7 @@ export const markdocComponents = {
InlineCode,
Image,
Br,
+ Style,
};
export type MarkdocComponents = typeof markdocComponents;
diff --git a/src/components/markdown/markdoc-components/style/style.markdoc.ts b/src/components/markdown/markdoc-components/style/style.markdoc.ts
new file mode 100644
index 000000000..ea1a21683
--- /dev/null
+++ b/src/components/markdown/markdoc-components/style/style.markdoc.ts
@@ -0,0 +1,13 @@
+export const styleMarkdocSchema = {
+ render: 'Style',
+ attributes: {
+ color: {
+ type: String,
+ required: false,
+ },
+ bg: {
+ type: String,
+ required: false,
+ },
+ },
+};
diff --git a/src/components/markdown/markdoc-components/style/style.tsx b/src/components/markdown/markdoc-components/style/style.tsx
new file mode 100644
index 000000000..bd9b2c54f
--- /dev/null
+++ b/src/components/markdown/markdoc-components/style/style.tsx
@@ -0,0 +1,23 @@
+import { type StyleProps } from './style.types';
+
+// Validates CSS color values to prevent injection of unexpected values.
+// Accepts named colors, hex codes, and rgb/rgba/hsl/hsla functions.
+function isValidCssColor(value: string): boolean {
+ return /^(#[0-9a-fA-F]{3,8}|rgb\(.*\)|rgba\(.*\)|hsl\(.*\)|hsla\(.*\)|[a-zA-Z]+)$/.test(
+ value.trim()
+ );
+}
+
+export default function Style({ color, bg, children }: StyleProps) {
+ const cssStyle: React.CSSProperties = {};
+
+ if (color && isValidCssColor(color)) {
+ cssStyle.color = color;
+ }
+
+ if (bg && isValidCssColor(bg)) {
+ cssStyle.backgroundColor = bg;
+ }
+
+ return {children};
+}
diff --git a/src/components/markdown/markdoc-components/style/style.types.ts b/src/components/markdown/markdoc-components/style/style.types.ts
new file mode 100644
index 000000000..cdbacfe67
--- /dev/null
+++ b/src/components/markdown/markdoc-components/style/style.types.ts
@@ -0,0 +1,7 @@
+import { type ReactNode } from 'react';
+
+export type StyleProps = {
+ color?: string;
+ bg?: string;
+ children?: ReactNode;
+};
diff --git a/src/components/markdown/markdoc-schema.ts b/src/components/markdown/markdoc-schema.ts
index 4c7b76c3a..6417cf37f 100644
--- a/src/components/markdown/markdoc-schema.ts
+++ b/src/components/markdown/markdoc-schema.ts
@@ -8,6 +8,7 @@ import { inlineCodeMarkdocSchema } from './markdoc-components/inline-code/inline
import { listMarkdocSchema } from './markdoc-components/list/list.markdoc';
import { signalButtonMarkdocSchema } from './markdoc-components/signal-button/signal-button.markdoc';
import { startWorkflowButtonMarkdocSchema } from './markdoc-components/start-workflow-button/start-workflow-button.markdoc';
+import { styleMarkdocSchema } from './markdoc-components/style/style.markdoc';
export const markdocConfig: Config = {
tags: {
@@ -15,6 +16,7 @@ export const markdocConfig: Config = {
start: startWorkflowButtonMarkdocSchema,
image: imageSchema,
br: brSchema,
+ style: styleMarkdocSchema,
},
nodes: {
// Standard HTML nodes
diff --git a/src/views/docs/markdown/markdown-guide.ts b/src/views/docs/markdown/markdown-guide.ts
index 8d7b81e3d..b07c2d2bc 100644
--- a/src/views/docs/markdown/markdown-guide.ts
+++ b/src/views/docs/markdown/markdown-guide.ts
@@ -127,6 +127,55 @@ Image with 100px height:
Image with 100px width and 100px height:
{% image src="https://cadenceworkflow.io/assets/images/workflow-84ef76d93c7ff138714a0aa7c9b92841.png" alt="Image with 100px width and 100px height" width="100" height="100" /%}
+## Styled Text
+
+Use the \`{% style %}\` tag to apply custom text color or background color to any content.
+
+### Color
+
+Use the \`color\` attribute to set the text color:
+
+\`\`\`
+{% style color="red" %}red text{% /style %}
+{% style color="#0070f3" %}blue text{% /style %}
+\`\`\`
+
+{% style color="red" %}red text{% /style %}
+
+{% style color="green" %}green text{% /style %}
+
+### Background
+
+Use the \`bg\` attribute to set the background color:
+
+\`\`\`
+{% style bg="yellow" %}highlighted text{% /style %}
+\`\`\`
+
+{% style bg="yellow" %}highlighted text{% /style %}
+
+### Combined
+
+Use both \`color\` and \`bg\` together:
+
+\`\`\`
+{% style color="white" bg="blue" %}white text on blue background{% /style %}
+\`\`\`
+
+{% style color="white" bg="blue" %}white text on blue background{% /style %}
+
+### Nesting
+
+Tags can be nested for fine-grained control:
+
+\`\`\`
+{% style color="blue" %}
+ This is blue text, {% style color="red" %}this part is red{% /style %}, and back to blue.
+{% /style %}
+\`\`\`
+
+{% style color="blue" %}This is blue text, {% style color="red" %}this part is red{% /style %}, and back to blue.{% /style %}
+
`;
export default content;