Skip to content

Commit a9c8951

Browse files
committed
Improve basic, css-modules and default-layout examples
1 parent ab49a83 commit a9c8951

File tree

6 files changed

+149
-33
lines changed

6 files changed

+149
-33
lines changed

examples/basic/src/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ md-files: support yaml frontmatter!
66
# Basic DOMStack Example
77

88
This example demonstrates a complete basic website built with DOMStack, showcasing the core features without advanced customization.
9+
Please inspect the website, the web inspector (source and network tab), the src code in the example folder as well as the ouput files in the public folder to get an idea of how everything works.
910

1011
## Features Demonstrated
1112

examples/basic/src/md-page/README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@ Below is an example of an image asset referenced from the page's assets folder:
3838

3939
![Matrix Animation](./assets/matrix.gif)
4040

41+
The static asset can live in the same directory as the page, or in any other directory.
42+
4143
## Navigation
4244

4345
- [Back to Home](../)
4446
- [View Subpage](./sub-page/README.md)
45-
46-
47-

examples/css-modules/src/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
This example demonstrates how to use CSS modules with DOMStack, providing component-scoped styling that avoids global namespace conflicts.
44

5+
CSS module support is provided by esbuild, so for more information on what is and isn't supported read the esbuild CSS module docs:
6+
7+
- [esbuild.github.io/content-types/#local-css](https://esbuild.github.io/content-types/#local-css)
8+
- [github.com/css-modules/css-modules](https://github.com/css-modules/css-modules)
9+
10+
CSS modules are NOT supported in Node.js natively, so you need to import a loader to support them, or only reference them in client bundles.
11+
512
## What Are CSS Modules?
613

714
CSS modules are CSS files where class names and animation names are scoped locally by default. This prevents style leakage and naming collisions in your application.

examples/css-modules/src/modules/client.js

Lines changed: 120 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,54 +2,145 @@ import { html, Component } from 'htm/preact'
22
import { render } from 'preact'
33
import { useCallback } from 'preact/hooks'
44
import { useSignal, useComputed } from '@preact/signals'
5-
import { outerShell } from './app.module.css'
5+
import { outerShell, button, dangerButton, card } from './app.module.css'
66

7-
const Header = ({ name }) => html`<h1>${name} List</h1>`
7+
// Header component with CSS module class
8+
const Header = ({ title }) => html`
9+
<header class=${outerShell}>
10+
<h1>${title}</h1>
11+
<p>This header uses the <code>outerShell</code> CSS module class</p>
12+
</header>
13+
`
814

9-
const Footer = props => {
15+
// Counter component demonstrating Preact Signals
16+
const Counter = () => {
1017
const count = useSignal(0)
11-
const double = useComputed(() => count.value * 2)
18+
const doubled = useComputed(() => count.value * 2)
1219

13-
const handleClick = useCallback(() => {
20+
const handleIncrement = useCallback(() => {
1421
count.value++
1522
}, [count])
1623

17-
return html`<footer ...${props}>
18-
${count}
19-
${double}
20-
${props.children}
21-
<button onClick=${handleClick}>Click</button>
22-
</footer>`
24+
const handleReset = useCallback(() => {
25+
count.value = 0
26+
}, [count])
27+
28+
return html`
29+
<div class=${card}>
30+
<h3 class="title">Counter with Signals</h3>
31+
<div class="content">
32+
<p>Count: <strong>${count}</strong></p>
33+
<p>Doubled: <strong>${doubled}</strong></p>
34+
<button class=${button} onClick=${handleIncrement}>Increment</button>
35+
<button class=${dangerButton} onClick=${handleReset}>Reset</button>
36+
</div>
37+
</div>
38+
`
2339
}
2440

25-
class App extends Component {
41+
// TodoList component using class component style
42+
class TodoList extends Component {
43+
constructor (props) {
44+
super(props)
45+
this.state = { todos: [], newTodo: '' }
46+
}
47+
2648
addTodo () {
27-
const { todos = [] } = this.state
28-
this.setState({ todos: todos.concat(`Item ${todos.length}`) })
49+
const { todos, newTodo } = this.state
50+
if (newTodo.trim()) {
51+
this.setState({
52+
todos: [...todos, newTodo],
53+
newTodo: ''
54+
})
55+
}
56+
}
57+
58+
updateNewTodo (e) {
59+
this.setState({ newTodo: e.target.value })
60+
}
61+
62+
removeTodo (index) {
63+
const { todos } = this.state
64+
this.setState({
65+
todos: todos.filter((_, i) => i !== index)
66+
})
2967
}
3068

31-
render ({ page }, { todos = [] }) {
69+
render () {
70+
const { todos, newTodo } = this.state
71+
3272
return html`
33-
<div class="${`app ${outerShell}`}">
34-
<${Header} name="ToDo's (${page})" />
35-
<ul>
36-
${todos.map(todo => html`
37-
<li key=${todo}>${todo}</li>
38-
`)}
39-
</ul>
40-
<button onClick=${() => this.addTodo()}>Add Todo</button>
41-
<${Footer}>footer content here<//>
73+
<div class=${card}>
74+
<h3 class="title">Todo List</h3>
75+
<div class="content">
76+
<div style="margin-bottom: 1rem;">
77+
<input
78+
type="text"
79+
value=${newTodo}
80+
onInput=${(e) => this.updateNewTodo(e)}
81+
placeholder="Add a new todo"
82+
/>
83+
<button
84+
class=${button}
85+
onClick=${() => this.addTodo()}
86+
>
87+
Add
88+
</button>
4289
</div>
43-
`
90+
91+
${todos.length === 0
92+
? html`<p>No todos yet. Add some!</p>`
93+
: html`
94+
<ul style="padding-left: 1.5rem;">
95+
${todos.map((todo, index) => html`
96+
<li key=${index}>
97+
${todo}
98+
<button
99+
class=${dangerButton}
100+
style="margin-left: 0.5rem; padding: 2px 6px;"
101+
onClick=${() => this.removeTodo(index)}
102+
>
103+
×
104+
</button>
105+
</li>
106+
`)}
107+
</ul>
108+
`
109+
}
110+
</div>
111+
</div>
112+
`
44113
}
45114
}
46115

47-
export const page = () => html`
48-
<${App} page="Isomorphic"/>
49-
<${Footer}>footer content here<//>
50-
<${Footer}>footer content here<//>
116+
// Footer component
117+
const Footer = () => html`
118+
<footer style="margin-top: 2rem; padding-top: 1rem; border-top: 1px solid #eee; text-align: center;">
119+
<p>CSS Modules Demo with Preact</p>
120+
<p><small>This demo shows how to use CSS Modules with Preact components</small></p>
121+
</footer>
122+
`
123+
124+
// Main App component
125+
const App = ({ title }) => {
126+
return html`
127+
<div style="max-width: 800px; margin: 0 auto; padding: 1rem;">
128+
<${Header} title=${title} />
129+
130+
<div style="display: grid; grid-template-columns: 1fr; gap: 1rem; margin: 1rem 0;">
131+
<${Counter} />
132+
<${TodoList} />
133+
</div>
134+
135+
<${Footer} />
136+
</div>
51137
`
138+
}
139+
140+
// Page component for export
141+
export const page = () => html`<${App} title="CSS Modules Demo" />`
52142

143+
// Client-side rendering
53144
if (typeof window !== 'undefined') {
54145
const renderTarget = document.querySelector('.app-main')
55146
render(page(), renderTarget)

examples/css-modules/src/modules/page.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { html } from 'htm/preact'
2-
// import styles from './app.module.css'
2+
// import styles from './app.module.css' THIS DOESN'T WORK IN NODE.JS
33

44
export default () => {
55
return html`

examples/default-layout/src/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,21 @@ While the default layout is convenient for getting started, you should create cu
8181
- Special metadata or analytics integrations
8282

8383
For custom layouts, check the other examples in the DOMStack repository, particularly the `basic` example.
84+
85+
## Ejecting from the Default Layout
86+
87+
If you want to customize the default layout, you can use the `--eject` flag to extract the built-in layout into your project:
88+
89+
```bash
90+
npx domstack --eject
91+
```
92+
93+
This command will:
94+
95+
1. Create a `root.layout.js` file in your project's `src` directory
96+
2. Copy the contents of the default layout into this new file
97+
3. Allow you to modify the layout to suit your specific needs
98+
99+
After ejecting, you can edit the generated `root.layout.js` file like any other custom layout. This gives you a solid foundation to build upon rather than starting from scratch.
100+
101+
> **Note:** Once you eject, DOMStack will use your custom layout file instead of the built-in default. If you want to revert to the original default layout, you'll need to delete your custom `root.layout.js` file.

0 commit comments

Comments
 (0)