A Web Component that inputs markdown content and renders it as HTML formatted with Elements styles.
<nve-markdown>
<template>
# Default
This is a default markdown component in its initial state.
- List item 1
- List item 2
- List item 3
</template>
</nve-markdown>
# Default
This is a default markdown component in its initial state.
- List item 1
- List item 2
- List item 3
The nve-markdown component renders markdown content with Elements styling. It supports both programmatic content via the source property and template-based content via slots.
<nve-markdown>
<template>
# Default
This is a default markdown component in its initial state.
- List item 1
- List item 2
- List item 3
</template>
</nve-markdown>
Basic Usage
Markdown from Source Property
Basic inline source attribute usage with headings, lists, bold/italic text, and code blocks
<nve-markdown
source="# This is a heading
- list item 1
- list item 2
- list item 3
**Bold text** and *italic text* with a [link](https://example.com).
```javascript
const code = 'example';
```"
></nve-markdown>
Markdown from Template
Markdown content defined inside a template element with nested lists and inline formatting
<nve-markdown>
<template>
# Markdown from Template
This content is **markdown** inside a template element.
### Unordered Lists
- First level item one
- First level item two
- Second level item one
- Second level item two
- Third level item
- First level item three
This paragraph tests that lists properly end with margin-bottom.
### Ordered Lists
1. Step one: Initialize the project
2. Step two: Install dependencies
1. Run \`npm install\`
2. Verify installation
3. Step three: Start development server
**Bold text** and *italic text* with a [link](https://example.com).
</template>
</nve-markdown>
# Markdown from Template
This content is **markdown** inside a template element.
### Unordered Lists
- First level item one
- First level item two
- Second level item one
- Second level item two
- Third level item
- First level item three
This paragraph tests that lists properly end with margin-bottom.
### Ordered Lists
1. Step one: Initialize the project
2. Step two: Install dependencies
1. Run \`npm install\`
2. Verify installation
3. Step three: Start development server
**Bold text** and *italic text* with a [link](https://example.com).
Advanced Examples
Combined Markdown and HTML
Mixing raw HTML elements with markdown syntax within a template
<nve-markdown>
<template>
# Markdown from Template
This content is **markdown** inside a template element.
- Template list item 1
- Template list item 2
- Template list item 3
## HTML Mixed with Markdown
This content has <strong>HTML</strong> mixed with markdown.
<ul>
<li>HTML list item 1</li>
<li>HTML list item 2</li>
<li>HTML list item 3</li>
</ul>
</template>
</nve-markdown>
# Markdown from Template
This content is **markdown** inside a template element.
- Template list item 1
- Template list item 2
- Template list item 3
## HTML Mixed with Markdown
This content has HTML mixed with markdown.
HTML list item 1
HTML list item 2
HTML list item 3
Interactive Examples
Dynamic Content Updates
Interactive demo with buttons to switch between different source content dynamically
<div>
<h3>Dynamic Source Demo</h3>
<p>This demonstrates switching between two HTML contents via the source property.</p>
<nve-markdown id="dynamic-source-markdown" type="html"></nve-markdown>
<div style="margin-top: 1rem">
<button id="switch-to-source-1">Switch to Source 1</button>
<button id="switch-to-source-2">Switch to Source 2</button>
</div>
<script type="module">
const nveMarkdown = document.getElementById("dynamic-source-markdown");
const source1Btn = document.getElementById("switch-to-source-1");
const source2Btn = document.getElementById("switch-to-source-2");
source1Btn.addEventListener("click", () => {
nveMarkdown.source = "# Source 1";
});
source2Btn.addEventListener("click", () => {
nveMarkdown.source = "# Source 2";
});
</script>
</div>
Dynamic Source Demo
This demonstrates switching between two HTML contents via the source property.
Streaming Content
Progressive streaming demo simulating AI assistant responses with block-by-block content rendering
<div>
<nve-markdown id="programmatic-markdown"></nve-markdown>
<script type="module">
const element = document.getElementById("programmatic-markdown");
// Complete markdown content to stream
const fullContent = `# AI Assistant Response
\n
Thank you for your question about **markdown streaming**. Here's how it works:
\n
## Key Features
\n
- **Real-time parsing** as content arrives
- *Progressive* rendering updates
- Smooth user experience
- Dynamic content handling
\n
### Implementation Example
\n
\`\`\`javascript
const element = document.getElementById('markdown');
element.source = streamingContent;
\`\`\`
\n
## How It Works
\n
The markdown component processes content incrementally, allowing for:
\n
1. **Streaming responses** from AI systems
2. **Live updates** without page refreshes
3. **Progressive enhancement** of content
\n
### Use Cases
\n
- Chat applications with AI assistants
- Real-time documentation generation
- Interactive tutorials and guides
- Live content editing interfaces
\n
## Technical Details
\n
The component uses a reactive approach:
\n
- Watches for \`source\` property changes
- Re-parses markdown on each update
- Maintains smooth rendering performance
- Handles both markdown and HTML content types
\n
### Performance Benefits
\n
- **Lazy loading** of markdown parser
- **Efficient re-rendering** with Lit's update cycle
- **Memory optimization** through proper cleanup
\n
> Perfect for AI assistants and real-time documentation!`;
// Split content into blocks/paragraphs for progressive display
const blocks = fullContent.split("\n");
let currentBlockIndex = 0;
function streamContent() {
if (currentBlockIndex < blocks.length) {
// Add 1 block at a time to preserve markdown structure
currentBlockIndex++;
const currentContent = blocks.slice(0, currentBlockIndex).join(" \n");
element.source = currentContent;
setTimeout(streamContent, 300);
}
}
// Start streaming after a brief delay
setTimeout(streamContent, 1000);
</script>
</div>
Features
Markdown Processing: The markdown parser processes all content
HTML Support: The renderer preserves and renders HTML tags within markdown
Two Input Methods:
source property for programmatic content
<template> slot for declarative content
Elements Styling: Comprehensive CSS styling that matches the Elements design system
Lazy Loading: Markdown parser is only loaded when needed for optimal performance
Release Status
All elements and features go through 3 phases of stability, pre-release, beta and stable.
pre-release
Docs PreviewAPI DocumentationFully Themeable
beta
Robust unit test coveragesPassed API ReviewPassed Designer VQA ReviewIncluded in library package
stable
No known outstanding AA WCAG issuesNo known outstanding performance issuesAdapts to different screen/container sizesNo breaking API changes for at least 90 days