awesome-bookshelf-carousel
v0.1.6
Published
A modern React 2D Bookshelf Carousel component with smooth animations, perspective effects, and customizable navigation for showcasing books, products, or media.
Maintainers
Keywords
Readme
Awesome Bookshelf Carousel
A modern React 2D Bookshelf Carousel component with smooth animations, perspective effects, and customizable navigation for showcasing books, products, or media.
Install
npm install awesome-bookshelf-carouselWatch the demo here
Usage
import { AwesomeBookshelfCarousel } from 'awesome-bookshelf-carousel'
import 'awesome-bookshelf-carousel/style.css'
const books = [
{
id: 1,
title: 'A Wild Sea',
author: 'E. King',
genre: 'Adventure',
year: 2024,
blurb: 'A tight story about storms and survival.',
quote: 'The sea never bargains.',
spineColor: '#2b5876',
spineColorB: '#4e4376',
texture: 'cloth',
imageUrl: 'https://example.com/cover-1.jpg'
}
]
export default function Demo() {
return (
<AwesomeBookshelfCarousel
data={books}
shelfHeight={260}
spineMinWidth={44}
spineMaxWidth={72}
autoInterval={4200}
onBookClick={(book) => console.log('book', book)}
onBookChange={(index, book) => console.log('active', index, book)}
/>
)
}Styles
Import the stylesheet once in your app entry (or the component file) to enable layout, typography, and animations.
import 'awesome-bookshelf-carousel/style.css'JSON Data Structure
data expects an array of BookCard objects.
[
{
"id": 1,
"title": "A Wild Sea",
"author": "E. King",
"genre": "Adventure",
"year": 2024,
"blurb": "A tight story about storms and survival.",
"quote": "The sea never bargains.",
"spineColor": "#2b5876",
"spineColorB": "#4e4376",
"texture": "cloth",
"imageUrl": "https://example.com/cover-1.jpg"
}
]Sample JSON Data
[
{
"id": 1,
"title": "The Name of the Rose",
"author": "Umberto Eco",
"genre": "Historical",
"year": 1980,
"blurb": "A Franciscan friar investigates a series of deaths in an Italian monastery, navigating a labyrinthine library holding forbidden knowledge.",
"quote": "Books are not made to be believed, but to be subjected to inquiry.",
"spineColor": "#8b4513",
"spineColorB": "#5c2c0a",
"texture": "leather"
},
{
"id": 2,
"title": "Midnight in the Garden",
"author": "John Berendt",
"genre": "True Crime",
"year": 1994,
"blurb": "Savannah, Georgia — a city of moss-draped squares, old money, and a murder that divided polite society and fascinated the nation.",
"quote": "The South is not a region. It is a state of mind.",
"spineColor": "#2d5a27",
"spineColorB": "#1a3818",
"texture": "cloth"
},
{
"id": 3,
"title": "Invisible Cities",
"author": "Italo Calvino",
"genre": "Fiction",
"year": 1972,
"blurb": "Marco Polo describes fifty-five impossible cities to Kublai Khan. Each is a meditation on memory, desire, signs, and the nature of place itself.",
"quote": "Cities, like dreams, are made of desires and fears.",
"spineColor": "#4a3060",
"spineColorB": "#2a1840",
"texture": "linen"
},
{
"id": 4,
"title": "Gödel, Escher, Bach",
"author": "Douglas Hofstadter",
"genre": "Philosophy",
"year": 1979,
"blurb": "A towering work exploring self-reference, strange loops, and the emergent mystery of consciousness through mathematics, music and visual art.",
"quote": "In the end, we are self-perceiving, self-inventing, locked-in mirages.",
"spineColor": "#1a4a6e",
"spineColorB": "#0d2a42",
"texture": "boards"
},
{
"id": 5,
"title": "The Shadow of the Wind",
"author": "Carlos Ruiz Zafón",
"genre": "Mystery",
"year": 2001,
"blurb": "In post-war Barcelona a boy discovers a book that will define his life — and a mystery concerning its author that threatens his very existence.",
"quote": "Every book has a soul — the soul of the person who wrote it.",
"spineColor": "#8a2020",
"spineColorB": "#4a1010",
"texture": "leather"
},
{
"id": 6,
"title": "Ficciones",
"author": "Jorge Luis Borges",
"genre": "Short Stories",
"year": 1944,
"blurb": "A collection of labyrinths — the Library of Babel, the Garden of Forking Paths, Pierre Menard who rewrote Don Quixote. Each story a perfect trap.",
"quote": "Time forks perpetually toward innumerable futures.",
"spineColor": "#b8860b",
"spineColorB": "#7a5800",
"texture": "cloth"
},
{
"id": 7,
"title": "The Pillars of the Earth",
"author": "Ken Follett",
"genre": "Historical",
"year": 1989,
"blurb": "The building of a cathedral in twelfth-century England becomes an epic of love, treachery, architecture, and the slow birth of a civilisation.",
"quote": "Great buildings, like great music, are never quite finished.",
"spineColor": "#5c4a30",
"spineColorB": "#3a2c18",
"texture": "boards"
},
{
"id": 8,
"title": "One Hundred Years",
"author": "Gabriel García Márquez",
"genre": "Magic Realism",
"year": 1967,
"blurb": "Seven generations of the Buendía family in the mythical town of Macondo — a century of solitude, war, love, and forgetting.",
"quote": "He had already understood that he would never leave that room.",
"spineColor": "#c0682a",
"spineColorB": "#7a3a10",
"texture": "linen"
}
]Props
AwesomeBookshelfCarousel props
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| data | BookCard[] | [] | Book list. If omitted and apiEndpoint is provided, data is fetched from the API. |
| apiEndpoint | string | undefined | URL to fetch book data from. If set, the component fetches JSON on mount. |
| apiHeaders | Record<string, string> | undefined | Optional headers merged into the fetch request. |
| apiTransform | (raw: unknown) => BookCard[] | undefined | Converts API response into a BookCard[]. If omitted, the component expects an array or { data: [...] }. |
| shelfHeight | number | 260 | Shelf height in pixels. |
| spineMinWidth | number | 44 | Minimum book spine width in pixels. |
| spineMaxWidth | number | 72 | Maximum book spine width in pixels. |
| autoInterval | number | 4200 | Auto-advance interval in milliseconds. |
| onBookClick | (card: BookCard) => void | undefined | Called when a book is opened/clicked. |
| onBookChange | (index: number, card: BookCard) => void | undefined | Called when the active book changes. |
BookCard fields
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| id | number | Yes | Unique id for the book. |
| title | string | Yes | Book title shown on spine and open panel. |
| author | string | No | Author name. |
| genre | string | No | Short genre or category tag. |
| year | string | number | No | Year of publication. |
| blurb | string | No | Description shown when the book is open. |
| quote | string | No | Pull quote or excerpt. |
| spineColor | string | Yes | Primary spine color. |
| spineColorB | string | No | Secondary color for gradient/texture. |
| texture | 'cloth' | 'leather' | 'linen' | 'boards' | No | Spine texture. Defaults to a derived value per index if omitted. |
| imageUrl | string | No | Cover image URL shown inside the open book panel. |
| onClick | (card: BookCard) => void | No | Per-book click handler (overrides onBookClick). |
