# Open from a button

No grid, no scan, no collection. A button deals one card from a pool, weighted by rarity, and the reveal comes out of the button. This is the shape of a daily reward, a loot drop after a level, or a thank-you after a purchase.

> Live preview: see it play at https://bettertyped.github.io/react-cards-opening/docs/examples/open-from-a-button/
>
> The example below, with a card in place of the button so it has somewhere to land.

## The code

`daily-card.tsx`

```tsx
import { rollCards, useCardOpening } from "@react-cards-opening/core";
import { CardOpening } from "@react-cards-opening/ui";
import { useRef, useState } from "react";
import "@react-cards-opening/ui/styles.css";

import { pool } from "./cards";

export function DailyCard({ userId, today }: { userId: string; today: string }) {
  const button = useRef<HTMLButtonElement>(null);
  // The same person gets the same card all day, on any device.
  const [cards] = useState(() => rollCards({ pool, count: 1, seed: `${userId}:${today}` }));
  const [opened, setOpened] = useState<string[]>([]);
  const hunt = useCardOpening({ cards, opened, onOpen: (id) => setOpened((now) => [...now, id]) });

  return (
    <>
      <button ref={button} onClick={() => hunt.start()} disabled={hunt.running || hunt.allOpened}>
        {hunt.allOpened ? `You got ${cards[0].name}` : "Open today's card"}
      </button>
      <CardOpening opening={hunt.opening} launch={() => button.current} />
    </>
  );
}
```

## Notes

- The roll is seeded with the person and the day, so a reload cannot reroll it. For a card that is worth something, roll on your server instead.
- There is no `landing`, so the card fades out where it is once it has been read. Add one to send it to a counter or a collection.
- A press on the card turns it early, a second press sends it away. Nothing here had to say so.

## Show the odds

```tsx
import { chances } from "@react-cards-opening/core";

const odds = chances(pool);

<ul>
  {pool.map((card) => (
    <li key={card.id}>
      {card.name}: {(odds.get(card.id)! * 100).toFixed(1)}%
    </li>
  ))}
</ul>
```

## Related

- [Your first opening](https://bettertyped.github.io/react-cards-opening/docs/first-opening/)
- [Rolls and odds](https://bettertyped.github.io/react-cards-opening/docs/core/rolls/)
- [Origin and landing](https://bettertyped.github.io/react-cards-opening/docs/guides/origin-and-landing/)
- [Collection example](https://bettertyped.github.io/react-cards-opening/docs/examples/collection/)

Source: https://bettertyped.github.io/react-cards-opening/docs/examples/open-from-a-button/
