# Pressable

> A wrapper that gives any interactive child a consistent, cross-browser press animation — scale down on pointerdown/keydown, back to rest on release, with a static opacity fallback under reduced motion.

- Package: `fancy-ui-svelte` (Svelte 5 + Tailwind CSS v4)
- Category: Buttons
- Tags: press, tap, scale, haptic, animation, micro-interaction
- Types: `PressableProps`
- Docs: https://fancy-ui.rama.app/docs/components/pressable
- Source: https://github.com/RamaHerbin/fancy-ui/tree/main/src/lib/fancy-ui/pressable

## Import

```svelte
<script lang="ts">
  import { Pressable } from 'fancy-ui-svelte';
</script>
```

Setup (once per project): `npm install fancy-ui-svelte`, then add `@import "fancy-ui-svelte/tailwind.css";` after `@import "tailwindcss";` in your main CSS file. Full guide: https://fancy-ui.rama.app/llms.txt

React: `import { Pressable } from 'fancy-ui-react';` (`class` becomes `className`, snippets become `ReactNode`, DOM callbacks are camel-cased; exact names on https://fancy-ui.rama.app/docs/components/react/pressable.md).

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `scale` | `number` | `0.97` | Target scale() factor while pressed |
| `haptic` | `false \| "light" \| "medium" \| "heavy" \| "success" \| "error"` | `false` | Touch-only vibration pattern fired on pointerdown; false never vibrates |
| `disabled` | `boolean` | `false` | Suppresses every listener; data-pressed never appears |
| `class` | `string` | — | Additional CSS classes, merged onto the wrapper |
| `ref` | `HTMLDivElement \| null` | `null` | Bindable reference to the wrapper element |

## Snippets

| Snippet | Description |
| --- | --- |
| `children` | Exactly one interactive child (documented, not enforced at runtime) |

## Examples

### Basic Usage

```svelte
<script lang="ts">
	import { Pressable } from "fancy-ui-svelte";

	const REPLIES = ["Sounds good", "Not today", "Let's talk"];
</script>

<div class="flex w-full items-center justify-center p-6">
	<div class="border-border bg-card w-full max-w-[280px] rounded-[1.75rem] border p-4 shadow-sm">
		<p class="text-muted-foreground mb-3 text-xs">Quick replies</p>
		<div class="flex flex-wrap gap-2">
			{#each REPLIES as reply}
				<Pressable>
					<button
						type="button"
						class="border-border bg-muted text-foreground rounded-full border px-3.5 py-1.5 text-sm"
					>
						{reply}
					</button>
				</Pressable>
			{/each}
		</div>
		<p class="text-muted-foreground mt-4 text-xs">
			Tap a chip (or focus one and press Space/Enter) — it gives under the press, then settles back
			the instant you let go. With reduced motion it dims instead of shrinking.
		</p>
	</div>
</div>
```

### With Haptics

Touch-only vibration patterns alongside the press scale.

```svelte
<script lang="ts">
	import { Pressable } from "fancy-ui-svelte";
</script>

<div class="flex w-full flex-col items-center justify-center gap-4 p-6">
	<div class="flex flex-wrap items-center justify-center gap-3">
		<Pressable haptic="light">
			<button
				type="button"
				class="border-border bg-card text-foreground rounded-full border px-4 py-2 text-sm font-medium"
			>
				Like
			</button>
		</Pressable>
		<Pressable haptic="medium">
			<button
				type="button"
				class="bg-primary text-primary-foreground rounded-full px-4 py-2 text-sm font-medium"
			>
				Add to cart
			</button>
		</Pressable>
	</div>
	<p class="text-muted-foreground max-w-xs text-center text-xs">
		On a touch device each button also fires a short vibration on press — a lighter buzz for "Like",
		a stronger one for "Add to cart". <code class="text-xs">haptic</code> is touch-only and additive:
		on this desktop preview (and for mouse or pen everywhere) you'll only ever see the press-scale, exactly
		like BasicUsage.
	</p>
</div>
```
