Skip to content

Repository files navigation

@softwarity/interactive-code

A Web Component for displaying syntax-highlighted code with interactive bindings. Perfect for documentation, tutorials, and live demos.

Features

  • Syntax Highlighting: HTML, SCSS, TypeScript, Shell, and JSON
  • Interactive Bindings: Click to edit values directly in the code
  • Multiple Types: boolean, number, string, select, color, comment, attribute, button
  • Collapsible Sections: Fold non-interactive line ranges with ${fold} markers (copy/download stay complete)
  • Theme System: Built-in IntelliJ default + 4 external CSS themes (vscode, github, solarized, catppuccin) with light/dark variants
  • Mixed Content Highlighting: HTML with embedded <style> (SCSS) and <script> (TypeScript) blocks
  • Copy & Download: Optional copy and download buttons (valid JSON export)
  • Line Numbers: Optional gutter line numbers
  • Accessibility: ARIA attributes, keyboard navigation (Enter/Space, ArrowUp/Down)
  • Framework Agnostic: Works with Angular, React, Vue, or vanilla JS
  • Zero Dependencies: Pure Web Components

Demo

Live demo

Installation

npm

npm install @softwarity/interactive-code
import'@softwarity/interactive-code';

CDN

<scripttype="module" src="https://cdn.jsdelivr.net/npm/@softwarity/interactive-code"></script>

No build step required — the custom elements <interactive-code> and <code-binding> are registered automatically.

Usage

<interactive-codelanguage="scss"><textarea>
:root {
--width: ${width}px;
--enabled: ${enabled};
}
</textarea><code-bindingkey="width" type="number" value="72" min="48" max="120"></code-binding><code-bindingkey="enabled" type="boolean" value="true"></code-binding></interactive-code>

Escaping: write \${...} to display a literal ${...} in the code instead of interpreting it as a binding or fold marker.

Binding Types

