@srvzr/cards
v0.1.0
Published
Self-contained SRVZ / SRVZr card components (Events, Services, Rentals, Stints, Menus). Props-only, no external data dependencies, mobile/desktop variants.
Maintainers
Readme
@srvzr/cards
Self-contained React card components ported 1:1 from the SRVZr mobile app. Drop them into any React project — no context, no store, no external dependencies.
v0.1.0 · MIT · ESM + CJS + TypeScript declarations included
Cards
| | Dark | Light |
|---|---|---|
| EventCard |
|
|
| ServiceCard |
|
|
| RentalCard |
|
|
| StintCard |
|
|
| MenuCard |
|
|
Install
npm install @srvzr/cards
# or
pnpm add @srvzr/cardsStyles are injected automatically (bundled via tsup injectStyle). No CSS import needed.
Quick Start
import { EventCard, ServiceCard, RentalCard, StintCard, MenuCard } from '@srvzr/cards';
function App() {
return (
<EventCard
id="evt-1"
name="Summer Rooftop Mixer"
description="Live music, drinks and a skyline view."
image="https://example.com/event.jpg"
date={new Date('2026-06-02T19:00:00')}
tags={['Music', 'Networking']}
/>
);
}Components
All cards share these base props:
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | 'desktop' \| 'mobile' | 'desktop' | Layout variant |
| theme | 'dark' \| 'light' | 'dark' | Colour scheme |
| className | string | — | Extra class names |
| style | React.CSSProperties | — | Inline style / CSS token overrides |
EventCard
Full-bleed image card for events. Shows a live countdown badge, title, date, description, tag chips, and a "View" footer.
<EventCard
id="evt-1"
name="Summer Rooftop Mixer"
description="Live music, drinks and a skyline view to kick off the season."
image="https://example.com/event.jpg"
date={new Date('2026-06-02T19:00:00')}
tags={['Music', 'Networking', 'Drinks']}
eventColor="#79C1F0"
variant="desktop"
theme="dark"
onClick={() => {}}
/>| Prop | Type | Description |
|---|---|---|
| id | string | Unique card id |
| name | string | Event name |
| description | string | Short description |
| image | string | Cover image URL |
| date | Date \| string \| number \| { seconds: number } | Event date/time |
| tags | string[] | Tag chips |
| eventColor | string | Accent hex colour |
| onClick | () => void | Click handler |
ServiceCard
Portrait card for a bookable service. Full-bleed icon image with gradient overlay, title, question phrase, bullet description, tags, and CTA buttons.
<ServiceCard
id="svc-1"
serviceName="Deep Cleaning"
questionPhrase="What's your space?"
bulletDescription="• Kitchen\n• Bathrooms\n• Floors"
iconImage="https://example.com/cleaning.jpg"
accentColour="#3B82F6"
tags={['Home', 'Office']}
onSaveClick={() => {}}
onClick={() => {}}
/>| Prop | Type | Description |
|---|---|---|
| id | string | Unique card id |
| serviceName | string | Service title |
| questionPhrase | string | Sub-heading question |
| bulletDescription | string | Newline-separated bullet points |
| iconImage | string | Cover image URL |
| accentColour | string | Accent hex colour |
| tags | string[] | Tag chips |
| isSaved | boolean | Bookmark state |
| onSaveClick | () => void | Bookmark button handler |
| onClick | () => void | Click handler |
RentalCard
Full-bleed rental listing card with multiple images and an animated vertical indicator strip. Transparent-mode renders a product PNG with padding instead of a cover crop.
<RentalCard
id="rnt-1"
itemName="Downtown Loft"
subheading="2BR · City center · Sleeps 4"
images={[
{ url: 'https://example.com/loft.jpg', transparent: false },
{ url: 'https://example.com/camera-kit.png', transparent: true },
]}
pricePerDay={149}
accentColor="#F59E0B"
tags={['Apartment', 'City', 'WiFi']}
onSaveClick={() => {}}
onClick={() => {}}
/>| Prop | Type | Description |
|---|---|---|
| id | string | Unique card id |
| itemName | string | Item / listing name |
| subheading | string | Sub-heading line |
| images | RentalImage[] \| string[] | One or more images |
| pricePerDay | number | Price shown as $X/day |
| accentColor | string | Accent hex colour |
| tags | string[] | Tag chips |
| isSaved | boolean | Bookmark state |
| onSaveClick | () => void | Bookmark handler |
| onClick | () => void | Click handler |
RentalImage — { url: string; transparent: boolean }
Set transparent: true for product PNGs — the card switches to padded object-fit: contain rendering so the transparent background shows cleanly.
StintCard
Compact gig/shift card. Full-bleed image with bottom gradient, title, and question phrase.
<StintCard
id="stn-1"
name="Grass Cutting"
image="https://example.com/lawn.jpg"
questionPhrase="Can you cut a great lawn?"
accentColor="#10B981"
onClick={() => {}}
/>| Prop | Type | Description |
|---|---|---|
| id | string | Unique card id |
| name | string | Gig / shift name |
| image | string | Cover image URL |
| questionPhrase | string | Question shown in italic |
| accentColor | string | Accent hex colour |
| onClick | () => void | Click handler |
MenuCard
Square menu card (260×260 px) with a thumbnail grid of item images, a manage row with animated arrow, and an accent-coloured gradient overlay.
<MenuCard
id="menu-1"
name="Brunch Menu"
statementDescription="Served 9am – 2pm"
accentColor="#059669"
items={[
{ image: 'https://example.com/eggs.jpg' },
{ image: 'https://example.com/pancakes.jpg' },
{ image: 'https://example.com/coffee.jpg' },
]}
onClick={() => {}}
onManageClick={() => {}}
/>| Prop | Type | Description |
|---|---|---|
| id | string | Unique card id |
| name | string | Menu name |
| statementDescription | string | Sub-heading (e.g. hours) |
| accentColor | string | Accent hex colour |
| items | MenuItemImage[] | Array of { image: string } |
| onClick | () => void | Card click handler |
| onManageClick | () => void | "Manage" row handler |
CSS Token Overrides
Pass any token via the style prop to re-theme a card without modifying its internals:
<EventCard
id="x"
name="Custom themed"
style={{
'--background': '#1a1a2e',
'--main-background': '#16213e',
'--text': '#e0e0e0',
'--sub-text': '#a0a0b0',
'--best-gray': '#0f3460',
} as React.CSSProperties}
/>| Token | Dark default | Light default |
|---|---|---|
| --background | #101010 | #ffffff |
| --main-background | #101010 | #ffffff |
| --text | #ffffff | #111827 |
| --sub-text | #bababa | #6b7280 |
| --gray1 | rgba(255,255,255,0.08) | rgba(0,0,0,0.08) |
| --gray2 | #2a2a2a | #e5e7eb |
| --best-gray | #252525 | #f3f4f6 |
| --shadow | rgba(0,0,0,0.4) | rgba(0,0,0,0.12) |
Development
# Install deps
npm install
# Run the live example dev harness (http://localhost:5180)
npm run dev
# Build the package
npm run build
# Run tests (vitest + @testing-library/react)
npm test
# TypeScript type-check
npm run typecheckThe example dev harness at example/App.tsx renders all 5 cards with live JSON editing, desktop/mobile variant toggle, and dark/light theme toggle.
Exports
// Components
export { EventCard, ServiceCard, RentalCard, StintCard, MenuCard }
// Types
export type { EventCardProps, ServiceCardProps, RentalCardProps }
export type { StintCardProps, MenuCardProps, MenuItemImage }
export type { SrvzBaseCardProps, SrvzVariant, SrvzTheme }License
MIT © SRVZr
