Gacela
Documentation version: 2.7.1
Colour theme

Facet

The design system this site is built from. Every swatch, size and component below is rendered from the tokens in src/design/tokens.css, so if a token breaks, it breaks here where somebody will see it.

Check this page in both themes before shipping a visual change.

Color

Color is authored in OKLCH and expressed with light-dark(), so the two themes are one palette at two lightness ranges rather than two stylesheets. Nothing outside tokens.css may contain a color literal.

The palette has one hue, 251, and it is the mark's own: #123456, the blue the gazelle is drawn in, measures oklch(0.3192 0.0725 251). Every surface and every ink is that color at another lightness, and --navy-700 is the brand value itself to the last decimal.

Surfaces

--canvasThe page itself
--surfaceCards and panels
--surface-sunkenCode, footer, wells
--surface-raisedDialogs and popovers
--surface-inverseBackdrops

Ink

--text-strongHeadings, emphasis
--textBody copy
--text-mutedLabels, captions
--borderVisible edges
--border-subtleHairline separators

Accent and semantics

The project's blue is the only accent, and it is deliberately rare: it marks the one thing on a screen that matters most, and nothing else. If two accent elements compete in a viewport, one of them is wrong.

The accent shares the ink's hue exactly, so it has only chroma to separate itself with: the ink ramp stays under 0.045 and the accent runs 0.11 to 0.15. That gap is what makes an active sidebar item read as active, and it is the reason the ink is kept as gray as it is.

--accentLinks, active state
--accent-washSelected backgrounds
--infoNote callouts
--warningWarning callouts
--dangerDanger callouts

Typography

Three faces, each with one job. Raleway carries display type, Heebo carries reading, and JetBrains Mono does every label on the site, which is what gives the pages their annotated, drawing-like quality.

--text-4xlOne door per module
--text-3xlSection heading
--text-2xlPage heading
--text-xlSubsection
--text-lgLede paragraph
--text-baseBody copy, the default
--text-mdSecondary copy
--text-2xsMono label

Space

A 4px grid that opens up as it climbs. Space encodes relatedness: less inside a group, more between groups.

1
2
3
4
5
6
7
8

Buttons

Primary Secondary Ghost Badge Accent badge

Version badge

Written inline in markdown as [since 1.9]. It marks the release a feature first appeared in, and it works inside a heading without touching the heading's id, the table of contents or the search index. The docs always describe the latest Gacela release; this badge is the whole of the versioning story between majors.

Cacheable methods Since 1.9

And mid-sentence: a feature Since 1.9 sits on the baseline without growing the line.

Version switcher and archive banner

The header's release pill becomes this dropdown once an archived docs line exists. It is a details element, so it works without JavaScript, and the pill it opens from is the same .badge the header always carried.

Every page of an archived line opens with this banner, linking to the page's current equivalent:

Callouts

Four kinds, distinguished by the color of the rail and by their label, never by color alone.

Card grid

Routes into a section, for a reader who has arrived without a destination. Cards take a column each while they fit and fall to one when they do not, so the same markup works in the documentation column and on a full-width page.

Index list

The workhorse of the marketing pages. A table of contents rather than a grid of cards, because a framework's feature set is a reference, and a reference should be scannable in one column pass. The arrow appears on hover and on focus; only the title takes the accent.

Stat row

A few figures that establish scale before the prose about them starts. Three or four entries is the useful range; past that a table reads better.

17+application modules
PHP 8.4declared platform
MITopen-source license

Video

A self-hosted poster that links to the video. Nothing loads from YouTube until the reader presses play; then the link becomes a no-cookie player in the same frame. Without JavaScript it opens the video on YouTube.

Play video: Gacela in 60 seconds

Code

A framed block with a mono caption bar rather than a filled slab, so a page of documentation does not become a stack of gray rectangles. The syntax palette is part of the design system, and it deliberately avoids the accent: keywords sit on the navy ramp, strings on teal, functions on violet and constants on amber. A hundred accent-colored keywords on a page would leave nothing for the eight marks that carry real signal.

src/Checkout/Facade.phpphp
namespace App\Checkout;

use Gacela\Framework\AbstractFacade;

/**
 * @method Factory getFactory()
 */
final class Facade extends AbstractFacade
{
    public function placeOrder(Basket $basket): OrderId
    {
        return $this->getFactory()
            ->createOrderPlacer()
            ->place($basket);
    }
}

A block with no caption shows only its language:

composer require gacela-project/gacela

Parallel files become tabs. The tabs are radio inputs and labels, so they switch with no JavaScript at all:

final class Facade extends AbstractFacade
{
}
final class Factory extends AbstractFactory
{
}

A recorded terminal session uses the same frame. The caption links to the exact source the output came from, the prompt is not selectable, and the pass and warning marks keep their glyphs, so colour only backs them up. A line holding only an ellipsis marks what an excerpt leaves out.

TerminalOutput recorded at phel-lang@eea8d09
vendor/bin/gacela doctor
…
✓ class filenames
    every pillar class matches its filename
⚠ Doctor finished with warnings

Prose

Lists

  • Modules interact with each other only via their Facade
  • The Factory manages the intra-dependencies of the module
  • The Provider resolves the extra-dependencies of the module
  1. Install the package
  2. Create the four classes
  3. Bootstrap Gacela at your entry point

Tables

Hairline rules only. A filled header band would out-shout the headings around it.

Class File Responsibility
Facade Facade.php The entry point, and the only public surface
Factory Factory.php Creates the module's own services
Provider Provider.php Resolves dependencies from other modules
Config Config.php Reads the project's configuration

Quotes

The Facade is the entry point of your module.

Documentation furniture

Two components every documentation page carries. The pager closes the page with its neighbours in reading order; the inline table of contents is the same list as the sidebar TOC, folded into a disclosure for the widths where the sidebar is gone.

The disclosure below is therefore only visible under 1180px, which is the point the sidebar TOC takes over. Narrow the window to review it.

On this page

Internal links such as the Factory sit in the accent color. External links such as Packagist (opens in a new tab) look the same, but they open in a new tab and say so: they carry target="_blank", rel="noreferrer", and a visually hidden "(opens in a new tab)" so the announcement is not left to sighted users alone.