Back to work
The Users module of the Funding Pips operations platform: a filters sidebar, a dense results table, and the module switcher across the top.

00 · Introduction

From a table that forgot every question to a product built to remember

Funding Pips managed its trading operation from one dense table. Filters reset, useful queries disappeared, and operators had no way to save or transfer what they had built. I redesigned the experience around persistent queries: three ways to ask, one live and editable place to continue the work.

Role
Product designer · module lead One of four designers on the redesign. I led this module end-to-end and shaped the shared foundation; the other six modules were carried by the rest of the team.
Timeline
Two months · Nov 2025 to Jan 2026 From a bare table to a persistent query system
Scope
1 module, designed in depth Shared foundation across 7 modules, designed in parallel by the team.
Status
Built and in use
Challenge

The live product could display the operation, but it could not remember how operators worked with it. Filters reset after every visit, statuses were reduced to coloured text, and detail pages surfaced NaN. Each investigation had to be reconstructed from scratch.

Objective

Build the missing product shell and turn temporary filtering into persistent, reusable queries. Whether operators constructed a query with filters, reopened a saved filter, or wrote it as a sentence, every route would resolve into the same live, editable view.

01 · The case in brief

The whole case, before the details

Problem

One table · no persistent context

Queries could be built for the moment, but not saved or handed to another operator.

Key decision

The query is the product.

Filters, saved filters and the command bar became three entrances to one live, editable query, not three disconnected features.

Evidence

Four findings shaped the direction: two observed in the live product, one identified through iteration history, and one explicitly marked as inference. Two external sources supported the underlying interaction principles.

4 findings · 2 external sources Evidence types disclosed
What shipped 3 entrances · 1 editable destination

Operators can enter through three routes with progressively fewer setup steps without losing the ability to inspect or refine the resulting query.

Built and in use

02 · The baseline

One table was the whole product

The starting point is the screen below: one table, one Filter button, and nothing that held a result. Operators could narrow a set, but the narrowing did not persist, could not be named or handed on, and produced no counts to read at a glance. Status was coloured text rather than a system, and detail pages printed NaN. Those specific gaps became the seven requirements below.

The old design · where the study started
The original Funding Pips shell: a plain table with top tabs and a single Filter button.

The operator model

Every task moved through the same three stages

3 operator jobs → 7 product requirements

The interface failed at different points in the same operator loop. Mapping those breaks made every product requirement traceable to the work an operator was trying to complete. This study covers the three stages up to the decision; the action itself sits in the account detail module.

Ask

Frame the operational question.

Narrow

Define the relevant set.

Read

Interpret what the set reveals.


What had to exist
Ask

Shared product shell

Top tabs only; no shared workspace carrying query, summary and panel state

→ 06 · The shell

Narrow

Persistent filtering

One Filter button; nothing persists

→ 06 · The shell

Narrow

Query stated in words

A global icon only; no way to state a query

→ 09 · Command bar

Narrow

Named saved filters

Nothing to keep, share or return to

→ 07 · Saved filters

Read

Live summary

No counts of anything, anywhere

→ 08 · Quick stats

Read

Status vocabulary

Red and green words, no system

→ 13 · UI foundation

Read

Defined numeric states

NaN printed straight to operators

→ 08 · Quick stats

03 · Product audit

What was observed, what history revealed, and what remains inferred

The audit produced four findings. Two are visible in the live interface, one appears in iteration history, and one remains a design hypothesis grounded in established interaction principles. Each is labelled by evidence type so observation is never presented as operator validation.

Observed · live product

A · Query state cannot persist

The interface offers filtering, but no visible way to preserve the resulting query. Once the working context changes, there is no durable state for an operator to reopen.

Observed · live product

B · Useful queries cannot be handed off

The interface provides no visible way to name, own or share a completed filter configuration. What one operator discovers cannot become a reusable product object for another.

Observed · iteration history

C · The first redesign iteration fixed the same metrics for everyone

The initial redesigned shell introduced one shared metric strip with no way to add, remove or reorder its contents.

Inferred · pattern supported

