One button set with variants
Button
One component set with Variant, State and Size. Teams pick a combination, so nobody copies a button and changes it.
The short version
Ten years designing software people use all day at work: loan back-offices, support tools, data-heavy CRM lists and checkouts across four countries. I also build working prototypes, so teams can test the design before anyone writes a ticket.
I'm Rock, a Senior Product Designer based in Tallinn, open to contract and full-time projects.
I design the screens, build the tokens and components behind them, and ship a version the team can click through before anyone writes a ticket.
Users duplicate a list just to filter it in different ways. Then the copies stop matching.
Let's keep one list and save the filter as a view on top of it. Like this.
Does a view copy the companies, or only store the filter?
Only the filter. The list stays the source of truth, so a view never drifts.
filter-builder Public
Fieldset. A filter builder over 50,000 rows that never loses your work.
karaoke-os Public
Karaoke OS. A song list for karaoke bars that you can search on your phone.
moving-out-webapp Public
MoveOutSale. Sell a flat’s worth of furniture when you move.
portfolio-presentation-template Public
A scroll-driven case-study page with live prototypes.
10years
Designing tools people use all day at work: loan back-offices, CRM integrations, sales data and support tools.
3design systems
Two built from zero at Inbank and Bigbank, one rebuilt at Well. Tokens, components and docs that teams use.
170+countries
Pipedrive is used in 170+ countries. At Bigbank I designed for 7 markets, and the Inbank checkout runs in 4.
7live demos
Prototypes and products I built and shipped in code, from case study recreations to side projects.
client work and experiments in one list · filter with the tags on the left
One landing page for two readers, with a switch between them. Built on tokens and shipped as a working prototype.
Landing page, Education landing-pageeducation
Added AI that answers the questions salespeople were answering by hand. Shipped in two rounds within two weeks.
AI, SaaS aisaas + Open live demo Live demo
Saved views inside one list, each with its own filters and columns, so people do not need to make a new list.
Data, SaaS datasaas + Open live demo Live demo
Rebuilt the internal support tool from scratch for new hire-purchase products.
Back-office, Fintech back-officefintech
Redesigned an outdated checkout across 4 countries. Fewer support tickets, faster completion.
Loan application, Fintech loan-applicationfintech
A floating window that lets integrations, like calling apps, work inside Pipedrive.
Integrations, SaaS integrationssaas
Act on a third-party app or a piece of data where it shows in Pipedrive.
Integrations, SaaS integrationssaas
Where developers create and manage app extensions, in the Pipedrive Marketplace Manager.
Integrations, SaaS integrationssaas
Redesigned loan application flows for a better experience and a modern look.
Loan application, Fintech loan-applicationfintech
A system made for the bank's accountants, built in-house.
Back-office, Fintech back-officefintech
A filter builder over 50,000 rows. It keeps your edits, and it asks you before it changes what you selected.
Data data
The karaoke bar's QR code opened a PDF with thousands of songs. I built a song list you can search.
Code code
A marketplace for selling the furniture from a whole flat when you move. Built with Next.js and Supabase.
Code code
A case study page that moves as you scroll. Chapter cards zoom open into full-screen chapters with working prototypes.
Code code
No projects match all of these.
Remove a filter to see more.
Section / Design systems
two built from zero, one rebuilt · this page uses a fourth
I have built design systems from scratch at Inbank and Bigbank, and rebuilt one at Well. Dev teams used each one in live products, on real deadlines.
Most of the work is in the logic under the UI kit: how tokens are layered, how components are split, which properties exist, and what happens when the brand or the theme changes.
Inbank DS
Bigbank DS
Well DS
how I build them
Button
One component set with Variant, State and Size. Teams pick a combination, so nobody copies a button and changes it.
Button
Button
Variant
State
Size
Show icon
Icon
Text, boolean and instance-swap properties handle small changes. I use variants only for real visual changes, so the set stays small.
blue.600→color.action.primary→button.bg
grey.050→color.text.primary→h1, row title
red.400→color.redline→pin, cursor
click the first swatch to rebrand the buttons above
Primitives hold the raw values. Semantic tokens say where each value is used. Components use only semantic tokens, so a rebrand changes only tokens.
One set of components with a Dark and a Light mode. This page switches between them, and no frame is copied.
two built from zero, one rebuilt · this page uses a fourth
I have built design systems from scratch at Inbank and Bigbank, and rebuilt one at Well. Dev teams used each one in live products, on real deadlines. This page is the fourth: every story below renders the real components and tokens of rockgomes.com.
| System | Years | Scope |
|---|---|---|
| Inbank | 2023 - 2025 | Built from scratch right after the rebrand. One system for checkout in four countries and the back-office. |
| Bigbank | 2016 - 2020 | Built with one other designer. A component library in code, used directly in the product. |
| Well | Contract | Rebuilt the back-office design system. Colour tokens updated to meet AAA contrast. |
<a class="btn" href="#">Button</a>
<a class="btn btn-primary" href="#">Button</a>One component with Style and State. The same names are in base.css: .btn and .btn-primary.
--color-surface-page--color-text-primary--color-text-secondary--color-annotation-measure--color-annotation-redline--color-status-positive.btn-primary {
background: var(--color-annotation-measure);
}Figma variables are exported to tokens.css with the same names, so the spec and the code use the same tokens.
<html data-view="engineer" data-theme="dark">This switch changes the theme of this page. Only the token values change.
<span class="pill pill-customer"><i></i>Customer</span>One component with a Status property that has four values.
Every colour is a variable in the Figma tokens collection, exported to tokens.css with the same name. The values below are read from this page right now, in Light - Dev.
--color-surface-page--color-surface-raised--color-surface-sunken--color-surface-stage--color-text-primary--color-text-secondary--color-text-muted--color-text-accent--color-border-strong--color-border-subtle--color-border-control--color-annotation-measure--color-annotation-measure-soft--color-annotation-redline--color-annotation-redline-soft--color-status-positive--color-status-positive-soft--color-status-negative-textOne set of components has six modes. The view switch sets data-view and the theme sets data-theme. Each pair picks one Figma mode, and only the token values change.
| View | data-view | Light | Dark |
|---|---|---|---|
| Designer | "design" | Light - Crisp | Dark |
| Recruiter | "recruiter" | Light - Recruiter | Dark - Recruiter |
| Engineer | "engineer" | Light - Dev | Dark - Dev |
:root[data-view="engineer"]:not([data-theme="dark"]) {
--color-annotation-measure: #097640;
}
:root[data-view="engineer"][data-theme="dark"] {
--color-annotation-measure: #3dd68c;
} Controls
| Name | Control |
|---|---|
| Label | |
| Style | |
| State |
One component set in Figma with Style and State, and a Label text property. In code it is one class, plus one more for Primary.
| Figma property | Values | In code |
|---|---|---|
| Label | text | element content |
| Style | Default, Primary | .btn, .btn-primary |
| State | Default, Hover, Focus | :hover, :focus-visible |
.btn {
border: 1px solid var(--color-border-strong);
border-radius: var(--radius-control);
}
.btn-primary {
background: var(--color-annotation-measure);
} Click an option, or use the arrow keys. This is the view switch from the header.
The view switch in the header. Each option is a radio button, so it works with the keyboard and screen readers.
| Option property | Values | In code |
|---|---|---|
| Label | text | button content |
| Selected | No, Yes | aria-checked |
| State | Default, Hover, Focus | :hover, :focus-visible |
<div class="ui-seg">
<button type="button" role="radio" aria-checked="true">Option</button>
<button type="button" role="radio" aria-checked="false">Option</button>
</div> Controls
| Name | Control |
|---|---|
| Status |
The status column in the filter table. One component with a Status property, one class per value in code.
.pill-lead { background: var(--color-surface-sunken); color: var(--color-text-secondary); }
.pill-trial { background: var(--color-annotation-redline-soft); color: var(--color-status-negative-text); }
.pill-customer { background: var(--color-status-positive-soft); color: var(--color-status-positive); }
.pill-churned { background: transparent; color: var(--color-text-muted); } 2016 → 2026
git log --graph --since=2016
Senior Product Designer · contract
I worked across the whole back-office, from onboarding new care homes to the care home structure, the medication cycles and all the other views staff use every day. I also helped on Direct to Patient, its public version. I rebuilt the design system and helped the front-end team implement it.
I worked on AI features, lists and data management, and user management. I took each one end to end, from testing ideas with sales teams to handoff to the developers, using AI for ideation and testing. I also designed the permissions and SSO the product needed for enterprise clients.
I work across the whole app experience. Right now I'm revamping the web version and growing and managing our design system. We use Claude heavily in our workflow, so I build the system with current best practices, so AI agents can read it too. I work closely with the other designers and developers to make sure we all follow the same patterns.
Senior Product Designer
I was Inbank's first in-house designer, so I owned design across the whole product: the hire-purchase flows in 4 countries, the customer service back-office, and a design system built from scratch. Today every market, online banking, partner channels and the back-office use it.
Senior Product Designer
I owned design for Integrations and Developer Experience. That means the app marketplace and the tools developers use to build apps for it. I set the patterns for how apps show and behave inside Pipedrive. I worked closely with PMs and developers, and with the business side on the roadmap, resources and goals.
Product Designer
In four years at Bigbank, I worked on both sides of lending: the loan application customers fill in, in 5 countries, and the back-office tools behind it. I also built the bank's first design system, with a coded component library.
subject annotated for completeness
file portrait.png
scene: mountain lake, morning hazedata-scene="mountain lake, morning haze"subject: Rockdata-subject="Rock"prop: one rock (fitting)data-prop="one rock (fitting)"mode: monochromedata-mode="monochrome" I am Rock. Senior product designer in Tallinn, Estonia. I have spent ten years on the kind of software people use all day at work: loan back-offices, support tools, CRM lists with 29,000 rows, checkouts that have to work in four countries.
I like the hard, boring parts: permissions, edge cases, tables that stay readable at 200 columns, and design systems that must keep working after a rebrand.
I also build working versions of what I design. I use AI tools a lot to turn a Figma file into a clickable version fast. Then I read the code, fix the tokens and the CSS, and give the team something they can test. I made the two Dealfront demos on this page this way.
Before this: Dealfront, Inbank, Pipedrive, Bigbank, and a back-office design system for a UK pharmacy group. Outside of work: photography, the gym, and small games.
Rock
Let's keep one list and save the filter as a view on top of it. Like this.