@@ -208,7 +208,7 @@ vdom.H("ul", nil,
208208 vdom.ForEach (items, func (item string , idx int ) any {
209209 return vdom.H (" li" , map [string ]any{
210210 " key" : idx,
211- " className" : " list-item " ,
211+ " className" : " py-2 px-3 border-b border-gray-100 " ,
212212 }, item)
213213 }),
214214)
@@ -326,7 +326,7 @@ This makes Tsunami applications naturally suitable for integration with external
326326
327327## Style Handling
328328
329- Tsunami applications use Tailwind v4 CSS by default for styling (className prop). You can also define inline styles using a map[ string] any in the props:
329+ Tsunami applications use Tailwind v4 CSS by default for styling (className prop) and you should favor styling with Tailwind whenever possible. However, you may also define inline styles using a map[ string] any in the props:
330330
331331``` go
332332vdom.H (" div" , map [string ]any{
@@ -359,6 +359,14 @@ Properties use camelCase (must match React) and values can be:
359359
360360The style map in props mirrors React's style object pattern, making it familiar to React developers while maintaining type safety in Go.
361361
362+ ### External Styles and Stylesheets
363+
364+ Quick styles can be added using a vdom.H("style", nil, "...") tag. You may also place CSS files in the ` static ` directory, and serve them directly with:
365+
366+ ``` go
367+ vdom.H (" link" , map [string ]any{" rel" : " stylesheet" , " src" : " /static/mystyles.css" })
368+ ```
369+
362370## Component Definition Pattern
363371
364372Create typed, reusable components using the client:
@@ -376,21 +384,17 @@ var TodoItem = app.DefineComponent("TodoItem",
376384 func (ctx context .Context , props TodoItemProps ) any {
377385 return vdom.H (" div" , map [string ]any{
378386 " className" : vdom.Classes (
379- " todo-item " ,
380- vdom.If (props.IsActive , " active " ),
387+ " p-3 border-b border-gray-200 cursor-pointer transition-opacity " ,
388+ vdom.If (props.IsActive , " opacity-100 bg-blue-50 " , " opacity-70 hover:bg-gray-50 " ),
381389 ),
382390 " onClick" : props.OnToggle ,
383- " style" : map [string ]any{
384- " cursor" : " pointer" ,
385- " opacity" : vdom.If (props.IsActive , 1.0 , 0.7 ),
386- },
387391 }, props.Todo .Text )
388392 },
389393)
390394
391395// Usage in parent component:
392396vdom.H (" div" , map [string ]any{
393- " className" : " todo-list " ,
397+ " className" : " bg-white rounded-lg shadow-sm border " ,
394398},
395399 TodoItem (TodoItemProps{
396400 Todo : todo,
@@ -403,7 +407,7 @@ vdom.H("div", map[string]any{
403407TodoItem (TodoItemProps{
404408 Todo : todo,
405409 OnToggle : handleToggle,
406- }).WithKey (fmt. Sprint ( idx) )
410+ }).WithKey (idx)
407411```
408412
409413Components in Tsunami:
@@ -417,10 +421,11 @@ Components in Tsunami:
417421
418422Special Handling for Component "key" prop:
419423
420- - Use the WithKey(key string) chaining func to set a key on a component
424+ - Use the ` WithKey(key any) ` chaining func to set a key on a component
421425- Keys must be added for components rendered in lists (just like in React)
422426- Keys should be unique among siblings and stable across renders
423427- Keys are handled at the framework level and should not be declared in component props
428+ - ` WithKey ` accepts any type and automatically converts it to a string using fmt.Sprint
424429
425430This pattern matches React's functional components while maintaining Go's type safety and explicit props definition.
426431
@@ -466,7 +471,7 @@ keyHandler := &vdom.VDomFunc{
466471}
467472
468473vdom.H (" input" , map [string ]any{
469- " className" : " special-input " ,
474+ " className" : " px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 " ,
470475 " onKeyDown" : keyHandler,
471476})
472477
@@ -555,8 +560,10 @@ func MyComponent(ctx context.Context, props MyProps) any {
555560 },
556561 }),
557562 vdom.H (" ul" , nil ,
558- vdom.ForEach (items, func (item string , _ int ) any {
559- return vdom.H (" li" , nil , item)
563+ vdom.ForEach (items, func (item string , idx int ) any {
564+ return vdom.H (" li" , map [string ]any{
565+ " key" : idx,
566+ }, item)
560567 }),
561568 ),
562569 )
@@ -584,7 +591,7 @@ The system provides three main types of hooks:
584591 })
585592 ```
586593
587- 2 . vdom.UseRef - For values that persist between renders without triggering updates:
594+ 2 . vdom.UseRef - For values that persist between renders without triggering updates (like React.useRef) :
588595
589596 - Holds mutable values that survive re-renders
590597 - Changes don't cause re-renders
@@ -593,6 +600,7 @@ The system provides three main types of hooks:
593600 - Storing timers/channels
594601 - Tracking subscriptions
595602 - Holding complex state structures
603+ - Unlike React, this ref CANNOT be set as the ref prop on an element
596604
597605 ``` go
598606 timerRef := vdom.UseRef (ctx, &TimerState{
@@ -607,6 +615,7 @@ The system provides three main types of hooks:
607615 - Managing focus
608616 - Measuring elements
609617 - Direct DOM manipulation when needed
618+ - These ref objects SHOULD be set as ref prop on elements.
610619 ``` go
611620 inputRef := vdom.UseVDomRef (ctx)
612621 vdom.H (" input" , map [string ]any{
@@ -696,8 +705,9 @@ var TodoApp = app.DefineComponent("TodoApp",
696705 }, []any{})
697706
698707 return vdom.H (" div" , nil ,
699- vdom.ForEach (globalTodos, func (todo Todo , _ int ) any {
700- return TodoItem (TodoItemProps{Todo: todo})
708+ vdom.ForEach (globalTodos, func (todo Todo , idx int ) any {
709+ // Use WithKey() for adding keys to components
710+ return TodoItem (TodoItemProps{Todo: todo}).WithKey (idx)
701711 }),
702712 )
703713 },
@@ -923,7 +933,7 @@ var App = app.DefineComponent("App",
923933 Todo: todo,
924934 OnToggle: func () { toggleTodo (todo.Id ) },
925935 OnDelete: func () { deleteTodo (todo.Id ) },
926- }).WithKey (strconv. Itoa ( todo.Id ) )
936+ }).WithKey (todo.Id )
927937 })),
928938 )
929939 },
0 commit comments