Packages

Clarity is an interactive introspection and visualization tool for Elixir projects, providing navigable graphs and diagrams for frameworks like Ash, Phoenix, and Ecto.

Current section

Files

Jump to
clarity lib clarity content graph.html.heex
Raw

lib/clarity/content/graph.html.heex

<div class="content flex flex-col h-full relative">
<div class="absolute top-4 right-4 z-10">
<button
type="button"
phx-click="toggle_controls"
phx-target={@myself}
class="inline-flex items-center justify-center p-2 rounded-md text-base-light-600 dark:text-base-dark-400 hover:text-base-light-900 dark:hover:text-base-dark-100 bg-base-light-100 dark:bg-base-dark-800 hover:bg-base-light-200 dark:hover:bg-base-dark-700 focus:outline-hidden focus:ring-2 focus:ring-primary-light dark:focus:ring-primary-dark transition-colors shadow-md border border-base-light-300 dark:border-base-dark-700"
aria-label="Toggle zoom controls"
>
<.icon_sliders class="w-5 h-5" />
</button>
<div
:if={@show_controls}
class="absolute top-12 right-0 bg-base-light-100 dark:bg-base-dark-800 rounded-lg p-4 shadow-lg border border-base-light-300 dark:border-base-dark-700 min-w-[20rem]"
>
<h3 class="text-sm font-semibold text-base-light-900 dark:text-base-dark-50 mb-3">
Graph Controls
</h3>
<form phx-change="update_controls" phx-target={@myself} class="flex flex-col gap-4">
<% {outgoing_edges, incoming_edges} = @zoom_level %>
<div class="flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-sm font-medium text-base-light-700 dark:text-base-dark-300">
Outgoing:
</span>
<span class="text-sm font-semibold text-base-light-900 dark:text-base-dark-100 min-w-[1.5rem] text-right">
{outgoing_edges}
</span>
</div>
<input
type="range"
name="outgoing_edges"
value={outgoing_edges}
min="0"
max="5"
class="w-full h-2 bg-base-light-300 dark:bg-base-dark-600 rounded-lg appearance-none cursor-pointer accent-primary-light dark:accent-primary-dark"
/>
</div>
<div class="flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-sm font-medium text-base-light-700 dark:text-base-dark-300">
Incoming:
</span>
<span class="text-sm font-semibold text-base-light-900 dark:text-base-dark-100 min-w-[1.5rem] text-right">
{incoming_edges}
</span>
</div>
<input
type="range"
name="incoming_edges"
value={incoming_edges}
min="0"
max="5"
class="w-full h-2 bg-base-light-300 dark:bg-base-dark-600 rounded-lg appearance-none cursor-pointer accent-primary-light dark:accent-primary-dark"
/>
</div>
<div class="flex flex-col gap-2">
<label class="flex items-center justify-between">
<span class="text-sm font-medium text-base-light-700 dark:text-base-dark-300">
Max Vertices:
</span>
<input
type="number"
name="max_vertices"
value={@max_vertices}
min="1"
max="1000"
class="w-20 px-3 py-1 text-sm bg-base-light-50 dark:bg-base-dark-900 border border-base-light-300 dark:border-base-dark-600 rounded-md text-base-light-900 dark:text-base-dark-100 focus:outline-hidden focus:ring-2 focus:ring-primary-light dark:focus:ring-primary-dark focus:border-transparent transition-colors hover:border-base-light-400 dark:hover:border-base-dark-500"
/>
</label>
</div>
</form>
<div
:if={length(@available_vertex_types) > 0}
class="flex flex-col gap-2 pt-2 border-t border-base-light-300 dark:border-base-dark-700"
>
<span class="text-sm font-semibold text-base-light-900 dark:text-base-dark-50">
Vertex Types
</span>
<div class="flex flex-col gap-1 max-h-48 overflow-y-auto">
<label
:for={vertex_type <- @available_vertex_types}
class="flex items-center gap-2 cursor-pointer hover:bg-base-light-50 dark:hover:bg-base-dark-900 p-1 rounded"
>
<input
type="checkbox"
name={"vertex_type_#{vertex_type}"}
value={inspect(vertex_type)}
checked={@shown_vertex_types == [] or vertex_type in @shown_vertex_types}
phx-click="toggle_vertex_type"
phx-value-type={inspect(vertex_type)}
phx-target={@myself}
class="rounded border-base-light-300 dark:border-base-dark-600 text-primary-light dark:text-primary-dark focus:ring-2 focus:ring-primary-light dark:focus:ring-primary-dark"
/>
<span class="text-sm text-base-light-900 dark:text-base-dark-100">
{inspect(vertex_type)}
</span>
</label>
</div>
</div>
</div>
</div>
<div class="flex-1 min-h-0 p-4">
<.viz
graph={
Graph.DOT.to_dot(@zoom_subgraph,
theme: @theme,
highlight: @vertex,
max_vertices: @max_vertices
)
}
id="content-view-viz"
class="h-full"
/>
</div>
</div>