D · Field-by-field filtering widens the gap between intent and action

An operator may begin with a complete request, but the interface requires that request to be decomposed into individual controls in a system-defined sequence. This is a design hypothesis, not an observed operator behaviour.

Supporting principles, not product validation
01

Ten usability heuristics for user interface design

Jakob Nielsen · Nielsen Norman Group · 1994

Recognition rather than recall: interfaces should keep relevant options and prior state visible or easily retrievable instead of requiring people to remember them. This supports the design rationale behind Finding A, but does not prove product-specific operator impact.

View the Nielsen Norman Group source →
02

The design of everyday things

Don Norman · Revised and expanded edition · Basic Books · 2013

The gulf of execution describes the distance between a person’s intended outcome and the actions an interface makes available. It provides a conceptual lens for Finding D, not validation of the proposed command bar.

View the publisher’s book page →

04 · Strategy

Four moves that made the query the workflow

Each move answers one finding. Together they turn narrowing from a thing you do to the list into the thing the product is for.

Move 01

The shell remembers

Filter state, column state and panel state persist with the view instead of resetting on navigation. The filter panel collapses when the operator is reading, and the data canvas expands into the space it releases, so the screen suits the task without ever losing the query.

Answers finding A
Before

In the first redesign iteration, the filter controls sat behind an icon and reset the moment you left the page. The original product had a single Filter button and nothing that held a result.

After

Query survives navigation, the filter panel collapses to suit the task

Move 02

Queries get names and owners

A constructed query is saved with a name and an owner, and appears in a flyout. The configuration becomes a reusable object rather than a set of controls to rebuild.

Answers finding B
Before

No saved object; a query exists only while the session lasts

After

Quick Andy Filters, Bolo filters, Students only

Move 03

The metric strip belongs to the operator

Quick Stats enters an edit mode. Metrics can be added, removed and reordered, so the strip is configured per-operator rather than fixed for everyone.

Answers finding C
Before

Five fixed metrics, identical for everyone

After

Add, remove and reorder, edited in place

Move 04

A sentence becomes a filter

A command bar accepts the sentence the operator already has, parses it into visible chips they can correct, then opens the real list with the filter panel populated to match.

Answers finding D
Before

Translate intent into the filter fields, one at a time, in the interface order

After

Type the intent, check the parse, land in the real view

05 · The product moves

What the strategy produced, and where each part is examined

The four moves became one rebuilt foundation and three capabilities the live product had no equivalent of. This page is the map; the sections that follow are the evidence.

The product evolution · three phases
Phase 0Original · one table

The running system, shown above: a table with top tabs and every filter behind one button.

Phase 1First redesign iteration · Nov 2025

The first redesign iteration rebuilt the existing table inside a shared shell, with a fixed five-card metric strip and temporary filters hidden behind an icon.

Phase 2Persistent query system · Jan 2026

The screens in this study. Persistent filters, editable metrics, saved filters, the command bar.

Where each capability is examined
00

The product shell Rebuilt foundation

Navigation, a metric strip and a persistent filter panel around the existing table.

06 · The shell
01

Saved filters Net new

A filter configuration kept as a named object with an owner and edit history.

07 · Saved filters
02

Editable metrics Net new

Add, remove and reorder the metric strip; the arrangement persists with the view.

08 · Quick stats
03

The command bar Net new

A typed sentence parsed into visible chips that open the list already filtered.

09 to 11

06 · The shell

The filter panel collapses, the data canvas expands

One module is detailed here; all seven inherit the same frame: a persistent top navigation bar, a filter panel carrying the query, a metric strip, and the data canvas. The filter panel collapses; the data canvas expands into the space it releases. Navigation stays visible at all times.

01

Persistent navigation bar

Module switcher and account identity. Persistent: it stays visible in every state shown here.

02

Filter panel

Holds the entire query state, including saved filters. Collapses when the operator is reading rather than narrowing.

03

Data canvas

Quick Stats above a dense table, with contextual drawers. Expands to fill the remaining workspace.

