Shared UI Components
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
The Shared UI Components in the Hoop WebApp V2 constitute a centrally owned visual layer designed to ensure consistency across the React-based modern frontend. These components wrap UI primitives from the Mantine v8 library, providing a standardized interface for developers to build pages and layouts without importing external library primitives directly. This architecture supports visual auditing and the use of centralized design patterns during the migration from the legacy ClojureScript (CLJS) environment.
Sources: webapp_v2/COMPONENTS.md:1-10, webapp_v2/CONTEXT_MIGRATION.md:5-15
Component Architecture and Strategy
The core strategy is that the application code never imports UI primitives directly from Mantine. Every primitive, such as Table, Button, or TextInput, is wrapped within the src/components/ directory. This abstraction allows for a consistent visual style, such as the surface-style table matching Radix UI from the legacy app, and the integration of semantic status badges.
Sources: webapp_v2/COMPONENTS.md:3-8, webapp_v2/COMPONENTS.md:118-124
UI Component Data Flow
The following diagram illustrates how page components interact with the shared component layer and the underlying state management via Zustand.
Diagram shows the relationship between React pages, shared wrappers, and the tech stack.
Sources: webapp_v2/COMPONENTS.md:3-8, webapp_v2/CONTEXT_MIGRATION.md:100-110
Key Reusable Components
Layout and State Components
These components handle high-level UI states like loading, empty data, and feature gating.
| Component | Purpose | Key Props |
|---|---|---|
PageLoader | Full-page or contained loading states. | h (height), overlay, error |
EmptyState | Zero-data states with call-to-action (CTA). | icon, title, description, action |
PageLayout | Standard padding for pages. | PAGE_PADDING (internal variable) |
FullBleed | Edge-to-edge rendering inside padded layouts. | children |
FreeLicenseCallout | Banners for feature-gated functionality. | message, variant ('info', 'limit') |
Sources: webapp_v2/COMPONENTS.md:13-33, webapp_v2/COMPONENTS.md:259-278, webapp_v2/COMPONENTS.md:316-324
Specialized Input Components
Specialized inputs extend standard forms to handle complex infrastructure requirements, such as secret management and paginated resource role selection.
Diagram shows specialized input flows for credentials and paginated data.
Sources: webapp_v2/COMPONENTS.md:175-195, webapp_v2/COMPONENTS.md:331-351
Data and Infrastructure Components
- Table: A surface-style table with
1px solid gray.3borders andborder-radius. It re-exports all sub-components (Thead, Tr, Th, Td) to maintain a single import point. Sources: webapp_v2/COMPONENTS.md:46-77 - ConnectionsMultiSelect: A port of the CLJS
connections-select. It resolves labels for selected IDs via?connection_ids=and handles infinite-scroll pagination. Sources: webapp_v2/COMPONENTS.md:298-311 - StepAccordion: A multi-step wizard mirror of the CLJS pattern, used for complex flows like Agent creation. Sources: webapp_v2/COMPONENTS.md:106-116
ClojureScript to React Mapping
Migrating to React components involves mapping legacy Hiccup/Tailwind patterns to Mantine-based wrappers.
| Legacy Tailwind Pattern | Mantine Shared Equivalent |
|---|---|
flex flex-col gap-4 | <Stack gap="md"> |
flex flex-row gap-4 | <Group gap="md"> |
text-sm text-gray-500 | <Text size="sm" c="dimmed"> |
webapp.components.callout-link | DocsBtnCallOut |
connections-select | ConnectionsMultiSelect |
Sources: webapp_v2/CLJS_PATTERNS.md:130-160, webapp_v2/COMPONENTS.md:298-300
Implementation Example: Role Configuration Details
The DetailsTab illustrates the use of Stack, TextInput, and MultiSelect to manage connection attributes and tags.
// webapp_v2/src/pages/Roles/Configure/DetailsTab.jsx
import { Stack, Title, Text, Group } from '@mantine/core'
import Badge from '@/components/Badge'
import TextInput from '@/components/TextInput'
import MultiSelect from '@/components/MultiSelect'
export default function DetailsTab({ connection }) {
return (
<Stack gap="xl" maw={720}>
<TextInput label="Name" value={connection.name} disabled />
<MultiSelect
label="Attributes"
data={attributeOptions}
value={drafts.attributes}
onChange={(value) => setDraft({ attributes: value })}
/>
</Stack>
)
}
Sources: webapp_v2/src/pages/Roles/Configure/DetailsTab.jsx:20-55
Notifications and Feedback
User feedback is managed via the showSnackbar utility, which is a React port of webapp.components.toast. It uses sonner for rendering to maintain visual parity with the legacy application. It supports level (success, error, info), text, and details (for error objects).
Sources: webapp_v2/COMPONENTS.md:404-425
Conclusion
Shared UI Components in Hoop serve as the foundation for the React Shell, facilitating a seamless transition from ClojureScript. By enforcing the use of standardized wrappers over Mantine primitives, the project ensures that infrastructure-heavy features, such as connection management and data masking, maintain a unified user experience while benefiting from a modern React 19 and Vite-based development stack.