Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion src/components/api-method.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
import {
ArrowDownLeft,
ArrowUpRight,
Diff,
Eye,
ListChecks,
Repeat2,
Webhook,
X,
type LucideIcon,
} from 'lucide-react';

export const API_METHODS = [
'GET',
'POST',
Expand All @@ -11,20 +23,38 @@ export const API_METHODS = [

export type ApiMethod = (typeof API_METHODS)[number];

const methodIcons: Record<ApiMethod, LucideIcon> = {
GET: ArrowDownLeft,
POST: ArrowUpRight,
PUT: Repeat2,
PATCH: Diff,
DELETE: X,
HEAD: Eye,
OPTIONS: ListChecks,
WEBHOOK: Webhook,
};

export function parseApiMethod(value: unknown): ApiMethod | undefined {
if (typeof value !== 'string') return undefined;

const method = value.toUpperCase() as ApiMethod;
return API_METHODS.includes(method) ? method : undefined;
}

// The page tree holds one element for a method, and the sidebar and the
// previous and next cards each show a different part of it (app.css).
export function ApiMethod({ method }: { method: ApiMethod }) {
const Icon = methodIcons[method];

return (
<span
className={`marfa-api-method marfa-api-method--${method.toLowerCase()}`}
title={method === 'WEBHOOK' ? 'Webhook' : `${method} method`}
>
{method}
<span className="marfa-api-method-icon" aria-hidden="true">
<Icon />
</span>
<span className="marfa-api-method-label">{method}</span>
</span>
);
}
54 changes: 47 additions & 7 deletions src/styles/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -207,22 +207,45 @@
max-width: none;
}

/* A method label is the method in its colour, as text. In the sidebar it has
a fixed width, so every endpoint title starts in the same place. */
/* A method is its colour, as a small chip. The chip holds the method's icon
and its name, and each place shows one: the sidebar the icon, a previous or
next card the name. */
.fd-page-tree-item-name {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.8125rem; /* sidebar item text 1px smaller (14px → 13px) */
}
.marfa-api-method {
display: inline-block;
display: inline-flex;
height: 1.125rem;
flex: none;
align-items: center;
justify-content: center;
padding-inline: 0.25rem;
border: 1px solid color-mix(in oklab, currentColor 22%, transparent);
border-radius: 0.3rem;
background: color-mix(in oklab, currentColor 9%, transparent);
}
.marfa-api-method-icon {
display: none;
width: 0.75rem;
height: 0.75rem;
flex: 0 0 0.75rem;
align-items: center;
justify-content: center;
}
.marfa-api-method-label {
font-size: 0.625rem;
font-weight: 600;
line-height: 1.125rem;
line-height: 1;
letter-spacing: 0.01em;
}
.marfa-api-method-icon > svg {
width: 0.75rem;
height: 0.75rem;
stroke-width: 1.8;
}
.marfa-api-method--get {
color: var(--color-green-600);
}
Expand Down Expand Up @@ -272,15 +295,32 @@
color: var(--color-violet-400);
}

/* Operation names can wrap in the narrow sidebar, so the label stays at the
first line and has one width for every method. */
/* Operation names can wrap in the narrow sidebar, so the method there is the
icon alone, kept square at the first line. */
#nd-sidebar .fd-page-tree-item-name,
#nd-sidebar-mobile .fd-page-tree-item-name {
align-items: flex-start;
}
#nd-sidebar .marfa-api-method,
#nd-sidebar-mobile .marfa-api-method {
width: 3.5rem;
width: 1.125rem;
padding-inline: 0;
}
#nd-sidebar .marfa-api-method-icon,
#nd-sidebar-mobile .marfa-api-method-icon {
display: inline-flex;
}
#nd-sidebar .marfa-api-method-label,
#nd-sidebar-mobile .marfa-api-method-label {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}

/* Sidebar groups and selected-row fills already communicate hierarchy and
Expand Down
Loading