The shell in three zones: navigating (persistent navigation bar, always visible), building (filter panel, collapses when reading), and reading and scanning (data canvas, expands to fill the remaining workspace).
Two states of the same screen: filter panel expanded while building a question, and collapsed while scanning, with the query still applied.

An operator scanning twelve columns collapses the filter panel and the canvas expands into the space it releases. An operator building a complex query keeps the filters open and lets the table shrink. Same screen, two different jobs.


The query survives navigation · closes R 02
01

Build the query

StudentStandardNew> 5,000
02

Open a user, then go back

navigated awayreturned
03

The query is still there

StudentStandardNew> 5,000

Filter state, column state and panel state are held by the view, not the session. In the live product the same trip returned an empty panel.

The product, so far Shell: added Summary: added Filters: added Query: still disposable

07 · Saved filters

A query with a name and an owner becomes a stored object

The interaction is small: build a query, name it, save it. Once a query has a name and an owner, it becomes a stored object that can be recalled, shared, reviewed and corrected.

The saved-filters flyout listing queries by name, and the modal that names a query before saving it.
 Without a nameWith a name
TransferabilityNo transferable object existsSelected from a named list
EditabilityEach copy is edited separatelyEdited once, in the shared definition
OwnershipNo ownership metadataOwner and last edited are recorded
PersistenceLost when the session endsPersists as a stored object

What the saved filter carries · specification

Quick Andy Filters

Owner · A. ZacekEdited 12 Jan
StudentStandardNewBalance > 5,000 USD
Ownership

Owner and last edited metadata are stored on the saved object and demonstrated in the specification below.

Save

The modal titles Save filter, labels the field Filter name, and its primary control reads Save filter.

Delete

Proposed safeguard: deletion requires confirmation, names the affected filter and offers session level undo.

The product, so far Shell: added Query: named and owned Metrics: still fixed

A query can now outlive the session and the person. The metric strip is still the same for everyone; the next section fixes that.

08 · Quick stats

From no summary at all, to a fixed strip, to one the operator owns

The original product carried no summary of any kind: the baseline screen in section 02 opens straight into rows. The first redesign iteration introduced one fixed strip, identical for every operator. Edit mode replaces that fixed configuration with a per-operator arrangement that persists with the view.

Phase 0 · the original product, same region of the screen
The original product at the same region of the screen: the table header sits directly under the navigation, with no summary layer between them.
Quick Stats in edit mode: each card gains a drag handle and a remove control, with Add metric at the end of the strip; and the strip after a card is removed and replaced.

Five metric states · closes R 07, honest numbers
5,001vs last month, up 20%
0no users in this state
Not availablesource did not return a value
Loadingspinner plus a Loading label, card keeps its size
Could not loadretry, and the card keeps its slot

The live product printed NaN when a value could not be computed. A card now states which of these five it is, and never shows a number it does not have.

The original had no strip. The first redesign iteration fixed five cards for every operator. Edit mode now allows add, remove and reorder, and the arrangement persists with the view. Designed behaviour; adoption was not measured.

The product, so far Shell: added Query: named and owned Metrics: per operator

The strip now belongs to the person reading it. The list now holds persistent queries, owned filters and configurable metrics. The remaining product move is the command bar.

09 · The command bar

The shortest route is also the one that must reveal its mistakes

Saved filters retrieve questions that already have a name. They do nothing for a new query that has never been built. A command bar accepts the sentence directly. It is also the only place in this module where the product can confidently misunderstand somebody and still look like it worked.

Operator has a sentence Call the bar from anywhere System parses to chips Parse correct? Real filtered view
If not No Edit a chip Review the parse again Yes Run the query
Entry point⌘Kon macOS · Ctrl+K on Windows

An accelerator over the existing filter model, not a replacement: nothing runs until the operator has seen the parse, and the panel route stays available throughout.

After the parse appears, Enter or Run query executes it. Before the parse is shown, neither action runs anything. Escape closes the bar and returns the operator to the originating screen.

10 · Command bar · type and parse

It opens from anywhere, and it shows what it understood

The bar is called with one shortcut and parses the sentence live into structured chips beneath it. The operator sees exactly what the system understood before anything runs.

