# How Persona-Adaptive UIs Adjust Detail Levels for Different User Types in Understand-Anything

> Discover how persona-adaptive UIs in Understand Anything tailor detail levels for non-technical, junior, or experienced users by dynamically adjusting components and data.

- Repository: [Yuxiang Lin/Understand-Anything](https://github.com/Lum1104/Understand-Anything)
- Tags: deep-dive
- Published: 2026-06-06

---

**Persona-adaptive UIs adjust detail levels by storing the selected user type in a global Zustand store and conditionally rendering interface components, filtering graph visualization nodes, and adapting export functionality based on whether the current user is non-technical, junior, or experienced.**

The Understand-Anything repository demonstrates how persona-adaptive UIs adjust detail levels for different user types through a sophisticated React-based dashboard architecture. By categorizing users into three distinct technical proficiency tiers and leveraging centralized state management, the system dynamically scales interface complexity without maintaining separate codebases. This approach ensures non-technical stakeholders see clean overviews while experienced developers access deep code graph analysis.

## Core Architecture and State Management

### Global State with Zustand

The foundation of the persona-adaptive system lies in a centralized Zustand store defined in [`packages/dashboard/src/store.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/packages/dashboard/src/store.ts). At line 289, the store defines the `persona` state as a type-safe discriminated union: `"non-technical" | "junior" | "experienced"`, alongside a `setPersona` setter function.

Components subscribe to this store using `useDashboardStore`, creating a reactive pipeline where persona changes trigger immediate UI updates. Because the state is global, switching personas propagates changes consistently across the dashboard's layout, graph views, and export features.

### Programmatic Persona Control

Developers can adjust detail levels programmatically through the store's API, enabling automated onboarding flows or keyboard shortcuts:

```typescript
// Switch persona programmatically (e.g. from a shortcut or test)
import { useDashboardStore } from "./store";

function switchToExperienced() {
  const setPersona = useDashboardStore.getState().setPersona;
  setPersona("experienced");
}

```

## Interface Adaptation Strategies

### Dynamic Layout Switching in App.tsx

The main layout engine in [`packages/dashboard/src/App.tsx`](https://github.com/Lum1104/Understand-Anything/blob/main/packages/dashboard/src/App.tsx) implements conditional rendering logic to show different panels based on the active persona. At line 1566, the component uses persona equality checks to branch the grid layout:

- **Non-technical**: Displays only the high-level graph and file explorer via `ProjectOverview`
- **Junior**: Adds the `LearnPanel` component featuring guided tours and language lessons
- **Experienced**: Reveals the full `NodeInfo` panel for deep-dive analysis

```tsx
// Layout branching in App.tsx (simplified)
{persona === "non-technical" ? (
  <ProjectOverview />
) : persona === "junior" || tourActive ? (
  <LearnPanel />
) : (
  <NodeInfo />
)}

```

### Graph Node Filtering in GraphView.tsx

To adjust detail levels in the visualization layer, [`packages/dashboard/src/components/GraphView.tsx`](https://github.com/Lum1104/Understand-Anything/blob/main/packages/dashboard/src/components/GraphView.tsx) implements persona-aware filtering at line 439. The system maintains a `Set` of `subFileTypes` representing low-level implementation details. When `persona === "non-technical"`, the filter removes individual functions and class members:

```typescript
// Persona-aware node filter used in GraphView
const filteredGraphNodes = graph.nodes.filter((n) => {
  if (persona === "non-technical" && subFileTypes.has(n.type)) {
    return false; // hide low-level implementation details
  }
  return true;
});

```

This ensures non-technical users see architectural relationships without implementation noise.

### Persona-Aware Export Logic

The adaptation extends to data export functionality in [`packages/dashboard/src/components/ExportMenu.tsx`](https://github.com/Lum1104/Understand-Anything/blob/main/packages/dashboard/src/components/ExportMenu.tsx). At line 186, the component builds `filteredGraphNodes` based on the current persona, ensuring exported graph data respects the same detail-level filters as the interactive view. Search results are similarly scoped to match the visible layer, preventing non-technical users from encountering overwhelming implementation details in exported reports.

## User Selection Flow

### PersonaSelector Component Mapping

The [`packages/dashboard/src/components/PersonaSelector.tsx`](https://github.com/Lum1104/Understand-Anything/blob/main/packages/dashboard/src/components/PersonaSelector.tsx) component provides the dropdown interface for persona selection at line 5. It maps user-friendly display labels to internal store values:

- `overview` → `"non-technical"`
- `learn` → `"junior"`
- `deepDive` → `"experienced"`

When users interact with the selector, the component invokes `setPersona` to update the global store, triggering the reactive cascade through all subscribed components and immediately adjusting detail levels across the interface.

## Performance Optimization Through Memoization

The Understand-Anything dashboard maintains responsiveness even with large code graphs by memoizing layout computations. As documented in the design specification "graph-layout-scaling-design", heavy layout calculations use the `persona` value as part of their memoization dependency array. This ensures layout recomputation only occurs when the persona actually changes, or when underlying graph topology or diff mode changes, rather than on every render cycle.

## Summary

- The system stores persona state in a type-safe Zustand store at [`packages/dashboard/src/store.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/packages/dashboard/src/store.ts) with three valid values: `"non-technical"`, `"junior"`, and `"experienced"`
- [`App.tsx`](https://github.com/Lum1104/Understand-Anything/blob/main/App.tsx) conditionally renders entirely different panel components based on the active persona, switching between `ProjectOverview`, `LearnPanel`, and `NodeInfo`
- [`GraphView.tsx`](https://github.com/Lum1104/Understand-Anything/blob/main/GraphView.tsx) filters low-level implementation nodes when `persona === "non-technical"`, hiding function-level details from non-technical users
- Export functionality in [`ExportMenu.tsx`](https://github.com/Lum1104/Understand-Anything/blob/main/ExportMenu.tsx) respects persona filters, ensuring exported data matches the current view's detail level
- Layout calculations are memoized against persona changes to maintain performance on large graphs

## Frequently Asked Questions

### What are the three user personas in Understand-Anything?

The dashboard recognizes three personas representing different technical familiarity levels: **non-technical** users who see only high-level overviews and file explorers, **junior** developers who receive guided learning panels with tutorials, and **experienced** developers who access the full `NodeInfo` panel for deep code analysis and low-level graph details.

### How does the system prevent layout recalculation on every render?

The dashboard implements memoization strategies that use the `persona` value as a dependency key for heavy layout computations. According to the "graph-layout-scaling-design" specification, layout engines only recompute when the persona actually changes, keeping the UI responsive even with large code graphs.

### Can developers trigger persona switches programmatically?

Yes. The Zustand store exposes a `setPersona` method accessible via `useDashboardStore.getState().setPersona`, allowing programmatic persona switching for testing, keyboard shortcuts, or automated onboarding flows that automatically adjust detail levels based on user actions.

### How does the export feature maintain persona-appropriate detail levels?

The [`ExportMenu.tsx`](https://github.com/Lum1104/Understand-Anything/blob/main/ExportMenu.tsx) component builds `filteredGraphNodes` using the same filtering logic as the main graph view, specifically checking the current persona value at line 186 before generating export payloads. This ensures exported files contain only the detail level currently visible to the user, preventing information overload in shared reports.