npm package: @minimall.io/astro-primitives
Description: Astro primitives inspired by Radix UI Themes
Author: minimall.io
Latest version: 0.0.2

# Astro primitives inspired by Radix UI Themes

## Table of Contents

- [Installation](#installation)
- [Breakpoints](#breakpoints)
- [Responsive Variants](#responsive-variants)
- [Box](#box)
- [Container](#container)
- [Divider](#divider)
- [Flex](#flex)
- [Grid](#grid)
- [Heading](#heading)
- [Link](#link)
- [SVG](#svg)
- [Text](#text)

## Installation

```bash
npm install @minimall.io/astro-primitives
```

## Breakpoints

Components with responsive variants (Box, Container, Flex, Grid, Heading, Link, SVG, Text) use the following `min-width` breakpoints:

| Variant | Breakpoint |
|---------|------------|
| XS      | 520px      |
| SM      | 768px      |
| MD      | 1024px     |
| LG      | 1280px     |
| XL      | 1640px     |

For example, `pMD="6"` applies padding 6 from the 1024px viewport and up; `sizeXS="3"` applies size 3 from the 520px viewport and up.

## Responsive Variants

Components that support responsive behavior follow a consistent naming convention. For any base prop `prop`, the responsive variants are:

- `propXS` — applies at the XS breakpoint (520px) and up
- `propSM` — applies at the SM breakpoint (768px) and up
- `propMD` — applies at the MD breakpoint (1024px) and up
- `propLG` — applies at the LG breakpoint (1280px) and up
- `propXL` — applies at the XL breakpoint (1640px) and up

The base prop (e.g., `size`, `p`, `gap`) sets the default value; responsive variants override it at their respective breakpoints. For example, `size="3"` with `sizeMD="5"` renders size 3 below 1024px and size 5 from 1024px upward.

## Box

A layout primitive for applying responsive padding. Renders as a semantic HTML element (`header`, `main`, `footer`, `section`, `nav`, `div`, or `li`) with configurable padding using a spacing scale (0–9). The following props support responsive variants: `p`, `px`, `py`, `pt`, `pr`, `pb`, and `pl`.

**Interface**

```typescript
interface Props {
  id?: string;
  as?: 'header' | 'main' | 'footer' | 'section' | 'nav' | 'div' | 'li';

  p?: Spacing;   // all sides
  px?: Spacing;  // horizontal
  py?: Spacing;  // vertical
  pt?: Spacing;  // top
  pr?: Spacing;  // right
  pb?: Spacing;  // bottom
  pl?: Spacing;  // left
  // Responsive variants: p, px, py, pt, pr, pb, pl
}

// Spacing: 0=0px, 1=8px, 2=12px, 3=16px, 4=24px, 5=32px, 6=48px, 7=64px, 8=96px, 9=128px
type Spacing = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
```

**Usage**

```astro
---
import Box from '@minimall.io/astro-primitives/Box';
---

<Box as="section" p="4" pMD="6">
  <p>Content with responsive padding</p>
</Box>
```

## Container

A centered layout container with a `max-width`. Constrains content width and centers it horizontally. The following props support responsive variants: `size`.

**Interface**

```typescript
interface Props {
  id?: string;
  size?: '1' | '2' | '3' | '4';
  // Responsive variants: size
}
// size: 1=448px, 2=688px, 3=880px, 4=1136px
```

**Usage**

```astro
---
import Container from '@minimall.io/astro-primitives/Container';
---

<Container size="3" sizeMD="4">
  <p>Centered content with max-width</p>
</Container>
```

## Divider

A horizontal rule for separating content. Renders an `<hr>` with optional custom border `color`. No responsive variants.

**Interface**

```typescript
interface Props {
  id?: string;
  color?: string;  // CSS color value (default: currentColor)
}
```

**Usage**

```astro
---
import Divider from '@minimall.io/astro-primitives/Divider';
---

<section>
  <p>First section</p>
  <Divider color="var(--gray-6)" />
  <p>Second section</p>
</section>
```

## Flex

A flexbox layout primitive. Renders as `div`, `ul`, or `ol`. The following props support responsive variants: `direction`, `wrap`, `gap`, `justifyContent`, `alignItems`, and `alignContent`.

**Interface**

```typescript
interface Props {
  id?: string;
  as?: 'div' | 'ul' | 'ol';

  direction?: 'row' | 'column';
  wrap?: 'wrap' | 'nowrap';
  gap?: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
  justifyContent?: 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly';
  alignItems?: 'start' | 'end' | 'center' | 'stretch';
  alignContent?: 'start' | 'end' | 'center' | 'stretch' | 'between' | 'around' | 'evenly';
  // Responsive variants: direction, wrap, gap, justifyContent, alignItems, alignContent
}
// Gap: 0=0px, 1=8px, 2=12px, 3=16px, 4=24px, 5=32px, 6=48px, 7=64px, 8=96px, 9=128px
```

**Usage**

```astro
---
import Flex from '@minimall.io/astro-primitives/Flex';
---

<Flex direction="row" directionMD="column" gap="3" justifyContent="between" alignItems="center">
  <span>Item 1</span>
  <span>Item 2</span>
</Flex>
```

## Grid

A CSS Grid layout primitive. Renders as `div`, `ul`, or `ol`. The following props support responsive variants: `gap`, `columns`, `rows`, `flow`, `justifyItems`, `alignItems`, `justifyContent`, `alignContent`, `minColWidth`, `minRowHeight`, `columnsSizing`, and `rowsSizing`.

**Interface**

```typescript
interface Props {
  id?: string;
  as?: 'div' | 'ul' | 'ol';

  gap?: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
  columns?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | 'fit' | 'fill';
  rows?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12';
  flow?: 'row' | 'column' | 'dense' | 'row-dense' | 'column-dense';
  justifyItems?: 'start' | 'end' | 'center' | 'stretch';
  alignItems?: 'start' | 'end' | 'center' | 'stretch';
  justifyContent?: 'start' | 'end' | 'center' | 'stretch' | 'between' | 'around' | 'evenly';
  alignContent?: 'start' | 'end' | 'center' | 'stretch' | 'between' | 'around' | 'evenly';
  minColWidth?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8';
  minRowHeight?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8';
  columnsSizing?: 'auto' | 'equal';
  rowsSizing?: 'auto' | 'equal';
  // Responsive variants: gap, columns, rows, flow, justifyItems, alignItems, justifyContent, alignContent, minColWidth, minRowHeight, columnsSizing, rowsSizing
}
// Gap: 0=0px, 1=8px, 2=12px, 3=16px, 4=24px, 5=32px, 6=48px, 7=64px, 8=96px, 9=128px
// minColWidth, minRowHeight: 1=160px, 2=180px, 3=200px, 4=240px, 5=260px, 6=280px, 7=320px, 8=360px
```

**Usage**

```astro
---
import Grid from '@minimall.io/astro-primitives/Grid';
---

<Grid columns="3" columnsMD="6" gap="4" minColWidth="5">
  <div>Card 1</div>
  <div>Card 2</div>
  <div>Card 3</div>
</Grid>
```

## Heading

A typography primitive for headings. Renders as `h1`–`h6` with configurable `size`, `weight`, `align`, `wrap`, `trim`, `truncate`, and `color`. The following props support responsive variants: `size`, `weight`, `align`, `wrap`, `trim`, and `truncate`.

**Interface**

```typescript
interface Props {
  id?: string;
  as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';

  size?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
  weight?: 'light' | 'regular' | 'medium' | 'bold';
  align?: 'left' | 'center' | 'right';
  wrap?: 'balance' | 'nowrap' | 'pretty' | 'stable' | 'wrap';
  trim?: 'normal' | 'start' | 'end' | 'both';
  truncate?: boolean;
  color?: string;
  // Responsive variants: size, weight, align, wrap, trim, truncate
}
// size (font-size): 1=12px, 2=14px, 3=16px, 4=18px, 5=20px, 6=24px, 7=28px, 8=35px, 9=60px
// weight (font-weight): light=300, regular=400, medium=500, bold=700
```

**Usage**

```astro
---
import Heading from '@minimall.io/astro-primitives/Heading';
---

<Heading as="h1" size="8" sizeMD="9" weight="bold" align="center">
  Page Title
</Heading>
```

## Link

A styled anchor link with typography options. The following props support responsive variants: `size`, `weight`, `align`, `wrap`, `trim`, and `truncate`. Automatically adds `rel="noopener noreferrer"` when `target="_blank"`.

**Interface**

```typescript
interface Props {
  id?: string;

  href: string;
  target?: '_self' | '_blank';
  rel?: string;

  size?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
  weight?: 'light' | 'regular' | 'medium' | 'bold';
  align?: 'left' | 'center' | 'right';
  wrap?: 'balance' | 'nowrap' | 'pretty' | 'stable' | 'wrap';
  trim?: 'normal' | 'start' | 'end' | 'both';
  truncate?: boolean;
  color?: string;
  // Responsive variants: size, weight, align, wrap, trim, truncate
}
// size (font-size): 1=12px, 2=14px, 3=16px, 4=18px, 5=20px, 6=24px, 7=28px, 8=35px, 9=60px
// weight (font-weight): light=300, regular=400, medium=500, bold=700
```

**Usage**

```astro
---
import Link from '@minimall.io/astro-primitives/Link';
---

<Link href="/about" size="4" weight="medium">
  Learn more
</Link>

<Link href="https://example.com" target="_blank">
  External link
</Link>
```

## SVG

A wrapper for SVG components. Accepts an Astro SVG component via the `as` prop. The following props support responsive variants: `width` and `height`. Supports accessibility with optional `label` for `aria-label` or `aria-hidden` when decorative.

**Interface**

```typescript
interface Props {
  id?: string;
  as: SvgComponent;  // Astro SVG component
  label?: string;   // For aria-label (role="img")
  style?: Record<string, string>;

  width?: string;   // CSS length (e.g. "24px", "1em")
  height?: string;  // CSS length (e.g. "24px", "1em")
  // Responsive variants: width, height
}
```

**Usage**

```astro
---
import SVG from '@minimall.io/astro-primitives/SVG';
import Icon from '../assets/icon.svg';
---

<SVG as={Icon} width="24px" height="24px" label="Settings" />

<SVG as={Icon} width="1em" widthMD="1.5em" />
```

## Text

A typography primitive for body text and spans. Renders as `p` or `span` with configurable `size`, `weight`, `align`, `wrap`, `trim`, `truncate`, and `color`. The following props support responsive variants: `size`, `weight`, `align`, `wrap`, `trim`, and `truncate`.

**Interface**

```typescript
interface Props {
  id?: string;
  as?: 'p' | 'span';

  size?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
  weight?: 'light' | 'regular' | 'medium' | 'bold';
  align?: 'left' | 'center' | 'right';
  wrap?: 'balance' | 'nowrap' | 'pretty' | 'stable' | 'wrap';
  trim?: 'normal' | 'start' | 'end' | 'both';
  truncate?: boolean;
  color?: string;
  // Responsive variants: size, weight, align, wrap, trim, truncate
}
// size (font-size): 1=12px, 2=14px, 3=16px, 4=18px, 5=20px, 6=24px, 7=28px, 8=35px, 9=60px
// weight (font-weight): light=300, regular=400, medium=500, bold=700
```

**Usage**

```astro
---
import Text from '@minimall.io/astro-primitives/Text';
---

<Text as="p" size="3" sizeMD="4" weight="regular">
  Body paragraph text with responsive sizing.
</Text>

<Text as="span" size="2" color="var(--gray-11)">
  Inline text
</Text>
```