flip-card-component / README.md
tejasashinde's picture
docs: add MatchWise reference in README
c25e6d9 verified
|
Raw
History Blame Contribute Delete
4.75 kB

A newer version of the Gradio SDK is available: 6.26.0

Upgrade
metadata
title: Flip Card Component
emoji: 🎴
colorFrom: blue
colorTo: indigo
sdk: gradio
sdk_version: 6.18.0
python_version: '3.13'
app_file: app.py
pinned: true
license: apache-2.0
short_description: Card matching game with emoji pairs and 3D card flips

🎴 Flip Card

A custom Gradio HTML component for a memory matching card game.

Flip cards, find matching emoji pairs, use presets, add custom emojis, and track completed games.

Inspired by MatchWise. The original prototype was expanded into a reusable application and now includes a custom HTML component for improved interactivity and integration.


Features

  • Built with gr.HTML
  • Smooth 3D card flip animation
  • Match and wrong-pair feedback
  • Preset and custom emoji input
  • Responsive grid up to 4Γ—4
  • Result output through props.value
  • Game history display

Files Structure

.
β”œβ”€β”€ app.py          # Demo Gradio app
β”œβ”€β”€ flip_card.py    # Reusable FlipCard component
β”œβ”€β”€ requirements.txt
└── README.md

Install and Run

pip install -r requirements.txt
python app.py

Then open http://127.0.0.1:7860 in your browser.


Quick Start

import gradio as gr
from flip_card import FlipCard


with gr.Blocks() as demo:
    game = FlipCard()
    result = gr.Textbox(label="Result")

    game.change(
        fn=lambda value: value or "",
        inputs=game,
        outputs=result,
    )

demo.launch()

Usage with Presets, Custom Emojis, and History

import gradio as gr
from flip_card import DEFAULT_EMOJIS, PRESETS, FlipCard, update_flip_card


def on_win(result: str | None, history: list[str] | None):
    if not result:
        return "", "", history or []

    history = (history or []) + [result]

    history_text = "\n".join(
        f"{i}. {item}"
        for i, item in enumerate(reversed(history[-10:]), start=1)
    )

    return result, history_text, history

def change_preset(name: str):
    emojis = PRESETS.get(name, DEFAULT_EMOJIS).copy()

    return (
        update_flip_card(emojis=emojis),
        emojis,
        ",".join(emojis),
        "",
    )

def parse_emojis(text: str | None):
    emojis = [item.strip() for item in (text or "").split(",") if item.strip()]
    emojis = list(dict.fromkeys(emojis))

    return emojis[:8] if len(emojis) >= 2 else DEFAULT_EMOJIS.copy()

def apply_custom(text: str | None):
    emojis = parse_emojis(text)

    return update_flip_card(emojis=emojis), emojis, ""

def new_game(emojis: list[str] | None):
    return update_flip_card(emojis=emojis or DEFAULT_EMOJIS.copy()), ""

with gr.Blocks() as demo:
    game = FlipCard()

    result = gr.Textbox(label="Result", interactive=False)
    history_box = gr.Textbox(label="Game History", lines=6, interactive=False)

    preset = gr.Dropdown(
        label="Preset",
        choices=list(PRESETS.keys()),
        value="Fruits",
    )
    custom = gr.Textbox(
        label="Custom Emojis",
        value="🍎,🍍",
        placeholder="Example: 🐢,🐱,🦊,🐼",
    )

    apply_btn = gr.Button("Apply Custom Emojis")
    new_btn = gr.Button("New Shuffled Game")
    current_emojis = gr.State(DEFAULT_EMOJIS.copy())
    history = gr.State([])

    game.change(
        fn=on_win,
        inputs=[game, history],
        outputs=[result, history_box, history],
    )
    preset.change(
        fn=change_preset,
        inputs=preset,
        outputs=[game, current_emojis, custom, result],
    )
    apply_btn.click(
        fn=apply_custom,
        inputs=custom,
        outputs=[game, current_emojis, result],
    )
    new_btn.click(
        fn=new_game,
        inputs=current_emojis,
        outputs=[game, result],
    )

demo.launch()

Component API

FlipCard(
    value=None,
    emojis=None,
    cards=None,
    cards_json=None,
    grid_cols=None,
    game_id=None,
    **kwargs
)

Parameters

  • value: Final winning message.
  • emojis: List of emojis used to create matching pairs.
  • cards: Pre-built shuffled card list.
  • cards_json: Internal JSON card state.
  • grid_cols: Number of grid columns.
  • game_id: Unique id used to reset frontend state.

Presets

from flip_card import PRESETS

Available presets:

  • Fruits
  • Animals
  • Space
  • Food
  • Nature
  • Challenge

Updating the Component

Use update_flip_card() when changing cards from an event handler.

from flip_card import update_flip_card

def change_game():
    return update_flip_card(emojis=["🐢", "🐱", "🦊", "🐼"])

Do not return a new FlipCard() instance from event handlers.


License

MIT