01 · It opens from anywhere

One shortcut, ⌘K on macOS or Ctrl+K on Windows, opens the bar as a global overlay. Escape returns the operator to the originating screen without changing query state.

The command bar open as a global overlay at step 2 of 3, with the typed sentence above and the parsed chips beneath it.

1 — The sentence, in the operator language: new Standard Student users with balance over 5,000 USD.

2 — The parse, as editable tokens: New · Standard · Student · Balance · 5,000 USD.

Run query · Enter to run. Available only once the parse is visible.

A natural language interface fails at the moment the person cannot tell what the machine heard. Showing the parse as editable tokens turns a black box into a glass box, and it does so before the query runs rather than after the results look wrong.


Design comparison · not observed product behaviour
 Without the chipsWith the chips
Where errors surfaceIn the result set, as a plausible but wrong listIn the parse, before anything is run
How a person recoversRewrite the sentence without knowing which term failedEdit the token that is wrong
What the operator learnsNothing about how the system reads themThe vocabulary the system actually supports
Execution gateQuery runs immediately on submitQuery runs only after the parse is shown

11 · Command bar · the result

It lands in the real view, not in an answer

The bar does not return an answer. It opens the existing Users module with the filter panel populated from the parse. From there, the query can be adjusted, saved and shared using the same controls as a manually constructed query.

Step 3 of 3: the Users module opens with the filter panel populated from the parse — status New, type Student and Standard, balance above 5,000 USD.

1 — The filter panel, populated from the parse: status New, type Student and Standard, balance above 5,000 USD.

2 — Quick Stats stays global here, labelled Global (20,212), because its values describe the whole population rather than the 1,284 result. Scoping the summary to the active filter is a known gap, listed in what should be measured next.

The command bar is an entry route into the existing product, not a separate result surface. The same table, filters and saved view controls remain available on arrival.

The product, so far New Standard Student Balance > 5,000 USD One view

The route with the fewest setup steps: a sentence, parsed in front of the operator, landing in the shell from section 06.

12 · States and edge cases

What happens when the sentence is wrong

An accelerator is judged on its worst input, not its best. These six states carry the rules that keep the bar honest when it cannot do what was asked.

Nothing parsed

Understanding failure

No filters recognised in that phrase

Open filters instead

The bar never guesses. If no chip can be produced it says so and hands the operator to the filter panel with the raw text preserved, rather than running an empty or arbitrary query.

Partly parsed

Understanding failure

Understood: Student · Balance 5,000. Not understood: recently

Edit the parse

A partial understanding is shown as a partial parse. The recognised chips stand, the unrecognised words are named explicitly, and nothing runs until the operator accepts what is there.

Ambiguous term

Understanding failure

Closed could mean account status or challenge outcome

Choose one

Where one word maps to two fields, the bar asks rather than picking. A silent choice here produces a plausible list that is quietly about the wrong thing, which is the most expensive failure available to it.

Parse is right, result is empty

Result failure

0 of 20,212 users match this filter

Edit constraints

An empty result is a finding, not a dead end. The chips stay on screen so the operator can see which constraint eliminated everything and loosen that one specifically.

Permission does not cover it

Permission failure

Your role cannot view payout amounts

Remove restricted criterion

The bar can express queries an operator is not entitled to run. It identifies the restricted criterion, explains why it cannot run and prevents execution until that criterion is removed.

Parser slow or offline

System failure

Command bar is taking longer than usual

Use filters instead

The bar degrades, the product does not. If parsing is delayed, the interface reveals progress and offers the filter panel as a fallback. The raw sentence is preserved either way; exact timing thresholds require engineering validation.

13 · UI foundation

The system underneath

The module inherits an Untitled UI foundation: neutral ramp, radii, type scale and input primitives. On top of it sits a shared status component reused across all seven modules, with each domain supplying its own controlled vocabulary. What follows is the part of that system this module actually uses.

The foundation specimens: the neutral ramp and accent, the five-size Inter type scale, and the status vocabulary in three families.
01

