Component: BlockRenderer
Relevant source files
The following files were used as context for generating this wiki page:The BlockRenderer is a fundamental React component in the Character Sheet Maker application. Its primary responsibility is to dynamically render different types of content blocks based on the block object passed to it as a prop. It functions as a conditional renderer, selecting the appropriate visual representation and behavior for each block type, such as headers, text fields, images, and more.
This component is central to the "What You See Is What You Get" (WYSIWYG) nature of the editor. It not only displays the blocks but also handles user interactions for updating block data and deleting blocks, communicating these changes to the central state management store. Styling for each block is dynamically applied based on a global theme, making the BlockRenderer a key integration point for data, logic, and presentation.
Sources: src/components/sheet/BlockRenderer.tsx, src/components/sheet/Canvas.tsx:10, src/store/useSheetStore.ts:20
Architecture and Placement
The BlockRenderer is not a standalone component; it is rendered within the Canvas component for each block present in the application's state. The Canvas component maps over the blocks array from the useSheetStore and instantiates a BlockRenderer for each item.
Sources: src/components/sheet/Canvas.tsx:50-56
This diagram shows the component hierarchy from the main Editor page down to the BlockRenderer.
Core Functionality
The component's logic is a large conditional block that checks the type property of the block prop. Based on this type, it renders a specific set of JSX elements. It also retrieves the current theme configuration to apply dynamic styling.
Sources: src/components/sheet/BlockRenderer.tsx:8-13
Rendering Flow
The following flowchart illustrates the decision-making process inside BlockRenderer.
State Interaction
BlockRenderer interacts directly with the useSheetStore (a Zustand store) to perform three main actions:
updateBlockData: Called when a user modifies the content of a block (e.g., typing in an input field). It updates thedataproperty for a specific block in the store.removeBlock: Called when the user clicks the delete button on a block. It removes the block from theblocksarray in the store.globalStyle: Accessed to get the current theme key (globalStyle.theme), which is used to retrieve the correct styling rules fromTHEMES.
Sources: src/components/sheet/BlockRenderer.tsx:8, src/store/useSheetStore.ts:43, 45, 51
The sequence diagram below shows how user input in a "text" block triggers a state update.
Supported Block Types
The component can render 8 distinct types of blocks, each with its own structure, data, and configuration. All blocks share a common DeleteBtn component for removal.
Sources: src/components/sheet/BlockRenderer.tsx:15-23, src/store/useSheetStore.ts:25
| Block Type | Description | Data Properties (block.data) | Config Properties (block.config) | Source Lines |
|---|---|---|---|---|
header | A title or subtitle. | text: string | level: 1 | 2 | 26-58 |
form-box | A labeled text area. | label: string, value: string | 61-90 | |
shape | A decorative geometric shape. | shapeType: "square" | "circle" | "rounded" | "heart" | 93-128 | |
divider | A horizontal line. | 131-137 | ||
container | A background element for grouping other blocks. | zIndex: "back" | 140-150 | |
list | An unordered list of editable items. | items: string[] | 153-184 | |
image | An image uploader and display area. | src: string (Data URL) | 187-218 | |
text | A free-form paragraph text area. | text: string | 221-234 |
Theming and Styling
Styling is not hardcoded. BlockRenderer retrieves the current theme configuration object from the THEMES constant defined in src/lib/themes.ts. The key for the current theme is read from useSheetStore().globalStyle.theme.
This allows each block type to have distinct visual styles (fonts, colors, borders) for different themes like "simple", "medieval", or "cyberpunk".
Sources: src/components/sheet/BlockRenderer.tsx:11, src/lib/themes.ts:32, 59, 86, src/store/useSheetStore.ts:50-51
This diagram illustrates how a theme is resolved and applied.
For example, the header block's class is determined by the theme:
// src/components/sheet/BlockRenderer.tsx:34-35
// Select the class from the theme based on level
const themeClass = level === 1 ? currentTheme.blocks.header.h1 : currentTheme.blocks.header.h2;
And the theme definition provides the actual CSS classes:
// src/lib/themes.ts:44-47
header: {
h1: "font-extrabold text-4xl border-b-2 border-gray-900 pb-2 tracking-tight",
h2: "font-bold text-2xl text-gray-700",
},
Conclusion
The BlockRenderer component is a critical piece of the application's architecture, acting as the bridge between abstract block data and its concrete, user-interactive representation on the canvas. Its flexible, type-driven design allows for easy extension with new block types, while its integration with the theme and state management systems ensures a consistent and dynamic user experience. It effectively decouples data structure from presentation, making the codebase more modular and maintainable.