---
title: "Interactive Features Showcase"
description: "All the interactive components, code features, and eye candy available in krowdev articles."
kind: snippet
maturity: evergreen
confidence: high
origin: ai-assisted
tags: [astro, reference]
created: 2026-03-17
prerequisites: []
related: [astro-mental-model]
url: https://krowdev.com/snippet/interactive-features-showcase/
---


This page demonstrates every interactive feature available when writing krowdev content. Use it as a reference when creating new articles. If you're new to how Astro renders these components, start with [the mental model](/guide/astro-mental-model/) — everything here is compiled to static HTML at build time.

## Code Blocks

Every fenced code block automatically gets a **language badge**, a **copy button** (hover to reveal), and proper Catppuccin syntax highlighting.

```python
def fibonacci(n):
    """Generate the first n Fibonacci numbers."""
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

for num in fibonacci(10):
    print(num)
```

```bash
# Install dependencies and build
npm install
npm run build
npm run preview
```

```sql
SELECT users.name, COUNT(posts.id) AS post_count
FROM users
LEFT JOIN posts ON users.id = posts.author_id
GROUP BY users.name
HAVING post_count > 5
ORDER BY post_count DESC;
```

## Line Highlighting

Use `mark={lines}` in the code fence meta to highlight specific lines:

```javascript mark={2-3}
function greet(name) {
  const greeting = `Hello, ${name}!`;
  console.log(greeting);
  return greeting;
}
```

## Diff Notation

Use `ins={lines}` and `del={lines}` to show additions and removals:

```javascript del={5} ins={6-7}
function createUser(name, email) {
  return {
    name,
    email,
    role: 'viewer',
    role: 'editor',
    createdAt: Date.now(),
  };
}
```

## Editor and Terminal Frames

Code blocks auto-detect their frame type. Use `title="filename"` for editor tabs:

```js title="src/utils/helper.js"
export function greet(name) {
  return `Hello, ${name}!`;
}
```

Shell languages get terminal frames automatically:

```bash title="Installing dependencies"
npm install astro-expressive-code
```

## Collapsible Sections

Use `collapse={lines}` to collapse less-important lines:

```typescript collapse={1-4}
interface BlogPost {
  title: string;
  date: Date;
  tags: string[];
  content: string;
  draft: boolean;
}

function publishPost(post: BlogPost): void {
  if (post.draft) {
    throw new Error('Cannot publish a draft');
  }
  // ... publish logic
}
```

## Callout Boxes

Eight types, each with a Catppuccin accent color:

:::note
**Notes** provide additional context. They use the blue accent.
:::

:::tip
**Tips** suggest best practices. They use the green accent.
:::

:::info
**Info** blocks share background details. They use the sapphire accent.
:::

:::warning
**Warnings** flag common mistakes. They use the yellow accent.
:::

:::danger
**Danger** blocks mark breaking or destructive actions. They use the red accent.
:::

:::caution
**Caution** blocks advise careful consideration. They use the peach accent.
:::

<strong>Analogies</strong> map to familiar concepts. Think of Astro components like Python functions — they take arguments (props) and return a result (HTML).

<strong>Key insights</strong> highlight the most important takeaway. This is what you'd underline in a textbook.

## Challenge Blocks

Interactive exercises that expand on click:

**Challenge: Build a greeting component**

Create a `Greeting.astro` component that:
1. Accepts a `name` prop (string)
2. Renders `<h2>Hello, {name}!</h2>`
3. Uses a scoped style to color the text with `var(--accent)`

```astro
---
interface Props {
  name: string;
}
const { name } = Astro.props;
---

<h2>Hello, {name}!</h2>

<style>
  h2 { color: var(--accent); }
</style>
```

**What happens if you forget the Props interface?**

TypeScript won't catch incorrect prop usage at build time. You'll get `undefined` instead of a type error. Always define the interface — it's your safety net.

## Code View Tabs

The Source / Compiled / Rendered pattern for showing how Astro transforms code:

<p class="cv-label">src/components/Badge.astro</p>
<nav class="cv-tabs" role="tablist">
<button class="cv-tab active" role="tab" data-tab="source" aria-selected="true">Source</button>
<button class="cv-tab" role="tab" data-tab="compiled" aria-selected="false">Compiled</button>
<button class="cv-tab" role="tab" data-tab="rendered" aria-selected="false">Rendered</button>
</nav>
<div class="cv-panel active" data-panel="source" role="tabpanel">

```astro
---
interface Props { label: string; color?: string; }
const { label, color = 'var(--accent)' } = Astro.props;
---

<span class="badge" style={`--badge-color: ${color}`}>
  {label}
</span>

<style>
  .badge {
    display: inline-flex;
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--badge-color);
    border: 1px solid var(--badge-color);
    background: color-mix(in srgb, var(--badge-color) 10%, transparent);
  }
</style>
```

<div class="cv-panel" data-panel="compiled" role="tabpanel">

```html
<span class="badge" style="--badge-color: var(--accent)"
      data-astro-cid-x7q2k1>
  beginner
</span>

<style>
  .badge[data-astro-cid-x7q2k1] {
    display: inline-flex;
    padding: 0.15rem 0.6rem;
    /* ... scoped to this component only */
  }
</style>
```

<div class="cv-panel" data-panel="rendered" role="tabpanel">

The compiled output shows Astro's scoped CSS in action. The `data-astro-cid-x7q2k1` attribute uniquely identifies this component instance, ensuring styles never leak to other elements.


