Theme
Sound
Jump to a component
Core · Content
MediaCard
MediaCard shows one episode, short or manga issue: its artwork at its real shape, then a title and a metadata line.
Live, from @anicanon/sakuga 2.0.0
Sakuga for iOS and Android is coming
iOS
Coming soon
MediaCard for iOS is in the roughs. The tokens it will read are the ones on this page, the same on every platform.
Android
Coming soon
MediaCard for Android is in the roughs. The tokens it will read are the ones on this page, the same on every platform.
- Use it for
- One episode, short or manga issue: its art at its real shape (16:9, 9:16 or a manga page), its title and a metadata line.
- Not for
- A picture in a frame, such as a take or a library itemThumb
- An episode or an issue announced but not out yetPremiereSlot
- A page of an issue in the editorMangaPage
- A cast member on the cast pageCastCard
Guidelines
kindsets the frame: episode 16:9, short 9:16, manga 1:1.414 with a paper corner and a spine shadow. Never put one kind's art in another's frame.- Continue watching passes
logo(the series logo laid over the art) andprogress(0–1). - Shorts pass
durationandcount; episodes passduration; manga passbadgefor New. metajoins facts with a middle dot: "EBA · Season 1 · Episode 1". In a creator's list it says where the production is ("Cut · 3 takes", "14 Oct · 3.4K views");attentionmarks the ones waiting for the creator with the accent dot, below the art, never over it.- A linked card's frame sinks on press; the art leans in on hover and focus, and watched
progressdraws in when the card appears. lightMapis the art's baked light map: its own highlights glow where the pointer is, and at the centre under keyboard focus (light on art). It is on wherever there is a map;light={false}turns it off on a surface that must stay still.- Give the card a width from the layout (a grid column or a fixed shelf width); the frame keeps its ratio.
- The corner follows the size: thumbnails 160px wide or less use
radius-sm, 64px or lessradius-xs, so a small frame never turns into a pill.
import { Badge, MediaCard } from '@anicanon/sakuga/ui';
export default function MediaCardExample() {
return (
<>
<MediaCard
kind="episode"
width={280}
image="/art/eba-s1e1.webp"
lightMap="/art/eba-s1e1.light.webp"
logo="/art/eba-logo.webp"
logoAlt="EBA"
progress={0.28}
title="The Legacy of Blood"
meta="EBA · Season 1 · Episode 1"
href="#"
/>
<MediaCard
kind="short"
width={140}
image="/art/eba-cinema.webp"
lightMap="/art/eba-cinema.light.webp"
imagePosition="62% center"
duration="0:24"
count="1.2M views"
title="The popcorn incident"
href="#"
/>
<MediaCard
kind="manga"
width={150}
image="/art/bad-memories-the-winter-p00.webp"
lightMap="/art/bad-memories-the-winter-p00.light.webp"
alt="The Winter cover"
badge={<Badge variant="new">New</Badge>}
title="The Winter"
meta="Bad Memories · 15 pages"
href="#"
/>
</>
);
}PropsMediaCardProps
kindrequired'episode' | 'short' | 'manga'Sets the frame ratio: episode 16:9, short 9:16, manga 1:1.414.
imagerequiredstringaltstringimagePositionstringlightMapstringThe art's baked light map: it glows with its own highlights under the pointer, at its centre under keyboard focus (light on art).
lightbooleanOn wherever there is a lightMap; false turns it off on a surface that must stay still.
titleReactNodemetaReactNodedurationstringm:ss, shown as a Badge.
countstringbadgeReactNodelogostringThe series logo laid over the artwork (Continue watching).
logoAltstringprogressnumber0–1 watched.
attentionbooleanThe meta line says this one waits for you (takes to review, a plan to approve, ready to publish): it reads in the text colour with the accent dot.
hrefstringlabelstringwidthnumber | stringclassNamestringEach token reads a role, and the role lands on a value in each theme. Change the role and every component that reads it follows.
Colour
media-card-titleMediaCard: title under the artwork.text-primaryneutral-925#0b0a10text-primaryneutral-0#ffffffmedia-card-spineMediaCard manga: the flat band of the binding down the cover's left edge, the same in both themes.black-a50rgba(0,0,0,0.5)black-a50rgba(0,0,0,0.5)media-card-metaMediaCard: metadata under the title.text-mutedneutral-600#5c5b67text-mutedneutral-400#a3a3a7media-card-placeholderMediaCard: frame behind artwork while it loads.bg-surfaceneutral-0#ffffffbg-surfaceneutral-900#111117media-card-scrimMediaCard: shade under a series logo laid over the artwork.bg-scrim-strongscrim-a78rgba(7,7,10,0.78)bg-scrim-strongscrim-a78rgba(7,7,10,0.78)Space and shape
media-card-radiusradius-md12px
media-card-manga-radiusradius-xs4px
media-card-art-filterits own value
saturate(0.9) brightness(0.92)
media-card-gapgap-md8px
media-card-episode-frame-aspect-ratioratio-video16/9
media-card-short-frame-aspect-ratioratio-short9/16
media-card-short-frame-radiusradius-lg16px
media-card-manga-frame-aspect-ratioratio-page1/1.414
media-card-frame-radius-smradius-sm8px
media-card-frame-radius-xsradius-xs4px
media-card-img-hover-scalescale-zoom1.04
media-card-logo-leftinset-sm8px
media-card-logo-bottominset-md12px
media-card-tl-insetinset-sm8px
media-card-br-insetinset-sm8px
media-card-bl-insetinset-sm8px
media-card-meta-margin-topits own value
calc(-1 * 4px)
media-card-manga-spine-widthits own value
8px
media-card-progress-insetinset-sm8px
media-card-frame-xs-maxits own value
64px
media-card-frame-sm-maxits own value
160px
media-card-meta-attention-gapgap-sm6px
media-card-frame-active-scalescale-press-lg.98
media-card-img-focus-scalescale-zoom1.04
media-card-frame-light-scalescale-zoom1.04
Type
media-card-font-familyfont-sansFunnel Sans
media-card-title-font-sizetext-label-size14px
Aa
media-card-title-line-heighttext-label-line-height20px
media-card-title-font-weighttext-label-weight600
media-card-meta-font-sizetext-caption-size13px
Aa
media-card-meta-line-heighttext-caption-line-height18px
media-card-meta-attention-font-weightweight-strong600
Motion
media-card-img-durationmotion-slower560ms
media-card-img-easingease-standardcubic-bezier(0.2, 0, 0, 1)
media-card-img-develop-animationmotion-developsk-develop 560ms cubic-bezier(0, 0, 0, 1)
media-card-frame-durationmotion-fast160ms
media-card-frame-easingease-standardcubic-bezier(0.2, 0, 0, 1)
media-card-frame-active-durationmotion-instant100ms
media-card-frame-light-durationmotion-slower560ms
media-card-frame-light-easingease-standardcubic-bezier(0.2, 0, 0, 1)
Checked automatically with axe-core 4.11.4 against WCAG 2.2 A and AA, on the live preview above, in light and dark, on 26 October 2026.
- Result
- No issues found, in light or in dark.
- By design
- With
hrefit is a link that Tab reaches and Enter follows, named bylabelif given, else by its content in order (any artwork and logo alt text, badge, duration, count, title, meta) ending with "waiting for you" whenattentionis set and "watched 40%" fromprogress; withouthrefthe same reads as text. The artwork's alt isaltand the logo'slogoAlt(both empty by default), and the spine, scrim, light and progress bar are hidden. - Not tested
- The automated check doesn't test keyboard use, focus order or what a screen reader says. The lines above are the design system's own account of them.