Client

Codify

Role

UI/UX Designer

Industry

Maritime Security

Design system

Data-heavy UI

Component design

SaaS

B2B

Data Interaction Patterns for a Maritime Security Platform

Codify's client is a maritime security company providing digital tools for protecting commercial vessels, cargo, and offshore operations. I designed the core patterns operators rely on to monitor threats, manage tasks, and track cargo across multiple voyages — from a reusable table system to a container journey tracker.

13

product sections

One component used across 13 different contexts, from audit logs to cargo control

9

data types

Text, date, duration, status, icon+label, number, progress, checkbox, actions

5

component states

Default, hover, selected, loading, and empty, fully designed and documented

Context

Codify is IT outstaffing company. I joined as a contracted designer to work on an enterprise maritime security platform, used by operators to monitor vessels, manage tasks, and control cargo across multiple voyages simultaneously.

The problem

The platform needed two things a standard component library couldn't provide. First, a table system: the existing table was functional for basic use cases but not built for the data complexity Codify required. As the product scaled, tables needed to handle radically different contexts audit logs with minimal data, task monitoring with 12+ columns, cargo control checklists, scenario tables, and subscriber lists. Each context had different data types, interaction needs, and density requirements. Second, visibility into container movement: containers could pass through multiple tasks over their lifecycle, but the system only showed a flat list of tasks linked to a container. Checking a container's status on a different task meant manually searching for it there, one task at a time and if something went wrong, tracing what happened meant cross-checking timestamps and statuses by hand across every task involved.

My Role

I owned both pieces end-to-end — from defining the table component's architecture, states, variants, and data types for engineering, to designing a new way to visualize how containers moved between tasks. I also contributed to the broader design system.

Process

Container journey tracking (Follow Up Tasks) Containers could pass through multiple tasks over their lifecycle, but the existing system only showed a flat list of tasks linked to a container. To check its status on a different task, a user had to manually type in that task's ID and re-search for the container inside it one task at a time. I designed a container path view that puts the entire journey on one screen: a node graph showing every task the container passed through, in order — where it first appeared, where it closed out, and every intermediate status along the way, with the time between each step. Selecting any node opens that task's full status history for the container (scanned, checked, on hold, inaccessible) without leaving the view. Built fully responsive the graph collapses into a stacked, tap-through layout on mobile and documented across multiple states, matching the same "no unstyled edge cases" standard set on the table component. Component architecture 1.Header cells - sortable columns with directional indicators, consistent sizing across density levels, and a flexible layout that accommodates both short labels and longer compound headers. 2. Table cells - a unified cell component with variants for every data type: text. number, date, duration, status badge, icon+label, progress indicator, checkbox, and action menu. All built as Figma auto-layout components with properties. 3. Row states - default, hover, selected (checkbox), and flagged/alert rows with a left-border color indicator for urgency. Kept density consistent across all states. 4. Table footer - pagination component with "rows per page" control. page indicator, and navigation. Two variants: full and compact. 5.Empty state - a purpose-built empty state with icon, message, and a primary CTA ("Create Entity") - not a blank screen. 6.Responsive variants - designed and documented table behavior across 5 breakpoints, showing which columns collapse, truncate, or shift to secondary views at each size. What we needed to support:

Text / Number

Standard columns

Status badges

Ongoing, Not started, etc.

Task progress

3/25 subtasks completed

Overflow actions

Context menu per row

Date & Time

Multiple formats incl. duration

Checkboxes

Multi-select & bulk actions

Asset type +
icon

Asset type + icon

Vessel type with visual marker

Empty / loading states

Full table-level feedback

Design decisions

The core challenge on the table was making one system work across completely different use cases from a 3-column audit log to a 12-column vessel monitoring view. Instead of building separate tables per context, I built a composable cell library: each cell type is a standalone component that plugs into the same row/header shell. Engineering got a single table component to maintain; designers could assemble the right column set per context without breaking visual consistency. For the container journey, a flat status list per task would have been simpler to build, but it wouldn't show how tasks related to each other or how much time passed between steps. I chose a node-graph layout so operators could follow the actual path including where one task branched into several follow-ups and read time gaps at a glance instead of piecing them together from separate screens.

Large Project Gallery Image #4
Large Project Gallery Image #4

Results

Both patterns became core to the platform. The table component is used across task monitoring, cargo control, audit logs, scenarios, and contacts a stable foundation to build on rather than patching each screen individually. The container journey view replaced manual, task-by-task checking with a single screen showing a container's full path and status history.

What I'd do differently

I'd spend more time upfront mapping all the contexts each pattern would need to support before designing individual cells or nodes. Some table data-type variants came late when engineers surfaced new requirements, and the same would apply to the journey view's edge cases (like branching paths) — a proper content audit at the start would have caught both earlier.