@justeattakeaway/pie-css
Version:
A styling library that provides both a shared collection of ready to use CSS styles to be used across JET web front-ends, and SCSS-based style helpers for our PIE Web Component library.
261 lines (190 loc) • 9.91 kB
Markdown
# PIE CSS Button Component Styles
[Source Code](https://github.com/justeattakeaway/pie/tree/main/packages/tools/pie-css) | [NPM Package](https://www.npmjs.com/package/@justeattakeaway/pie-css)
Style static HTML elements (such as `<div>`s) with PIE button design system styling. This is intended for non-interactive elements that need to visually resemble a button.
> **Important:** This is an extremely niche use case. Almost all consumers should use the [`pie-button`](https://webc.pie.design/?path=/docs/components-button--docs) web component instead, which provides full interactivity, keyboard navigation, form integration and accessibility out of the box. These CSS-only styles exist solely for rare situations where a **static, non-interactive element** needs to _look_ like a button — for example, a `<div>` inside a clickable card or banner where the parent element handles the interaction. If you are unsure whether you need this, please reach out to the Design System team via **#help-designsystem**.
## Table of Contents
- [When to Use This (and When Not To)](#when-to-use-this-and-when-not-to)
- [Installation](#installation)
- [Importing](#importing)
- [Basic Usage](#basic-usage)
- [Available Classes](#available-classes)
- [Sizes](#sizes)
- [Variants](#variants)
- [Modifiers](#modifiers)
- [Icons](#icons)
- [Accessibility](#accessibility)
## When to Use This (and When Not To)
**Do NOT use these CSS classes if:**
- You need a clickable button — use `pie-button`
- You need a link styled as a button — use `pie-button` with the `tag="a"` prop
- You need form submission — use `pie-button` with `type="submit"`
- You are building any interactive control
**Use these CSS classes only if:**
- You need a static, non-interactive element (like a `<div>`) to visually match a PIE button
- The element sits inside a parent that already handles the interaction (e.g. an `<a>` tag wrapping a banner ad)
- You have confirmed with the Design System team that this is the correct approach for your use case
## Installation
The button component styles are included as part of the `@justeattakeaway/pie-css` package:
```bash
# Using Yarn
yarn add @justeattakeaway/pie-css
# Using NPM
npm install @justeattakeaway/pie-css
```
## Importing
### CSS Import (JavaScript/Framework)
Import the pre-compiled CSS file in your JavaScript/TypeScript application:
```javascript
import '@justeattakeaway/pie-css/dist/components/button.css';
```
**React Example:**
```jsx
import '@justeattakeaway/pie-css/dist/components/button.css';
function MyCard() {
return (
<div className="c-button c-button--primary c-button--medium">
Click me
</div>
);
}
```
**Vue Example:**
```html
<script setup>
import '@justeattakeaway/pie-css/dist/components/button.css';
</script>
<template>
<div class="c-button c-button--primary c-button--medium">
Click me
</div>
</template>
```
## Basic Usage
Apply the `c-button` class along with variant and size modifiers to a static element.
```html
<!-- Primary button, medium size -->
<div class="c-button c-button--primary c-button--medium">
Button label
</div>
<!-- Secondary button, small productive size -->
<div class="c-button c-button--secondary c-button--small-productive">
Button label
</div>
<!-- Disabled state -->
<div class="c-button c-button--primary c-button--medium is-disabled">
Disabled
</div>
<!-- Full width -->
<div class="c-button c-button--primary c-button--medium c-button--fullWidth">
Full width
</div>
```
## Available Classes
### Base
| Class | Description |
|-------|-------------|
| `.c-button` | Base button layout, typography and custom properties. |
### Variants
| Class | Description |
|-------|-------------|
| `.c-button--primary` | Primary brand colour background |
| `.c-button--primary-alternative` | Primary alternative colour background |
| `.c-button--primary-alternative-dark` | Primary alternative dark colour background |
| `.c-button--secondary` | Secondary colour background |
| `.c-button--outline` | Transparent background with border |
| `.c-button--ghost` | Transparent background, no border |
| `.c-button--ghost-dark` | Transparent background, dark text |
| `.c-button--inverse` | Inverse colour background |
| `.c-button--ghost-inverse` | Transparent background, light text |
| `.c-button--outline-inverse` | Transparent background with border, light text |
| `.c-button--ghost-inverse-light` | Transparent background, light solid text |
| `.c-button--destructive` | Error/destructive colour background |
| `.c-button--destructive-ghost` | Transparent background, error text |
### Sizes
| Class | Description |
|-------|-------------|
| `.c-button--xsmall` | Extra small button |
| `.c-button--small-productive` | Small productive button |
| `.c-button--small-expressive` | Small expressive button |
| `.c-button--medium` | Medium button |
| `.c-button--large` | Large button |
### Modifiers
| Class | Description |
|-------|-------------|
| `.is-disabled` | Disabled appearance (cursor: not-allowed, pointer-events: none) |
| `.c-button--fullWidth` | Makes the button span 100% of its container |
| `.c-button--truncate` | Truncates the label with an ellipsis when text overflows the button's width |
| `.c-button--responsive` | Enables responsive size bumping at wider viewports |
| `.c-button--expressive` | Used with `--responsive` to prefer expressive sizing at wider viewports |
## Sizes
Each size sets the font size, line height, padding and icon size for the button.
| Size | Font | Icon Size | Responsive Bump |
|------|------|-----------|-----------------|
| `xsmall` | Interactive XS | 16px | small-productive (or small-expressive with `--expressive`) |
| `small-productive` | Interactive S | 20px | medium |
| `small-expressive` | Interactive L | 20px | medium |
| `medium` | Interactive L | 24px | large |
| `large` | Interactive L | 24px | No change |
### Responsive Behaviour
Add `.c-button--responsive` to enable automatic size bumping at viewports wider than 768px. By default the xsmall size bumps to small-productive; add `.c-button--expressive` to bump to small-expressive instead.
```html
<!-- Responsive: xsmall → small-productive at wide viewports -->
<div class="c-button c-button--primary c-button--xsmall c-button--responsive">
Responsive
</div>
<!-- Responsive + Expressive: xsmall → small-expressive at wide viewports -->
<div class="c-button c-button--primary c-button--xsmall c-button--responsive c-button--expressive">
Expressive
</div>
```
## Variants
All 13 variants are supported. Each sets the background colour, text colour and interactive hover/active states.
The `primary` variant includes special handling for `xsmall` and `small-productive` sizes, which use different colour tokens to ensure text remains accessible at smaller sizes.
Outline variants (`outline`, `outline-inverse`) include a 1px border and automatically offset vertical padding by 1px to maintain consistent overall height.
## Modifiers
### Disabled
The disabled modifier uses class-based selectors (`.is-disabled`) rather than the `:disabled` pseudo-class, because these CSS classes target non-interactive elements where `:disabled` is not applicable.
```html
<div class="c-button c-button--primary c-button--medium is-disabled">
Disabled
</div>
```
### Full Width
```html
<div class="c-button c-button--primary c-button--medium c-button--fullWidth">
Full Width Button
</div>
```
### Truncate
Add `.c-button--truncate` to truncate the button label with an ellipsis when text overflows the button's width. When using this modifier, the label **must** be wrapped in a `<span>` element — `text-overflow: ellipsis` does not work directly on flex containers, so the inner `<span>` is required. The button's width must also be constrained externally (e.g. via `c-button--fullWidth` inside a sized container, or a `max-width` on a parent element). Buttons are `inline-flex` by default and will grow to fit their content, so truncation only takes effect when something limits the button's width.
```html
<!-- Constrain the parent to force truncation -->
<div style="max-width: 200px;">
<div class="c-button c-button--primary c-button--medium c-button--fullWidth c-button--truncate">
<span>This label is too long and will be truncated with an ellipsis</span>
</div>
</div>
```
## Icons
Icon sizing within CSS-only buttons is built exclusively for [`@justeattakeaway/pie-icons-webc`](https://www.npmjs.com/package/@justeattakeaway/pie-icons-webc). Other icon libraries, inline SVGs, or custom icon elements are **not supported** and may not size or align correctly. We will not be adding support for other icon solutions.
A button can contain only one icon, either **leading** (before the label) or **trailing** (after the label). The icon size is determined automatically by the button size class.
### Leading icon
Place the icon element **before** the label text:
```html
<div class="c-button c-button--primary c-button--medium">
<icon-plus-circle></icon-plus-circle>
Add item
</div>
```
### Trailing icon
Place the icon element **after** the label text:
```html
<div class="c-button c-button--primary c-button--medium">
Next
<icon-plus-circle></icon-plus-circle>
</div>
```
## Accessibility
These CSS classes are intended for **non-interactive, visual-only** elements. They do not add any interactive behaviour such as keyboard handling, ARIA roles, or focus management.
If you need an interactive button, **do not use these classes** — use the [`pie-button`](https://webc.pie.design/?path=/docs/components-button--docs) web component instead, which provides full keyboard navigation, ARIA attributes and screen reader support out of the box.
If you are unsure whether you need CSS-only button styles or the `pie-button` web component, reach out to the Design System team via **#help-designsystem**.