Model.Unit.tsx Implementation Guide

Model.Unit.tsx files are foundational server components that provide reusable presentation elements for domain models in Akan.js applications. They create consistent visual representations that can be used across pages, zones, templates, and utilities.

Purpose and Role

Model Unit components serve several critical purposes in the Akan.js architecture:

  • Create standardized visual representations of domain entities
  • Serve as atomic UI building blocks for complex interfaces
  • Encapsulate rendering logic for cnst.LightModel data objects
  • Optimize for Next.js server components architecture

Component Variations

Abstract

Minimal representation with essential information only

1<Product.Unit.Abstract product={product} />
Card

Medium-detail representation in a card format

1<Product.Unit.Card product={product} />
Full

Complete representation with all relevant details

1<Product.Unit.Full product={product} />
Row

Table row representation for list views

1<Product.Unit.Row product={product} />

Example: Product Unit Components

1// Product.Unit.tsx
2export const Abstract = ({ product, className }) => (
3  <div className={"flex items-center gap-3"}>
4    {product.thumbnail && (
5      <Image file={product.thumbnail} className="h-12 w-12 rounded" />
6    )}
7    <div>
8      <h3 className="font-medium">{product.name}</h3>
9      <p className="text-sm">{product.price.toLocaleString()} KRW</p>
10    </div>
11  </div>
12);
13
14export const Card = ({ product, className }) => (
15  <div className={"card bg-base-100 shadow-sm"}>
16    {product.image && (
17      <Image file={product.image} className="h-48 w-full object-cover" />
18    )}
19    <div className="card-body">
20      <h2 className="card-title">{product.name}</h2>
21      <p className="line-clamp-2">{product.shortDescription}</p>
22      <div className="card-actions justify-end">
23        <button className="btn btn-primary btn-sm">View</button>
24      </div>
25    </div>
26  </div>
27);

Implementation Guidelines

server-components

Keep as server components without client-side hooks

1// No useState, useEffect, etc.
lightmodel

Only access properties defined in LightModel types

1product.name // Not product.description
conditional

Use optional chaining for nested properties

1product.avatar?.url
className

Always include className prop for styling

1className={'base-classes'}

Image Handling Best Practice

1import { Image } from "@akanjs/ui";
2
3export const Card = ({ product }) => (
4  <div className="card">
5    {product.image ? (
6      <Image 
7        file={product.image} 
8        alt={product.name}
9        className="h-40 w-full object-cover"
10        sizes="(max-width: 768px) 100vw, 50vw"
11      />
12    ) : (
13      <div className="bg-base-200 flex h-40 items-center justify-center">
14        <span className="text-base-content/50">No image</span>
15      </div>
16    )}
17  </div>
18);

Usage Examples

In Pages

1// Product page
2import { Product } from "@shared/client";
3
4export default async function ProductsPage() {
5  const products = await getProducts();
6  
7  return (
8    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
9      {products.map(product => (
10        <Product.Unit.Card 
11          key={product.id} 
12          product={product} 
13          href={`/products/${product.id}`}
14        />
15      ))}
16    </div>
17  );
18}

In Templates

1// Product selection template
2"use client";
3import { useState } from "react";
4import { Product } from "@shared/client";
5
6export const ProductSelector = ({ products }) => {
7  const [selectedId, setSelectedId] = useState(null);
8
9  return (
10    <div className="space-y-2">
11      {products.map(product => (
12        <div 
13          key={product.id}
14          className={`cursor-pointer transition-all ${selectedId === product.id ? "ring-2 ring-primary" : ""}`}
15          onClick={() => setSelectedId(product.id)}
16        >
17          <Product.Unit.Abstract product={product} />
18        </div>
19      ))}
20    </div>
21  );
22};

Performance Optimization

For optimal performance with Unit components:

1// Memoization in client components
2"use client";
3import { memo } from "react";
4import { Product } from "@shared/client";
5
6const MemoizedCard = memo(Product.Unit.Card);
7
8export const ProductGrid = ({ products }) => (
9  <div className="grid grid-cols-3 gap-4">
10    {products.map(product => (
11      <MemoizedCard key={product.id} product={product} />
12    ))}
13  </div>
14);
15
16// Virtualization for long lists
17"use client";
18import { useVirtualizer } from "@tanstack/react-virtual";
19import { useRef } from "react";
20import { User } from "@shared/client";
21
22export const VirtualUserList = ({ users }) => {
23  const parentRef = useRef();
24  const rowVirtualizer = useVirtualizer({
25    count: users.length,
26    getScrollElement: () => parentRef.current,
27    estimateSize: () => 64,
28  });
29
30  return (
31    <div ref={parentRef} className="h-[600px] overflow-auto">
32      <div style={{ height: `${rowVirtualizer.getTotalSize()}px`}}>
33        {rowVirtualizer.getVirtualItems().map(virtualItem => (
34          <div 
35            key={virtualItem.key}
36            style={{
37              position: "absolute",
38              top: 0,
39              left: 0,
40              width: "100%",
41              height: `${virtualItem.size}px`,
42              transform: `translateY(${virtualItem.start}px)`,
43            }}
44          >
45            <User.Unit.Row user={users[virtualItem.index]} />
46          </div>
47        ))}
48      </div>
49    </div>
50  );
51};

Troubleshooting

server-hooks

Server component using client hooks

1Remove useState/useEffect from Unit files
missing-props

Accessing undefined properties

1product.description → product.shortDescription
image-errors

Missing alt text for images

1<Image alt="Product image" ... />

Conclusion

Model.Unit.tsx files are essential building blocks in Akan.js that enable consistent, reusable presentation components for domain models. By following these implementation guidelines, you'll create performant, maintainable UI components that work seamlessly across your application.

Released under the MIT License
Official Akan.js Consulting onAkansoft
Copyright © 2025 Akan.js. All rights reserved.
System managed bybassman