Skip to content

Add tab interface, update deps #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# v0.1.1 (Tue Apr 09 2024)

#### 🚀 Enhancement

- Update dependancies
- Add slides with tabs & auto-forwarding, inspired by [Antifu's blog post](https://antfu.me/posts/shiki-magic-move)

#### 🐛 Bug Fix

- `@code-hike/mdx`
- `from` annotation with line range [#376](https://github.com/code-hike/codehike/pull/376) ([@pomber](https://github.com/pomber))
- Fix dimensions when code starts hidden [#373](https://github.com/code-hike/codehike/pull/373) ([@pomber](https://github.com/pomber))
- Merge main [#365](https://github.com/code-hike/codehike/pull/365) ([@pomber](https://github.com/pomber))

#### Authors: 1

- Tom Byrer ([@tomByrer](https://github.com/tomByrer))

---

# v0.1.0 (Fri Feb 23 2024)

#### Old History

#### Authors: 1

- Rodrigo Pombo ([@pomber](https://github.com/pomber))

---
1 change: 1 addition & 0 deletions app/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ Examples:

- [/app/scrollycoding](/scrollycoding)
- [/app/slideshow](/slideshow)
- [/app/tabs](/tabs)

For more information, check out [Code Hike v1 docs](https://v1.codehike.org/docs).
175 changes: 175 additions & 0 deletions app/tabs/content.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
## !!steps A Game of Thrones

A Game of Thrones is the first book in the A Song of Ice and Fire series by George R.R. Martin. Set in a world where seasons last for years, it introduces a complex plot and a wide cast of characters, ranging from noble families vying for the Iron Throne to the supernatural threats in the North.

```js ! game.js
const houses = [
"Stark",
"Lannister",
"Baratheon",
"Targaryen",
]

const winner =
houses[
Math.floor(
Math.random() * houses.length,
)
]

console.log(`Iron Throne: ${winner}`)
```

## !!steps A Clash of Kings

A Clash of Kings, the second book in the series, continues the epic saga. The Seven Kingdoms are plunged into war, with kings rising and falling. Meanwhile, Daenerys Targaryen seeks to return to Westeros with her growing dragons.

```js ! clash.js
const houses = [
"Stark",
"Lannister",
"Baratheon",
"Targaryen",
]

const clash = () => {
const winner =
houses[
Math.floor(
Math.random() * houses.length,
)
]
return `${winner} wins the battle!`
}

console.log(clash())
```

## !!steps A Storm of Swords

The third book, A Storm of Swords, is known for its intense and shocking developments. Battles rage on, alliances shift, and characters face unexpected challenges and betrayals, making it one of the most thrilling books in the series.

```js ! storm.js
const houses = [
"Stark",
"Lannister",
"Baratheon",
]

const reveal = () => {
const traitor =
houses[
Math.floor(
Math.random() * houses.length,
)
]
return `${traitor} betrays the alliance!`
}

console.log(reveal())
```

## !!steps A Feast for Crows

A Feast for Crows, the fourth book, explores the aftermath of the wars, with a focus on the characters in the southern regions of Westeros. It delves into the politics and power struggles in a kingdom weary of battle.

```js ! feast.js
const houses = [
"Martell",
"Lannister",
"Baratheon",
"Tyrell",
]

const intrigue = () => {
const ally1 =
houses[
Math.floor(
Math.random() * houses.length,
)
]
const ally2 =
houses[
Math.floor(
Math.random() * houses.length,
)
]
return `${ally1} and ${ally2} form an alliance!`
}

console.log(intrigue())
```

## !!steps A Dance with Dragons

A Dance with Dragons, the fifth book, runs concurrently with A Feast for Crows and focuses on the characters in the North and across the Narrow Sea. The story advances with dragons, the Night’s Watch, and the lingering threat of winter.

```js ! dance.js
const houses = [
"Stark",
"Lannister",
"Baratheon",
"Targaryen",
]

const dragons = () => {
const dragon =
houses[
Math.floor(
Math.random() * houses.length,
)
]
return `${dragon} has a dragon!`
}

console.log(dragons())
```

## !!steps The Winds of Winter

The Winds of Winter, the anticipated sixth book, is expected to continue the intricate storylines and bring new twists and turns to the world of Westeros. Fans eagerly await its release.

```js ! winds.js
const houses = [
"Stark",
"Lannister",
"Baratheon",
"Targaryen",
"Martell",
"Tyrell",
"Greyjoy",
]

const winterIsComing = () => {
const isComing = Math.random() > 0.99
if (isComing) {
return "Winter is coming!"
} else {
return "Winter is not coming."
}
}

console.log(winterIsComing())
```

## !!steps A Dream of Spring

A Dream of Spring is the proposed final book in the series, anticipated to conclude the epic saga. It remains one of the most awaited books in modern fantasy literature.

```js ! dream.js
const houses = [
"Stark",
"Lannister",
"Baratheon",
"Targaryen",
"Martell",
"Tyrell",
"Greyjoy",
]

const keepDreaming = () => {
return "Not gonna happen..."
}

console.log(keepDreaming())
```
39 changes: 39 additions & 0 deletions app/tabs/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// @ts-ignore
import { getBlocks } from "./content.md"
import { CodeContent, CodeBlock } from "codehike"
import { Slides, Tabs } from "./slides"

type Blocks = {
steps: StepBlock[]
}

type StepBlock = {
query: string
code: CodeBlock
children: React.ReactNode[]
}

export default function Page() {
const { steps } = getBlocks() as Blocks
const fileNames = steps.map((step: any) => (
step.code.meta
))
const slides = steps.map((step: any) => (
<div>
<div className="h-44 px-6">{step.children}</div>
<Tabs tabNames={fileNames} />
<Code codeblock={step.code} />
</div>
))
return <Slides slides={slides} />
}

function Code({ codeblock }: { codeblock: CodeBlock }) {
return (
<CodeContent
codeblock={codeblock}
config={{ theme: "github-dark" }}
className="min-h-[44rem] !bg-zinc-900 m-0 rounded-none"
/>
)
}
55 changes: 55 additions & 0 deletions app/tabs/slides.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use client"
import * as React from "react"

const StepIndexContext = React.createContext<
[number, React.Dispatch<React.SetStateAction<number>>]
>([0, () => {}])

export function Slides({ slides }: { slides: React.ReactNode[] }) {
const [selectedIndex, setSelectedIndex] = React.useState(0)

return (
<StepIndexContext.Provider value={[selectedIndex, setSelectedIndex]}>
{slides[selectedIndex]}
</StepIndexContext.Provider>
)
}

export function Tabs({ tabNames }: { tabNames: String[] }) {
const tabLength: number = tabNames.length;
const [selectedIndex, setSelectedIndex] = React.useContext(StepIndexContext)
const [isActive, setIsActive] = React.useState(true);
function selectTab(i) {
setSelectedIndex(i);
setIsActive(false);
}

React.useEffect(() => {
let interval:any = null;
if (isActive) {
interval = setInterval(() => {
setSelectedIndex(selectedIndex =>
(selectedIndex === tabLength-1)
? 0
: selectedIndex + 1)
}, 2618);
} else if (!isActive) {
clearInterval(interval);
}
return () => clearInterval(interval);
}, [isActive, selectedIndex]);

return (
<nav className="flex space-x-2" aria-label="Tabs" role="tablist">
{[...Array(tabLength)].map((_, i) => (
<button
key={i}
className={`-mb-px py-3 px-4 flex-nowrap whitespace-nowrap items-center gap-2 text-md font-medium text-center rounded-t-lg hover:text-gray-200 disabled:opacity-50 disabled:pointer-events-none active cursor-pointer ${
selectedIndex === i ? "text-white bg-zinc-900" : "text-gray-400 bg-zinc-800"
}`}
onClick={() =>selectTab(i)}
>{tabNames[i]}</button>
))}
</nav>
)
}
Loading