Typeface

Inter throughout, five sizes: 24 for page titles and metric values, 16 for section intros and card titles, 14 for table rows and body, 12 for secondary values and captions, 11 for column headers and micro labels.

02

Neutral ramp

Untitled UI greys from #101828 ink to #f2f4f7 surface, with #eaecf0 as the single table and panel rule.

03

Accent

#1a56db for action and selection. A blue to purple gradient is reserved for hero metrics so emphasis stays scarce.

04

Status vocabulary

The account family: New, Onboarding, Ongoing, Not passed, Expired, Closed, Refunded. The badge component and its colour rules are shared; each domain supplies its own vocabulary. Colour reinforces the text label and never carries meaning alone.

05

Table primitive

One table serves a twelve-column user list, a payout queue and a per-row error log, with shared sort, hover, pagination and export.

06

Density

Optimised for high-density desktop workflows, with compact rows and WCAG AA text contrast.


Accessibility · designed spec, not yet audited
AgTable text17.75 : 1 · AA AgSecondary text7.69 : 1 · AA AgAccent on white6.18 : 1 · AA AgWhite on accent6.18 : 1 · AA AgLowest status-badge contrast5.4 : 1 · AA AgLowest alert-badge contrast6.05 : 1 · AA
Focus state

Every interactive element carries a 2-pixel #1a56db ring at a 2-pixel offset. Focus is never removed, only styled.

Keyboard

The table uses a roving tab index: arrow keys move row focus, Enter opens the row, Escape returns to the list. The command bar opens with ⌘K on macOS or Ctrl+K on Windows and closes with Escape, returning focus to its origin.

Screen reader

Status is never colour alone: every badge carries its text label. The parse chips announce as a list, each with its token type: status New, type Student.

Table semantics

Column headers are real headers with sort state announced. The result count is a live region, so 1,284 results is spoken when a filter lands.

Reduced motion

The bar and drawer use 150-millisecond fades, replaced by instant transitions when reduced motion is requested. Nothing meaningful is carried by animation alone.

Contrast ratios above are computed from the actual palette values. Everything else on this card is designed behaviour that an audit would need to confirm in the build.


One component, six states · primary button
The primary button in six states: default, hover, focus, disabled, loading and pressed.
How the foundation was maintained

Four designers worked across seven modules in parallel, with the foundation shared between them. I led the module documented here; the other designers carried the remaining six. Any module-specific need either had to fit the shared system or justify changing it for everyone, keeping the platform coherent without erasing necessary domain differences.

14 · What this demonstrates

Structural properties, not measured outcomes

Two outcomes were measured after rollout: time to reach the target set and the number of context switches. Everything else below is a structural property of the designed screens, checkable by reading them.

Summary layer0 → 5metric cardsOriginal → Phase 2
Revealing filtersRequired → Noneinteraction before filteringFirst iteration → Phase 2
Filter visibility0 → 100%of active filters on screenFirst iteration → Phase 2
Visible filter fields0 → 7filter fields visible by defaultOriginal → Phase 2

Measured after rollout
Time to reach the target set25% fasterMeasured after rollout, not a projection.
Context switches50% fewerMeasured after rollout, not a projection.

The instrument, resolved
20,212Current dataset shown
Recall a nameknown question
Type a sentencenew question
Set the controlsfull precision
One editable viewsaveable · shareable · the same across all routes
Decide

Three input methods, one editable destination. The first and last steps do not change; the product shortens the step between them.


What changed, in one line each
Query lifetimeSession bound, lost on navigationPersistent, held by the view
Saved objectNone existsA named filter with an owner
Metric stripFixed set, identical for allAdd, remove and reorder in place
Entry routesOne, the filter panelThree, all to one editable view
Interpretation visibilityNo parse shownParse shown before execution

What should be measured next
Query completion rate Chip correction rate Misparse rate Saved filter reuse Recovery from a wrong parse Filtered scope for the metric strip

Two measures moved; the rest of this list is still open. What the redesign establishes either way is the system required to test it: persistent queries, inspectable interpretation, and one editable destination.