Jump to a component
AniCanonKit · AniCanon™
SpendButton
An action that spends fragments: Sakuga's Button with AniCanon™'s price after the label, behind the hairline, with the fragment mark. It takes every Button prop except trailing, plus cost. The core Button knows nothing of fragments; its trailing slot is neutral, and this is the part that fills it.
Live, from @anicanon/sakuga 2.0.0
Sakuga for iOS and Android is coming
iOS
Coming soon
SpendButton 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
SpendButton 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
- An action that spends fragments: Generate, Draw it again, Make the clip, Plan scene 5.
- Not for
- An action that costs nothingButton
- A fragment amount inside a sentenceFragmentBalance variant="inline"
- A price on a choice cardSpendTiles
Guidelines
- Keep the label a plain verb ("Generate", "Start", "Retake"); never write the price into the label.
- The mark is drawn at the button's icon size, so it grows with
size="lg".
import { SpendButton } from '@anicanon/sakuga/anicanonkit';
export default function SpendButtonExample() {
return (
<>
<SpendButton variant="primary" size="lg" cost="~12">
Generate
</SpendButton>
<SpendButton variant="secondary" cost="~12">
Draw it again
</SpendButton>
<SpendButton variant="primary" shape="pill" size="lg" cost="~120">
Make the clip
</SpendButton>
</>
);
}PropsSpendButtonProps
coststringIt has no tokens of its own: it draws with Button’s, listed here.
Each 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
button-primary-bgButton primary: fill.action-primaryneutral-925#0b0a10action-primaryneutral-0#ffffffbutton-primary-fgButton primary: label and icon.text-inverseneutral-0#fffffftext-inverseneutral-925#0b0a10button-secondary-bgButton secondary: fill.action-secondaryshade-a12rgba(11,10,16,0.12)action-secondarywhite-a14rgba(255,255,255,0.14)button-secondary-fgButton secondary: label and icon.text-primaryneutral-925#0b0a10text-primaryneutral-0#ffffffbutton-outline-borderButton outline: edge.border-controlshade-a52rgba(11,10,16,0.52)border-controlwhite-a45rgba(255,255,255,0.45)button-outline-fgButton outline: label and icon.text-primaryneutral-925#0b0a10text-primaryneutral-0#ffffffbutton-ghost-fgButton ghost: label and icon.text-secondaryneutral-800#2e2d36text-secondaryneutral-200#dcdcdebutton-ghost-hover-bgButton ghost: hover fill.bg-fill-subtleshade-a06rgba(11,10,16,0.06)bg-fill-subtlewhite-a08rgba(255,255,255,0.08)button-disabled-bgButton primary or media while it can't be used yet: a quiet fill, never a faded white.bg-fill-subtleshade-a06rgba(11,10,16,0.06)bg-fill-subtlewhite-a08rgba(255,255,255,0.08)button-disabled-fgButton label while disabled.text-mutedneutral-600#5c5b67text-mutedneutral-400#a3a3a7button-media-bgButton media: fill over video or artwork.action-medianeutral-0#ffffffaction-medianeutral-0#ffffffbutton-media-fgButton media: label and icon.text-on-action-medianeutral-925#0b0a10text-on-action-medianeutral-925#0b0a10button-media-secondary-bgButton media-secondary: glass fill over video or artwork.action-media-secondaryglass-dark-a42rgba(28,28,34,0.42)action-media-secondaryglass-dark-a42rgba(28,28,34,0.42)button-media-secondary-fgButton media-secondary: label and icon.text-on-medianeutral-0#fffffftext-on-medianeutral-0#ffffffbutton-media-secondary-borderButton media-secondary: edge.border-glass-mediawhite-a16rgba(255,255,255,0.16)border-glass-mediawhite-a16rgba(255,255,255,0.16)button-destructive-bgButton destructive: the fill of the action that confirms a deletion or takes access away.dangervermilion-600#c8321edangervermilion-600#c8321ebutton-destructive-fgButton destructive: its label and icon.on-dangerneutral-0#ffffffon-dangerneutral-0#ffffffSpace and shape
button-radiusradius-mdbutton-pill-radiusradius-fullbutton-height-smsize-control-smbutton-height-mdsize-control-mdbutton-height-lgsize-control-lgbutton-gapgap-mdbutton-active-scalescale-pressbutton-padding-x-sminset-mdbutton-padding-x-mdinset-lgbutton-padding-x-lginset-xlbutton-outline-inset-ring-widthline-hairlinebutton-media-secondary-blurblur-glassbutton-media-secondary-inset-ring-widthline-hairlinebutton-disabled-opacityopacity-disabledbutton-icon-size-lgicon-size-smbutton-icon-sizeicon-size-smbutton-cost-gapgap-xsbutton-cost-margin-leftgap-2xsbutton-cost-padding-leftinset-mdbutton-cost-border-left-widthline-hairlinebutton-cost-padding-left-sm-mdinset-smbutton-forced-edge-widthline-hairlineType
button-font-familyfont-sansbutton-font-weightweight-boldbutton-font-size-smtext-label-bold-sizebutton-line-height-smtext-label-bold-line-heightbutton-font-size-mdtext-label-bold-sizebutton-line-height-mdtext-label-bold-line-heightbutton-font-size-lgbutton-line-height-lgbutton-secondary-font-weightweight-strongbutton-outline-font-weightweight-strongbutton-ghost-font-weightweight-strongbutton-media-secondary-font-weightweight-strongbutton-cost-font-weightweight-strongMotion
button-durationmotion-fastbutton-easingease-standardbutton-active-durationmotion-instantChecked 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
- Button's own: a native button (a link with
href), so Tab reaches it, Enter activates it, and Space does too on a button. A screen reader hears its label, then the price as "~100 fragments"; the mark and icons are hidden. Withhrefanddisabledit is a disabled button, out of the tab order, so a price can't be spent through a disabled link. - 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.