Skip to content

Iconography

Icons are rare on jsonresume.org: words do most of the work. When an icon helps (a download, a search, an external link), use Lucide outline icons at a 1.75 stroke, in the color of the text beside them.

Sizes

16px inline and in small controls, 20px in buttons and navigation, 24px on their own.

Sizes
16px
20px
24px
icons/sizes.tsx
import { Stack, Text } from '@jsonresume/ui';
import { FileJson, Github, Palette } from 'lucide-react';
import * as styles from './sizes.css';

// Three sizes, one stroke width. Icons take the color of their text.
export default function IconSizes() {
  return (
    <Stack gap={4}>
      {[16, 20, 24].map((size) => (
        <Stack key={size} direction="row" gap={4} align="center">
          <Text as="span" size="xs" tone="muted" className={styles.label}>
            {size}px
          </Text>
          <FileJson size={size} strokeWidth={1.75} aria-hidden="true" />
          <Palette size={size} strokeWidth={1.75} aria-hidden="true" />
          <Github size={size} strokeWidth={1.75} aria-hidden="true" />
        </Stack>
      ))}
    </Stack>
  );
}
icons/sizes.css.ts
import { style } from '@vanilla-extract/css';

export const label = style({ width: '3rem' });
SizeWhere
16pxInline with body text, badges, small buttons
20pxNavigation, standard controls
24pxEmpty states and standalone icons

In components

Inside a Button, icons scale with the label automatically (1em).

Buttons, icon buttons and links
jsonresume.org
Show code
icons/in-components.tsx
import { Button, Link, Stack, Tooltip } from '@jsonresume/ui';
import { Download, ExternalLink, Search } from 'lucide-react';
import * as styles from './in-components.css';

// Inside buttons, icons size to the label (1em). Icon-only buttons need an
// aria-label; a tooltip shows the same words to sighted users.
export default function IconsInComponents() {
  return (
    <Stack direction="row" gap={4} align="center" wrap>
      <Button variant="primary">
        <Download aria-hidden="true" /> Export PDF
      </Button>
      <Tooltip content="Search themes">
        <Button size="icon" aria-label="Search themes">
          <Search aria-hidden="true" />
        </Button>
      </Tooltip>
      <Link href="https://jsonresume.org" className={styles.iconLink}>
        jsonresume.org <ExternalLink size={14} aria-hidden="true" />
      </Link>
    </Stack>
  );
}
icons/in-components.css.ts
import { style } from '@vanilla-extract/css';

// Keep a trailing icon on the link's baseline and with its text.
export const iconLink = style({
  display: 'inline-flex',
  alignItems: 'center',
  gap: '0.3em',
});
usage
import { Download } from 'lucide-react';

<Button variant="primary">
  <Download aria-hidden="true" /> Export PDF
</Button>

Accessibility

  • Decorative icons next to text get aria-hidden="true".
  • Icon-only controls need an aria-label naming the action, plus a Tooltip with the same words.
  • Never use an icon alone to convey status; say it in words too.

Guidelines

Do

  • Use Lucide, outline style, strokeWidth 1.75.
  • Let icons inherit color from their text.
  • Pair icons with labels.

Don’t

  • Mix icon sets or filled and outline styles.
  • Color icons for decoration.
  • Use an icon where a word is clearer.