TypeDescriptionInteraction
booleantrue/false valueClick to toggle
numberNumeric valueClick to edit, supports min/max/step
stringText valueClick to edit
selectOption from listClick to toggle (2 options), dropdown (3+), or carousel (carousel attribute)
colorColor valueClick to open color picker
commentLine/block toggleClick indicator to comment/uncomment (//, #, <!-- -->, /* */)
attributeHTML attribute toggleClick to toggle (strikethrough when disabled)
buttonAction token (value = label)Click to fire a change event (e.detail = value); no value edit, no re-render
readonlyDisplay onlyNo interaction

API

<interactive-code>

AttributeTypeDescription
language'html' | 'scss' | 'typescript' | 'shell' | 'json'Syntax highlighting language
color-scheme'light' | 'dark'Color scheme override (inherits from parent by default)
show-separatorsbooleanShow visual separators between textarea sections
show-copybooleanShow copy-to-clipboard button (top-right corner)
show-downloadbooleanShow download button (exports the full content as a file)
downloadstringFile name for the download button (defaults to snippet.<ext>)
show-line-numbersbooleanShow line numbers in the gutter
PropertyTypeDescription
codestring | nullSet code content programmatically

<code-binding>

AttributeTypeDescription
keystringBinding identifier (matches ${key} in template)
typeBindingTypeType of binding
valueanyInitial value
disabledbooleanDisable editing
minnumberMinimum value (for number type)
maxnumberMaximum value (for number type)
stepnumberStep increment (for number type)
optionsstringComma-separated options (for select type)
carouselbooleanCycle through options on click instead of dropdown (for select type)
EventDescription
changeFired when value changes (CustomEvent with detail = new value)

Inline handler: Use onchange attribute where e is the CustomEvent:

<code-bindingkey="checked" type="boolean" value="true"
onchange="document.getElementById('preview').checked = e.detail"></code-binding>

addEventListener / Framework binding:

// Vanilla JSbinding.addEventListener('change',(e)=>{preview.checked=e.detail;});// Angular: (change)="handler($event.detail)"// React: onChange={(e) => handler(e.detail)}// Vue: @change="handler($event.detail)"

Examples

Boolean Toggle

<interactive-codelanguage="html"><textarea><nav[autoCollapse]="${autoCollapse}">...</nav></textarea><code-bindingkey="autoCollapse" type="boolean" value="true"></code-binding></interactive-code>

Number with Constraints

<interactive-codelanguage="scss"><textarea>
:root {
--width: ${width}px;
}
</textarea><code-bindingkey="width" type="number" value="72" min="48" max="120" step="4"></code-binding></interactive-code>

Color Picker

<interactive-codelanguage="scss"><textarea>
:root {
--primary: ${primary};
}
</textarea><code-bindingkey="primary" type="color" value="#6750a4"></code-binding></interactive-code>

Comment Toggle (Line Enable/Disable)

Comment style adapts to language: // for TypeScript/SCSS, # for Shell, <!-- --> for HTML.

<interactive-codelanguage="scss"><textarea>
:root {
${enableWidth}--custom-width: 280px;
}
</textarea><code-bindingkey="enableWidth" type="comment" value="true"></code-binding></interactive-code>

Block Comment

Use ${key}...${/key} syntax for multi-line or inline block comments:

<interactive-codelanguage="typescript"><textarea>
const config = {
name: 'app',
${debug}debug: true,
verbose: true,${/debug}
};
</textarea><code-bindingkey="debug" type="comment" value="true"></code-binding></interactive-code>

Attribute Toggle

Toggle HTML attributes on/off. Supports attributes with or without values:

<interactive-codelanguage="html"><textarea><button${disabled}>Submit</button><input${placeholder}="Enter name" ${required}></textarea><code-bindingkey="disabled" type="attribute" value="true"></code-binding><code-bindingkey="placeholder" type="attribute" value="true"></code-binding><code-bindingkey="required" type="attribute" value="false"></code-binding></interactive-code>

Conditional Textareas

Show different code sections based on binding values. Multiple <textarea> elements are concatenated, and the condition attribute controls visibility:

<interactive-codelanguage="typescript" show-separators><textarea>const result = provider.complete(input, { groupBy: ${groupBy} });</textarea><textareacondition="!groupBy">// Use result.items for flat list
console.log(result.items);</textarea><textareacondition="groupBy">// Use result.groups for grouped display
console.log(result.groups);</textarea><code-bindingkey="groupBy" type="select" options="undefined,'continent'" value="undefined"></code-binding></interactive-code>
  • condition="key" - Show when binding value is truthy
  • condition="!key" - Show when binding value is falsy
  • condition="key=value" - Show when binding value equals a specific value
  • condition="!key=value" - Show when binding value does NOT equal a specific value
  • show-separators - Add visual separators between sections (customizable via --code-separator-color)

Collapsible Sections

Wrap a range of lines in ${fold}${/fold} markers to make it foldable (GitHub-diff style). Collapsed by default; use ${fold:open} to start expanded. The marker lines are removed from the output — folding is purely visual, and copy/download still export the full content. Works inside a <textarea> or via the code property, in any language.

<interactive-codelanguage="json" show-downloaddownload="config.json"><textarea>{
"name": "${name}",
${fold}
"_internal": {
"trace": true,
"buffer": 4096
},
${/fold}
"enabled": ${enabled}
}</textarea><code-bindingkey="name" type="string" value="app"></code-binding><code-bindingkey="enabled" type="boolean" value="true"></code-binding></interactive-code>

Action Button

A button binding is a clickable token that fires a change event on every click (no value to edit, no re-render), with e.detail set to its value — handy for a hub of actions.

<interactive-codelanguage="typescript"><textarea>await provider.${refresh}();</textarea><code-bindingkey="refresh" type="button" value="refresh()"
onchange="runAction(e.detail)"></code-binding></interactive-code>

Themes

The built-in default is IntelliJ (Light/Darcula). Four external CSS themes are available as separate stylesheets:

ThemeFileLightDark
VS Codethemes/vscode.cssLight+Dark+
GitHubthemes/github.cssLightDark
Solarizedthemes/solarized.cssLightDark
Catppuccinthemes/catppuccin.cssLatteMocha

Load a theme by adding a <link> stylesheet:

<linkrel="stylesheet" href="https://cdn.jsdelivr.net/npm/@softwarity/interactive-code/themes/vscode.css">

Use color-scheme to override light/dark mode per element:

<interactive-codelanguage="typescript" color-scheme="light">
...
</interactive-code>

CSS Customization

The component exposes CSS custom properties for styling. Themes and custom overrides use these variables.

UI Variables

PropertyDescription
--code-bgBackground color
--code-textForeground text color
--code-border-radiusBorder radius
--code-line-numberLine number color
--code-gutter-widthWidth of the left gutter control column
--code-separator-colorSeparator color between textarea sections
--code-focus-outlineFocus ring color
--code-input-bgInline input background
--code-input-borderInline input border
--code-hover-bgHover background
--code-copy-colorCopy button color
--code-copy-borderCopy button border
--code-copy-accentCopy success accent
--code-color-preview-borderColor swatch border
--code-interactive-highlightInteractive zone accent color
--code-interactive-colorInteractive zone text color
--code-interactive-bg-colorInteractive zone background
--code-interactive-border-colorInteractive zone border color
--code-comment-colorComment indicator color

Token Variables

All syntax token colors: --token-keyword, --token-string, --token-number, --token-comment, --token-tag, --token-attr-name, --token-attr-value, --token-punctuation, --token-property, --token-variable, --token-function, --token-decorator, --token-type, --token-class-name, --token-template-string, --token-value, --token-unknown, --token-binding-key

Interactive Zone Styling

Interactive controls expose part="interactive" for external CSS styling:

interactive-code::part(interactive) {
text-decoration: underline wavy var(--code-interactive-highlight);
}
interactive-code::part(interactive):hover {
background:var(--code-interactive-bg-color);
}

Built-in styles: wavy (default), dotted, dashed, highlight, outline, pill, hand-drawn, none.

interactive-code {
--code-bg:#282c34;
--code-border-radius:4px;
--code-separator-color:rgba(100,100,100,0.5);
}

Development

# Install dependencies
npm install
# Start dev server
npm run dev
# Build for production
npm run build

License

Apache-2.0 - Softwarity

About

Web Component for syntax-highlighted, click-to-edit code with collapsible sections, copy/download and themes — HTML, SCSS, TypeScript, Shell & JSON. Framework-agnostic, zero dependencies.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages