Language Switcher

Add a language picker when you need to switch between languages in a code block.

content.mdx
<CodeSwitcher>
```java !!
public class Main {
public static int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
}
```
```cpp !!
int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
```
```scala !!
object Main {
def factorial(n: Int): Int = {
if (n == 0) {
return 1
} else {
return n * factorial(n - 1)
}
}
}
```
```py !!
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n - 1)
```
```matlab !!
function result = factorial(n)
if n == 0
result = 1;
else
result = n * factorial(n - 1);
end
end
```
```js !!
function factorial(n) {
if (n === 0) {
return 1
} else {
return n * factorial(n - 1)
}
}
```
```kotlin !!
fun factorial(n: Int): Int {
return if (n == 0) {
1
} else {
n * factorial(n - 1)
}
}
```
```go !!
func factorial(n int) int {
if n == 0 {
return 1
} else {
return n * factorial(n - 1)
}
}
```
```swift !!
func factorial(n: Int) -> Int {
if n == 0 {
return 1
} else {
return n * factorial(n: n - 1)
}
}
```
```rust !!
fn factorial(n: i32) -> i32 {
if n == 0 {
return 1;
} else {
return n * factorial(n - 1);
}
}
```
```fsharp !!
let rec factorial n =
if n = 0 then
1
else
n * factorial (n - 1)
```
</CodeSwitcher>
public class Main {
public static int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
}

Pick a different language from the dropdown to see the code block change.

Implementation

We use the Select components from shadcn/ui:

npx shadcn-ui@latest add select

Since our component will have state we need a client component:

code.tsx
"use client"
import { HighlightedCode, Pre, highlight } from "codehike/code"
import { useState } from "react"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
export function Code({ highlighted }: { highlighted: HighlightedCode[] }) {
const [selectedLang, setSelectedLang] = useState(highlighted[0].lang)
const selectedCode = highlighted.find((code) => code.lang === selectedLang)!
return (
<div className="">
<Pre code={selectedCode} className="" />
<div className="">
<Select value={selectedLang} onValueChange={setSelectedLang}>
<SelectTrigger className="">
<SelectValue />
</SelectTrigger>
<SelectContent position="item-aligned">
{highlighted.map(({ lang }, index) => (
<SelectItem key={index} value={lang}>
{lang}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
)
}

If you are using React Server Components, we also need a component to highlight the codeblocks:

language-switcher.tsx
import { RawCode, highlight } from "codehike/code"
import { Code } from "./code"
export async function CodeSwitcher(props: { code: RawCode[] }) {
const highlighted = await Promise.all(
props.code.map((codeblock) => highlight(codeblock, "github-dark")),
)
return <Code highlighted={highlighted} />
}

If you want to animate the transitions, you can use the token transitions handler.

If you need to persist and/or sync the selected language across multiple code blocks, you can replace the useState with a useLocalStorage hook, for example using @uidotdev/usehooks or your own implementation.