Skip to content

Commit 92d4310

Browse files
committed
Tailwind example
1 parent 56c7cd2 commit 92d4310

File tree

8 files changed

+171
-0
lines changed

8 files changed

+171
-0
lines changed

examples/tailwind/package.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "@top-bun/preact-example",
3+
"version": "0.0.0",
4+
"type": "module",
5+
"scripts": {
6+
"start": "npm run watch",
7+
"build": "npm run clean && top-bun",
8+
"clean": "rm -rf public && mkdir -p public",
9+
"watch": "npm run clean && tb --watch"
10+
},
11+
"author": "Bret Comnes <[email protected]> (https://bret.io/)",
12+
"license": "MIT",
13+
"dependencies": {},
14+
"devDependencies": {
15+
"npm-run-all2": "^6.0.0",
16+
"@preact/signals": "^2.0.0",
17+
"htm": "^3.1.1",
18+
"preact": "^10.24.0",
19+
"preact-render-to-string": "^6.5.11",
20+
"top-bun": "../../.",
21+
"esbuild-plugin-tailwindcss": "2.0.1"
22+
}
23+
}

examples/tailwind/src/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Preact example
2+
3+
This is a preact example WITH TAILWIND!
4+
5+
[Isomorphic Component Rendering](./isomorphic/)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import tailwindPlugin from 'esbuild-plugin-tailwindcss'
2+
3+
export default async function esbuildSettingsOverride (esbuildSettings) {
4+
esbuildSettings.plugins = [
5+
tailwindPlugin(),
6+
]
7+
return esbuildSettings
8+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log('Global client')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
@import "tailwindcss";
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { html, Component } from 'htm/preact'
2+
import { render } from 'preact'
3+
import { useCallback } from 'preact/hooks'
4+
import { useSignal, useComputed } from '@preact/signals'
5+
6+
const Header = ({ name }) => html`
7+
<h1 class="text-3xl font-bold text-gray-800 mb-4">${name} List</h1>
8+
`
9+
10+
const Footer = props => {
11+
const count = useSignal(0)
12+
const double = useComputed(() => count.value * 2)
13+
14+
const handleClick = useCallback(() => {
15+
count.value++
16+
}, [count])
17+
18+
return html`
19+
<footer class="mt-8 p-4 bg-gray-100 rounded shadow flex flex-col gap-2" ...${props}>
20+
<div class="text-gray-600">Count: ${count}</div>
21+
<div class="text-gray-600">Double: ${double}</div>
22+
<div>${props.children}</div>
23+
<button
24+
onClick=${handleClick}
25+
class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 transition"
26+
>
27+
Click
28+
</button>
29+
</footer>
30+
`
31+
}
32+
33+
class App extends Component {
34+
addTodo () {
35+
const { todos = [] } = this.state
36+
this.setState({ todos: todos.concat(`Item ${todos.length}`) })
37+
}
38+
39+
render ({ page }, { todos = [] }) {
40+
return html`
41+
<div class="app max-w-xl mx-auto p-6 bg-white rounded shadow">
42+
<${Header} name="ToDo's (${page})" />
43+
<ul class="space-y-2 mb-4">
44+
${todos.map(todo => html`
45+
<li key=${todo} class="p-2 bg-gray-50 rounded shadow">${todo}</li>
46+
`)}
47+
</ul>
48+
<button
49+
onClick=${() => this.addTodo()}
50+
class="bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700 transition"
51+
>
52+
Add Todo
53+
</button>
54+
<${Footer}>footer content here<//>
55+
</div>
56+
`
57+
}
58+
}
59+
60+
export const page = () => html`
61+
<div class="space-y-6">
62+
<${App} page="Isomorphic"/>
63+
<${Footer}>footer content here<//>
64+
<${Footer}>footer content here<//>
65+
</div>
66+
`
67+
68+
if (typeof window !== 'undefined') {
69+
const renderTarget = document.querySelector('.app-main')
70+
render(page(), renderTarget)
71+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { page } from './client.js'
2+
3+
export default () => {
4+
return page()
5+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// @ts-ignore
2+
import { html } from 'htm/preact'
3+
import { render } from 'preact-render-to-string'
4+
5+
/**
6+
* @template T extends object
7+
* @typedef {import('../build-pages/resolve-layout.js').LayoutFunction<T>} LayoutFunction
8+
*/
9+
10+
/**
11+
* Global layout with Tailwind container styles
12+
*
13+
* @type {LayoutFunction<{
14+
* title: string,
15+
* siteName: string,
16+
* defaultStyle: boolean,
17+
* basePath: string
18+
* }>}
19+
*/
20+
export default function defaultRootLayout ({
21+
vars: {
22+
title,
23+
siteName = 'TopBun',
24+
basePath,
25+
},
26+
scripts,
27+
styles,
28+
children,
29+
}) {
30+
return /* html */`
31+
<!DOCTYPE html>
32+
<html class="h-full">
33+
${render(html`
34+
<head>
35+
<meta charset="utf-8" />
36+
<title>${title ? `${title}` : ''}${title && siteName ? ' | ' : ''}${siteName}</title>
37+
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
38+
${scripts
39+
? scripts.map(script => html`<script type='module' src="${script.startsWith('/') ? `${basePath ?? ''}${script}` : script}" />`)
40+
: null}
41+
${styles
42+
? styles.map(style => html`<link rel="stylesheet" href="${style.startsWith('/') ? `${basePath ?? ''}${style}` : style}" />`)
43+
: null}
44+
</head>
45+
`)}
46+
${render(html`
47+
<body class="min-h-screen bg-gray-50 text-gray-900 safe-area-inset">
48+
${typeof children === 'string'
49+
? html`<main class="container mx-auto p-4 mine-layout app-main" dangerouslySetInnerHTML="${{ __html: children }}" />`
50+
: html`<main class="container mx-auto p-4 mine-layout app-main">${children}</main>`
51+
}
52+
</body>
53+
`)}
54+
</html>
55+
`
56+
}

0 commit comments

Comments
 (0)