https://github.com/oscarrc/crust
Don't throw the crust. An opinionated, crisp, and zero-waste toast library built natively for Astro and React.
https://github.com/oscarrc/crust
astro astrojs react reactjs toast toast-notifications
Last synced: 2 days ago
JSON representation
Don't throw the crust. An opinionated, crisp, and zero-waste toast library built natively for Astro and React.
- Host: GitHub
- URL: https://github.com/oscarrc/crust
- Owner: oscarrc
- License: mit
- Created: 2026-06-06T21:56:37.000Z (10 days ago)
- Default Branch: main
- Last Pushed: 2026-06-06T22:50:51.000Z (10 days ago)
- Last Synced: 2026-06-07T00:05:09.234Z (10 days ago)
- Topics: astro, astrojs, react, reactjs, toast, toast-notifications
- Language: TypeScript
- Homepage: http://crust.oscarrc.me/
- Size: 161 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# π Crust
[](https://www.npmjs.com/package/@oscarrc/crust)
[](https://github.com/oscarrc/crust/actions/workflows/ci.yml)
[](./LICENSE)
Don't throw the crust. An opinionated, crisp, and zero-waste toast library built natively for Astro and React.
Most toast libraries are bloated white bread. They force you into wrapper fatigue, endless configuration files, and a hard React dependency just to slide a notification onto the screen.
**Crust is different.** The renderer is vanilla DOM β a React-free Astro site is a first-class citizen, and React gets a thin, concurrent-safe bridge on top. Warm matte surfaces, a capsule that grows into a card as one continuous surface, and rock-solid defaults. Take it or leave it β just like the crust.
**[Docs & playground β](https://crust.oscarrc.me)**
---
## Why Crust?
- π **Astro-first, honestly.** The core renders with plain DOM. No React island required to *show* toasts β React is an optional peer dependency.
- π« **One shared store.** Trigger from an Astro ``, a React island, or anywhere else: same toaster, same stack, no provider, no context.
- π₯ **Crisp & opinionated.** A tactile morph-expand interaction and an organic motion profile (ease-out-quint, nothing over 320ms, zero bounce). No spending 40 minutes tweaking cubic-bΓ©ziers.
- βΏ **Accessible by default.** `aria-live` region, keyboard-reachable dismiss, timers that pause while you read, and `prefers-reduced-motion` as a first-class theme.
- π¦ **Zero-waste footprint.** ESM-only, ~2 KB of JS, one CSS file, no dependencies.
## Quickstart
Install the package:
```bash
pnpm add @oscarrc/crust
```
Import the styles and mount the toaster once, at the root of your layout β no React, no provider:
```ts
import '@oscarrc/crust/styles.css';
import { mountToaster } from '@oscarrc/crust/vanilla';
mountToaster(); // bottom-right by default
```
Then bake toasts from anywhere:
```ts
import { toast } from '@oscarrc/crust/vanilla';
toast.success('Fresh bread out of the oven!');
// A message makes a toast expandable β it morphs open on hover/focus/tap,
// or on its own with `expandAfter`:
toast('Order update', {
message: 'Your order shipped today.',
expandAfter: 2000 // auto-expands 2s after becoming visible
});
// Async flows: loading β success/error, opening the outcome by itself:
toast.promise(saveDraft(), {
loading: 'Savingβ¦',
success: (draft) => ({ title: 'Saved', message: `β${draft.name}β is safe.` }),
error: 'Save failed'
}, { expandOnSettle: true });
```
That's the whole setup. For React islands, view transitions, theming, and the rest, read on β or head to the **[docs & playground](https://crust.oscarrc.me)**.
## Usage
### 1. Pure Astro / vanilla JS β zero React
```astro
---
// src/layouts/Layout.astro
import '@oscarrc/crust/styles.css';
---
<html>
<body>
<slot />
<script>
import { mountToaster } from '@oscarrc/crust/vanilla';
mountToaster();