@krizaka/ui 3.30.0 → 3.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -8
- package/dist/action-bar.js +3 -3
- package/dist/action-bar.js.map +1 -1
- package/dist/argument-card.d.ts +1 -1
- package/dist/argument-card.js +2 -2
- package/dist/argument-card.js.map +1 -1
- package/dist/blocks.css +19 -60
- package/dist/{button-BmCrLCq7.d.ts → button-Cm9pFH3P.d.ts} +10 -9
- package/dist/button.d.ts +11 -10
- package/dist/button.js +1 -1
- package/dist/captcha.js +1 -1
- package/dist/card-grid.d.ts +5 -12
- package/dist/card-grid.js +4 -12
- package/dist/card-grid.js.map +1 -1
- package/dist/card.d.ts +7 -7
- package/dist/card.js +2 -2
- package/dist/card.js.map +1 -1
- package/dist/{chunk-GYKQ52HX.js → chunk-2AJ4NJUF.js} +2 -2
- package/dist/{chunk-MQPC3P4T.js → chunk-2DGLWTPS.js} +3 -3
- package/dist/chunk-2DGLWTPS.js.map +1 -0
- package/dist/{chunk-DZU6RMYD.js → chunk-3DHNN5V7.js} +15 -9
- package/dist/chunk-3DHNN5V7.js.map +1 -0
- package/dist/{chunk-TFJDIOFK.js → chunk-4E5IUZHR.js} +3 -3
- package/dist/chunk-4E5IUZHR.js.map +1 -0
- package/dist/{chunk-HAQWKORZ.js → chunk-4JO5GSSD.js} +1 -37
- package/dist/chunk-4JO5GSSD.js.map +1 -0
- package/dist/{chunk-APNIVNIX.js → chunk-IBDTAMPF.js} +3 -4
- package/dist/chunk-IBDTAMPF.js.map +1 -0
- package/dist/{chunk-LYOPPBMC.js → chunk-KIBICUZK.js} +2 -2
- package/dist/{chunk-HBZPJ3EP.js → chunk-NJFCSVPT.js} +2 -2
- package/dist/{chunk-KM6VAKIE.js → chunk-RE5WJ4QP.js} +2 -2
- package/dist/chunk-RE5WJ4QP.js.map +1 -0
- package/dist/{chunk-CHOJUCVE.js → chunk-SJS6RJIT.js} +15 -9
- package/dist/chunk-SJS6RJIT.js.map +1 -0
- package/dist/{chunk-6ZYRUOTA.js → chunk-UV4HBVH7.js} +15 -9
- package/dist/chunk-UV4HBVH7.js.map +1 -0
- package/dist/command.js +2 -2
- package/dist/confirm-button.d.ts +1 -1
- package/dist/confirm-button.js +1 -1
- package/dist/continue-prompt.js +14 -8
- package/dist/continue-prompt.js.map +1 -1
- package/dist/data-table.js +2 -2
- package/dist/dialog.js +2 -2
- package/dist/engine-flow.d.ts +25 -2
- package/dist/engine-flow.js +27 -6
- package/dist/engine-flow.js.map +1 -1
- package/dist/force-update-screen.js +2 -2
- package/dist/force-update-screen.js.map +1 -1
- package/dist/genui.js +3 -3
- package/dist/glow-card.d.ts +5 -4
- package/dist/glow-card.js +2 -8
- package/dist/glow-card.js.map +1 -1
- package/dist/image-cropper.js +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/iso.d.ts +1 -1
- package/dist/iso.js.map +1 -1
- package/dist/landscape.js +4 -4
- package/dist/landscape.js.map +1 -1
- package/dist/link-card.d.ts +3 -6
- package/dist/link-card.js +1 -1
- package/dist/maintenance-screen.js +1 -1
- package/dist/map.d.ts +50 -5
- package/dist/map.js +202 -66
- package/dist/map.js.map +1 -1
- package/dist/match-dialog.js +1 -1
- package/dist/media-gallery.js +1 -1
- package/dist/media-gallery.js.map +1 -1
- package/dist/media-grid.js +2 -2
- package/dist/motion.css +52 -122
- package/dist/motion.d.ts +2 -2
- package/dist/motion.js +1 -1
- package/dist/native/map.js +64 -64
- package/dist/native/map.js.map +1 -1
- package/dist/native.js +30 -30
- package/dist/native.js.map +1 -1
- package/dist/nav-bar.js +2 -2
- package/dist/pointer-light.d.ts +6 -9
- package/dist/pointer-light.js +9 -5
- package/dist/pointer-light.js.map +1 -1
- package/dist/radio-group.js +2 -2
- package/dist/radio-group.js.map +1 -1
- package/dist/service-card.js +1 -1
- package/dist/service-card.js.map +1 -1
- package/dist/site-footer.js +2 -2
- package/dist/slider.js +1 -1
- package/dist/slider.js.map +1 -1
- package/dist/story.css +5 -12
- package/dist/theme.d.ts +1 -1
- package/dist/theme.js +1 -1
- package/dist/update-prompt.js +2 -2
- package/dist/update-prompt.js.map +1 -1
- package/dist/vertical-video.js +1 -1
- package/dist/video-player.js +2 -2
- package/dist/video-player.js.map +1 -1
- package/package.json +7 -7
- package/registry/action-bar.json +1 -1
- package/registry/app-shell.json +4 -4
- package/registry/argument-card.json +7 -16
- package/registry/auth-layout.json +4 -4
- package/registry/button.json +20 -20
- package/registry/card-grid.json +21 -24
- package/registry/card.json +7 -7
- package/registry/component-page.json +2 -2
- package/registry/confirm-button.json +6 -6
- package/registry/contact-page.json +2 -2
- package/registry/cover-hero.json +3 -3
- package/registry/dashboard-layout.json +2 -2
- package/registry/detail-layout.json +4 -4
- package/registry/docs-hub-page.json +2 -2
- package/registry/empty-state.json +1 -1
- package/registry/engine-flow.json +74 -3
- package/registry/examples/app-shell/admin-console.js +1 -1
- package/registry/examples/app-shell/admin-console.tsx +1 -1
- package/registry/examples/app-shell/basic.js +1 -1
- package/registry/examples/app-shell/basic.tsx +1 -1
- package/registry/examples/app-shell/desktop.js +1 -1
- package/registry/examples/app-shell/desktop.tsx +1 -1
- package/registry/examples/app-shell/orochia-studio.js +1 -1
- package/registry/examples/app-shell/orochia-studio.tsx +1 -1
- package/registry/examples/argument-card/hover-quiet.js +1 -1
- package/registry/examples/argument-card/hover-quiet.tsx +1 -1
- package/registry/examples/auth-layout/onboarding.js +2 -2
- package/registry/examples/auth-layout/onboarding.tsx +2 -2
- package/registry/examples/auth-layout/sign-in.js +2 -2
- package/registry/examples/auth-layout/sign-in.tsx +2 -2
- package/registry/examples/auth-layout/verify.js +1 -1
- package/registry/examples/auth-layout/verify.tsx +1 -1
- package/registry/examples/avatar/native/presence.dark.png +0 -0
- package/registry/examples/avatar/native/presence.light.png +0 -0
- package/registry/examples/badge/native/tones.dark.png +0 -0
- package/registry/examples/badge/native/tones.light.png +0 -0
- package/registry/examples/button/native/disabled.dark.png +0 -0
- package/registry/examples/button/native/disabled.light.png +0 -0
- package/registry/examples/button/native/gradient.dark.png +0 -0
- package/registry/examples/button/native/gradient.light.png +0 -0
- package/registry/examples/button/native/icon-only.dark.png +0 -0
- package/registry/examples/button/native/icon-only.light.png +0 -0
- package/registry/examples/button/native/icon.dark.png +0 -0
- package/registry/examples/button/native/icon.light.png +0 -0
- package/registry/examples/button/native/loading.dark.png +0 -0
- package/registry/examples/button/native/loading.light.png +0 -0
- package/registry/examples/button/native/primary.dark.png +0 -0
- package/registry/examples/button/native/primary.light.png +0 -0
- package/registry/examples/button/native/sizes.dark.png +0 -0
- package/registry/examples/button/native/sizes.light.png +0 -0
- package/registry/examples/button/signature.js +2 -2
- package/registry/examples/button/signature.tsx +4 -4
- package/registry/examples/card/interactive-link.tsx +1 -1
- package/registry/examples/card/native/body.dark.png +0 -0
- package/registry/examples/card/native/body.light.png +0 -0
- package/registry/examples/card/native/default.dark.png +0 -0
- package/registry/examples/card/native/default.light.png +0 -0
- package/registry/examples/card/native/elevated.dark.png +0 -0
- package/registry/examples/card/native/elevated.light.png +0 -0
- package/registry/examples/card-grid/hover-quiet.js +1 -1
- package/registry/examples/card-grid/hover-quiet.tsx +1 -1
- package/registry/examples/chat/native/assistant.dark.png +0 -0
- package/registry/examples/chat/native/assistant.light.png +0 -0
- package/registry/examples/chat/native/conversation.dark.png +0 -0
- package/registry/examples/chat/native/conversation.light.png +0 -0
- package/registry/examples/chat/native/inbox.dark.png +0 -0
- package/registry/examples/chat/native/inbox.light.png +0 -0
- package/registry/examples/checkbox/native/terms.dark.png +0 -0
- package/registry/examples/checkbox/native/terms.light.png +0 -0
- package/registry/examples/chip/native/multiple.dark.png +0 -0
- package/registry/examples/chip/native/multiple.light.png +0 -0
- package/registry/examples/chip/native/single.dark.png +0 -0
- package/registry/examples/chip/native/single.light.png +0 -0
- package/registry/examples/chip/native/toggle.dark.png +0 -0
- package/registry/examples/chip/native/toggle.light.png +0 -0
- package/registry/examples/component-page/button.js +2 -2
- package/registry/examples/component-page/button.tsx +2 -2
- package/registry/examples/contact-page/team.js +1 -1
- package/registry/examples/contact-page/team.tsx +1 -1
- package/registry/examples/cover-hero/plain.js +1 -1
- package/registry/examples/cover-hero/plain.tsx +1 -1
- package/registry/examples/cover-hero/shop.js +1 -1
- package/registry/examples/cover-hero/shop.tsx +1 -1
- package/registry/examples/dashboard-layout/orazaka-eric.js +2 -2
- package/registry/examples/dashboard-layout/orazaka-eric.tsx +2 -2
- package/registry/examples/date-picker/native/calendar.dark.png +0 -0
- package/registry/examples/date-picker/native/calendar.light.png +0 -0
- package/registry/examples/date-picker/native/day-strip.dark.png +0 -0
- package/registry/examples/date-picker/native/day-strip.light.png +0 -0
- package/registry/examples/date-picker/native/month-year.dark.png +0 -0
- package/registry/examples/date-picker/native/month-year.light.png +0 -0
- package/registry/examples/date-picker/native/time-slots.dark.png +0 -0
- package/registry/examples/date-picker/native/time-slots.light.png +0 -0
- package/registry/examples/description-list/native/job-details.dark.png +0 -0
- package/registry/examples/description-list/native/job-details.light.png +0 -0
- package/registry/examples/detail-layout/checkout.js +1 -1
- package/registry/examples/detail-layout/checkout.tsx +1 -1
- package/registry/examples/detail-layout/job.js +1 -1
- package/registry/examples/detail-layout/job.tsx +1 -1
- package/registry/examples/detail-layout/video.js +2 -2
- package/registry/examples/detail-layout/video.tsx +2 -2
- package/registry/examples/dialog/native/sheet.dark.png +0 -0
- package/registry/examples/dialog/native/sheet.light.png +0 -0
- package/registry/examples/docs-hub-page/krizaka.js +1 -1
- package/registry/examples/docs-hub-page/krizaka.tsx +1 -1
- package/registry/examples/empty-state/library.js +1 -1
- package/registry/examples/empty-state/library.tsx +1 -1
- package/registry/examples/empty-state/native/default.dark.png +0 -0
- package/registry/examples/empty-state/native/default.light.png +0 -0
- package/registry/examples/fab/native/extended.dark.png +0 -0
- package/registry/examples/fab/native/extended.light.png +0 -0
- package/registry/examples/force-update-screen/native/default.dark.png +0 -0
- package/registry/examples/force-update-screen/native/default.light.png +0 -0
- package/registry/examples/form/native/amount.dark.png +0 -0
- package/registry/examples/form/native/amount.light.png +0 -0
- package/registry/examples/form/native/audience.dark.png +0 -0
- package/registry/examples/form/native/audience.light.png +0 -0
- package/registry/examples/form/native/profile.dark.png +0 -0
- package/registry/examples/form/native/profile.light.png +0 -0
- package/registry/examples/form/native/settings.dark.png +0 -0
- package/registry/examples/form/native/settings.light.png +0 -0
- package/registry/examples/form/native/sign-up.dark.png +0 -0
- package/registry/examples/form/native/sign-up.light.png +0 -0
- package/registry/examples/form/native/upload.dark.png +0 -0
- package/registry/examples/form/native/upload.light.png +0 -0
- package/registry/examples/glow-card/spotlight.tsx +1 -1
- package/registry/examples/goal-gauge/native/default.dark.png +0 -0
- package/registry/examples/goal-gauge/native/default.light.png +0 -0
- package/registry/examples/landing-page/krizaka.js +3 -3
- package/registry/examples/landing-page/krizaka.tsx +3 -3
- package/registry/examples/link-card/hover-quiet.js +1 -1
- package/registry/examples/link-card/hover-quiet.tsx +1 -1
- package/registry/examples/loader/native/block.dark.png +0 -0
- package/registry/examples/loader/native/block.light.png +0 -0
- package/registry/examples/map/native/location-picker.dark.png +0 -0
- package/registry/examples/map/native/location-picker.light.png +0 -0
- package/registry/examples/map/route.js +36 -0
- package/registry/examples/map/route.tsx +35 -0
- package/registry/examples/marketing-layout/pricing.js +1 -1
- package/registry/examples/marketing-layout/pricing.tsx +1 -1
- package/registry/examples/marketing-layout/product-page.js +1 -1
- package/registry/examples/marketing-layout/product-page.tsx +2 -2
- package/registry/examples/mascot-state/native/default.dark.png +0 -0
- package/registry/examples/mascot-state/native/default.light.png +0 -0
- package/registry/examples/mascots/native/crane.dark.png +0 -0
- package/registry/examples/mascots/native/crane.light.png +0 -0
- package/registry/examples/mascots/native/default.dark.png +0 -0
- package/registry/examples/mascots/native/default.light.png +0 -0
- package/registry/examples/mascots/native/lovebird.dark.png +0 -0
- package/registry/examples/mascots/native/lovebird.light.png +0 -0
- package/registry/examples/mascots/native/phoenix.dark.png +0 -0
- package/registry/examples/mascots/native/phoenix.light.png +0 -0
- package/registry/examples/match-dialog/native/its-a-match.dark.png +0 -0
- package/registry/examples/match-dialog/native/its-a-match.light.png +0 -0
- package/registry/examples/media-capture/native/photo.dark.png +0 -0
- package/registry/examples/media-capture/native/photo.light.png +0 -0
- package/registry/examples/meta-row/native/video.dark.png +0 -0
- package/registry/examples/meta-row/native/video.light.png +0 -0
- package/registry/examples/meter/native/credits.dark.png +0 -0
- package/registry/examples/meter/native/credits.light.png +0 -0
- package/registry/examples/meter/native/split-ring.dark.png +0 -0
- package/registry/examples/meter/native/split-ring.light.png +0 -0
- package/registry/examples/nav-bar/family-product.js +1 -1
- package/registry/examples/nav-bar/family-product.tsx +1 -1
- package/registry/examples/onboarding/native/first-launch.dark.png +0 -0
- package/registry/examples/onboarding/native/first-launch.light.png +0 -0
- package/registry/examples/permission-prompt/native/blocked.dark.png +0 -0
- package/registry/examples/permission-prompt/native/blocked.light.png +0 -0
- package/registry/examples/permission-prompt/native/camera.dark.png +0 -0
- package/registry/examples/permission-prompt/native/camera.light.png +0 -0
- package/registry/examples/photo-grid/native/profile-photos.dark.png +0 -0
- package/registry/examples/photo-grid/native/profile-photos.light.png +0 -0
- package/registry/examples/pricing-page/credits.js +3 -3
- package/registry/examples/pricing-page/credits.tsx +3 -3
- package/registry/examples/product-page/orazaka.js +2 -2
- package/registry/examples/product-page/orazaka.tsx +2 -2
- package/registry/examples/profile-card/native/default.dark.png +0 -0
- package/registry/examples/profile-card/native/default.light.png +0 -0
- package/registry/examples/progress/native/bar.dark.png +0 -0
- package/registry/examples/progress/native/bar.light.png +0 -0
- package/registry/examples/progress/native/indeterminate.dark.png +0 -0
- package/registry/examples/progress/native/indeterminate.light.png +0 -0
- package/registry/examples/progress/native/ring.dark.png +0 -0
- package/registry/examples/progress/native/ring.light.png +0 -0
- package/registry/examples/radio-group/native/buttons.dark.png +0 -0
- package/registry/examples/radio-group/native/buttons.light.png +0 -0
- package/registry/examples/radio-group/native/cards.dark.png +0 -0
- package/registry/examples/radio-group/native/cards.light.png +0 -0
- package/registry/examples/radio-group/native/list.dark.png +0 -0
- package/registry/examples/radio-group/native/list.light.png +0 -0
- package/registry/examples/screen/native/auth.dark.png +0 -0
- package/registry/examples/screen/native/auth.light.png +0 -0
- package/registry/examples/screen/native/chat.dark.png +0 -0
- package/registry/examples/screen/native/chat.light.png +0 -0
- package/registry/examples/screen/native/profile.dark.png +0 -0
- package/registry/examples/screen/native/profile.light.png +0 -0
- package/registry/examples/screen/native/settings.dark.png +0 -0
- package/registry/examples/screen/native/settings.light.png +0 -0
- package/registry/examples/search-field/native/cancel.dark.png +0 -0
- package/registry/examples/search-field/native/cancel.light.png +0 -0
- package/registry/examples/settings-layout/account.js +1 -1
- package/registry/examples/settings-layout/account.tsx +1 -1
- package/registry/examples/settings-layout/native/account.dark.png +0 -0
- package/registry/examples/settings-layout/native/account.light.png +0 -0
- package/registry/examples/settings-layout/sections.js +1 -1
- package/registry/examples/settings-layout/sections.tsx +1 -1
- package/registry/examples/showcase/native/slides.dark.png +0 -0
- package/registry/examples/showcase/native/slides.light.png +0 -0
- package/registry/examples/slider/native/default.dark.png +0 -0
- package/registry/examples/slider/native/default.light.png +0 -0
- package/registry/examples/slider/native/range.dark.png +0 -0
- package/registry/examples/slider/native/range.light.png +0 -0
- package/registry/examples/slider/native/stepped.dark.png +0 -0
- package/registry/examples/slider/native/stepped.light.png +0 -0
- package/registry/examples/slider/native/vertical.dark.png +0 -0
- package/registry/examples/slider/native/vertical.light.png +0 -0
- package/registry/examples/spinner/native/sizes.dark.png +0 -0
- package/registry/examples/spinner/native/sizes.light.png +0 -0
- package/registry/examples/split-view/messages.js +1 -1
- package/registry/examples/split-view/messages.tsx +1 -1
- package/registry/examples/status-page/building.js +1 -1
- package/registry/examples/status-page/building.tsx +1 -1
- package/registry/examples/step-progress/native/sign-up.dark.png +0 -0
- package/registry/examples/step-progress/native/sign-up.light.png +0 -0
- package/registry/examples/stepper/native/run.dark.png +0 -0
- package/registry/examples/stepper/native/run.light.png +0 -0
- package/registry/examples/sticky-action/phone.js +1 -1
- package/registry/examples/sticky-action/phone.tsx +1 -1
- package/registry/examples/switch/native/default.dark.png +0 -0
- package/registry/examples/switch/native/default.light.png +0 -0
- package/registry/examples/switch/native/settings.dark.png +0 -0
- package/registry/examples/switch/native/settings.light.png +0 -0
- package/registry/examples/tab-bar/native/main-sections.dark.png +0 -0
- package/registry/examples/tab-bar/native/main-sections.light.png +0 -0
- package/registry/examples/tabs/native/sections.dark.png +0 -0
- package/registry/examples/tabs/native/sections.light.png +0 -0
- package/registry/examples/tag-selector/native/interests.dark.png +0 -0
- package/registry/examples/tag-selector/native/interests.light.png +0 -0
- package/registry/examples/toast/native/snackbar.dark.png +0 -0
- package/registry/examples/toast/native/snackbar.light.png +0 -0
- package/registry/examples/toast/native/tones.dark.png +0 -0
- package/registry/examples/toast/native/tones.light.png +0 -0
- package/registry/examples/txt/native/tones.dark.png +0 -0
- package/registry/examples/txt/native/tones.light.png +0 -0
- package/registry/examples/update-prompt/native/default.dark.png +0 -0
- package/registry/examples/update-prompt/native/default.light.png +0 -0
- package/registry/examples/verified-badge/native/verified.dark.png +0 -0
- package/registry/examples/verified-badge/native/verified.light.png +0 -0
- package/registry/examples/vertical-video/native/rail.dark.png +0 -0
- package/registry/examples/vertical-video/native/rail.light.png +0 -0
- package/registry/examples/waveform/native/card.dark.png +0 -0
- package/registry/examples/waveform/native/card.light.png +0 -0
- package/registry/force-update-screen.json +1 -1
- package/registry/form.json +6 -6
- package/registry/glow-card.json +19 -19
- package/registry/index.json +20 -21
- package/registry/iso.json +7 -7
- package/registry/landing-page.json +2 -2
- package/registry/landscape.json +1 -1
- package/registry/link-card.json +15 -24
- package/registry/map.json +235 -6
- package/registry/marketing-layout.json +3 -3
- package/registry/media-gallery.json +1 -1
- package/registry/nav-bar.json +3 -3
- package/registry/pointer-light.json +17 -22
- package/registry/pricing-page.json +2 -2
- package/registry/product-page.json +2 -2
- package/registry/progress.json +2 -2
- package/registry/radio-group.json +1 -1
- package/registry/rail-nav.json +2 -2
- package/registry/service-card.json +1 -1
- package/registry/settings-layout.json +3 -3
- package/registry/site-footer.json +2 -2
- package/registry/slider.json +1 -1
- package/registry/split-view.json +2 -2
- package/registry/status-page.json +1 -1
- package/registry/sticky-action.json +2 -2
- package/registry/update-prompt.json +1 -1
- package/registry/video-player.json +1 -1
- package/dist/chunk-6ZYRUOTA.js.map +0 -1
- package/dist/chunk-AB5D3KBG.js +0 -37
- package/dist/chunk-AB5D3KBG.js.map +0 -1
- package/dist/chunk-APNIVNIX.js.map +0 -1
- package/dist/chunk-CHOJUCVE.js.map +0 -1
- package/dist/chunk-DZU6RMYD.js.map +0 -1
- package/dist/chunk-HAQWKORZ.js.map +0 -1
- package/dist/chunk-KM6VAKIE.js.map +0 -1
- package/dist/chunk-MQPC3P4T.js.map +0 -1
- package/dist/chunk-TFJDIOFK.js.map +0 -1
- package/registry/examples/argument-card/hover-light.js +0 -17
- package/registry/examples/argument-card/hover-light.tsx +0 -19
- package/registry/examples/link-card/hover-light.d.ts +0 -4
- package/registry/examples/link-card/hover-light.js +0 -18
- package/registry/examples/link-card/hover-light.tsx +0 -20
- /package/dist/{chunk-GYKQ52HX.js.map → chunk-2AJ4NJUF.js.map} +0 -0
- /package/dist/{chunk-LYOPPBMC.js.map → chunk-KIBICUZK.js.map} +0 -0
- /package/dist/{chunk-HBZPJ3EP.js.map → chunk-NJFCSVPT.js.map} +0 -0
- /package/registry/examples/{argument-card/hover-light.d.ts → map/route.d.ts} +0 -0
package/registry/button.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"name": "button",
|
|
3
3
|
"type": "primitive",
|
|
4
4
|
"title": "Button",
|
|
5
|
-
"summary": "The action: six looks, three sizes,
|
|
6
|
-
"description": "The action: six looks, three sizes,
|
|
5
|
+
"summary": "The action: six looks, three sizes, two shapes (an 8 px radius, the pill) — and the whole life of an action built in: a wait traced by the loader glyph, its progress, a success or a failure drawn and announced.",
|
|
6
|
+
"description": "The action: six looks, three sizes, two shapes (an 8 px radius, the pill) — and the whole life of an action built in: a wait traced by the loader glyph, its progress, a success or a failure drawn and announced.",
|
|
7
7
|
"status": "stable",
|
|
8
8
|
"deprecated": null,
|
|
9
9
|
"category": "actions",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"One primary per view; the danger variant only for what destroys or cannot be undone.",
|
|
47
47
|
"`loading` while the action runs: the button is disabled, says it is busy and draws the glyph; add `progress` when you know how far it is.",
|
|
48
48
|
"End with `status` (`success` / `error`) and `announce` the result in words: sighted people see the check, everyone hears “Saved”. Clear the status after a moment.",
|
|
49
|
-
"`shape=\"cut\"`, `shimmer` and `magnetic` are
|
|
49
|
+
"One shape for every action (an 8 px radius, the radius of a field); the pill only for a chip-like action. The hover changes a colour, never the position. `shape=\"cut\"`, `shimmer` and `magnetic` are deprecated since 3.31 (krizaka-ui#393) and do nothing.",
|
|
50
50
|
"Style a link without the component with `buttonVariants({ variant, size })`."
|
|
51
51
|
],
|
|
52
52
|
"accessibility": {
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
"name": "magnetic",
|
|
115
115
|
"type": "boolean",
|
|
116
116
|
"default": null,
|
|
117
|
-
"description": "
|
|
117
|
+
"description": "@deprecated Since 3.31 (krizaka-ui#393): does nothing — a button never moves under the pointer. Removed in 4.0.",
|
|
118
118
|
"required": false
|
|
119
119
|
},
|
|
120
120
|
{
|
|
@@ -128,14 +128,14 @@
|
|
|
128
128
|
"name": "shape",
|
|
129
129
|
"type": "\"rounded\" | \"pill\" | \"cut\"",
|
|
130
130
|
"default": "rounded",
|
|
131
|
-
"description": "rounded · pill
|
|
131
|
+
"description": "`rounded` (an 8 px radius, the radius of a field) · `pill`. `cut` is deprecated (krizaka-ui#393: the chamfer is\nretired) — it draws `rounded` and warns in development; it will be removed in 4.0.",
|
|
132
132
|
"required": false
|
|
133
133
|
},
|
|
134
134
|
{
|
|
135
135
|
"name": "shimmer",
|
|
136
136
|
"type": "boolean",
|
|
137
137
|
"default": null,
|
|
138
|
-
"description": "
|
|
138
|
+
"description": "@deprecated Since 3.31 (krizaka-ui#393): does nothing — the hover is quiet. Removed in 4.0.",
|
|
139
139
|
"required": false
|
|
140
140
|
},
|
|
141
141
|
{
|
|
@@ -204,7 +204,7 @@
|
|
|
204
204
|
"name": "magnetic",
|
|
205
205
|
"type": "boolean",
|
|
206
206
|
"default": null,
|
|
207
|
-
"description": "
|
|
207
|
+
"description": "@deprecated Since 3.31 (krizaka-ui#393): does nothing — a button never moves under the pointer. Removed in 4.0.",
|
|
208
208
|
"required": false
|
|
209
209
|
},
|
|
210
210
|
{
|
|
@@ -218,14 +218,14 @@
|
|
|
218
218
|
"name": "shape",
|
|
219
219
|
"type": "\"rounded\" | \"pill\" | \"cut\"",
|
|
220
220
|
"default": "rounded",
|
|
221
|
-
"description": "rounded · pill
|
|
221
|
+
"description": "`rounded` (an 8 px radius, the radius of a field) · `pill`. `cut` is deprecated (krizaka-ui#393: the chamfer is\nretired) — it draws `rounded` and warns in development; it will be removed in 4.0.",
|
|
222
222
|
"required": false
|
|
223
223
|
},
|
|
224
224
|
{
|
|
225
225
|
"name": "shimmer",
|
|
226
226
|
"type": "boolean",
|
|
227
227
|
"default": null,
|
|
228
|
-
"description": "
|
|
228
|
+
"description": "@deprecated Since 3.31 (krizaka-ui#393): does nothing — the hover is quiet. Removed in 4.0.",
|
|
229
229
|
"required": false
|
|
230
230
|
},
|
|
231
231
|
{
|
|
@@ -280,10 +280,10 @@
|
|
|
280
280
|
{
|
|
281
281
|
"name": "signature",
|
|
282
282
|
"title": "The signature action",
|
|
283
|
-
"description": "
|
|
283
|
+
"description": "The gradient beside a quiet outline: the one call to action of a hero; the arrow leans forward on hover, the button never moves.",
|
|
284
284
|
"path": "examples/button/signature.tsx",
|
|
285
285
|
"module": "@krizaka/ui/registry/examples/button/signature",
|
|
286
|
-
"code": "import { Button } from \"@krizaka/ui/button\";\n\n// The one action a page is about:
|
|
286
|
+
"code": "import { Button } from \"@krizaka/ui/button\";\n\n// The one action a page is about: the brand gradient beside a quiet outline. The arrow of a signature icon leans\n// forward on hover; the button itself never moves (krizaka-ui#393).\nexport default function ButtonSignature() {\n return (\n <div className=\"flex flex-wrap items-center gap-3\">\n <Button variant=\"gradient\" size=\"lg\">\n Start free\n <svg data-kz-icon=\"ForwardIcon\" viewBox=\"0 0 24 24\" className=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M5 12h14M13 6l6 6-6 6\" />\n </svg>\n </Button>\n <Button variant=\"outline\" size=\"lg\">\n Talk to us\n </Button>\n </div>\n );\n}\n"
|
|
287
287
|
},
|
|
288
288
|
{
|
|
289
289
|
"name": "primary",
|
|
@@ -643,7 +643,7 @@
|
|
|
643
643
|
"files": [
|
|
644
644
|
{
|
|
645
645
|
"path": "button/button.tsx",
|
|
646
|
-
"content": "// Server-safe: no hook, no context. `buttonVariants` styles a <Link> or a Server Component without the component.\nimport { Slot } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { LoaderGlyph } from \"../spinner/glyph\";\nimport { buttonRecipe } from \"./recipe\";\n\nexport const buttonVariants = tv(buttonRecipe);\n\nexport type ButtonVariants = VariantProps<typeof buttonVariants>;\n\nexport type ButtonProps = React.ComponentProps<\"button\"> &\n ButtonVariants & {\n /**\n * The look: `primary` (the accent), `gradient` (accent → accent-2), `secondary` (a raised surface), `outline`,\n * `ghost`, `danger`.\n * @default \"secondary\"\n */\n variant?: ButtonVariants[\"variant\"];\n /**\n * sm · md · lg, or `icon` (a square).\n * @default \"md\"\n */\n size?: ButtonVariants[\"size\"];\n /**\n * rounded · pill
|
|
646
|
+
"content": "// Server-safe: no hook, no context. `buttonVariants` styles a <Link> or a Server Component without the component.\nimport { Slot } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { LoaderGlyph } from \"../spinner/glyph\";\nimport { buttonRecipe } from \"./recipe\";\n\nexport const buttonVariants = tv(buttonRecipe);\n\nexport type ButtonVariants = VariantProps<typeof buttonVariants>;\n\nexport type ButtonProps = React.ComponentProps<\"button\"> &\n ButtonVariants & {\n /**\n * The look: `primary` (the accent), `gradient` (accent → accent-2), `secondary` (a raised surface), `outline`,\n * `ghost`, `danger`.\n * @default \"secondary\"\n */\n variant?: ButtonVariants[\"variant\"];\n /**\n * sm · md · lg, or `icon` (a square).\n * @default \"md\"\n */\n size?: ButtonVariants[\"size\"];\n /**\n * `rounded` (an 8 px radius, the radius of a field) · `pill`. `cut` is deprecated (krizaka-ui#393: the chamfer is\n * retired) — it draws `rounded` and warns in development; it will be removed in 4.0.\n * @default \"rounded\"\n */\n shape?: ButtonVariants[\"shape\"];\n /** Renders the child (e.g. a <Link>) instead of the <button>, with props, classes and ref merged. */\n asChild?: boolean;\n /**\n * Disables and signals the wait (aria-busy, data-loading) and shows the Krizaka loader glyph before the label; the\n * button keeps its colour.\n */\n loading?: boolean;\n /**\n * Between 0 and 1, while `loading`: the glyph's trace and a light fill across the button grow to the value (an\n * upload, an export).\n */\n progress?: number | null;\n /**\n * How the action ended: `success` draws a check, `error` a cross (and the button shakes its head once); a ring of\n * the status colour opens around it. Clear it to return to rest.\n */\n status?: \"success\" | \"error\" | null;\n /** A message announced politely by assistive technology when it changes (“Saved”, “Upload failed”) — passed translated. */\n announce?: string;\n /**\n * Shows the glyph while `loading` / with a `status`. `false`: you draw your own.\n * @default true\n */\n indicator?: boolean;\n /** @deprecated Since 3.31 (krizaka-ui#393): does nothing — the hover is quiet. Removed in 4.0. */\n shimmer?: boolean;\n /** @deprecated Since 3.31 (krizaka-ui#393): does nothing — a button never moves under the pointer. Removed in 4.0. */\n magnetic?: boolean;\n };\n\nconst STATUS_TEXT = { success: \"text-fg-success\", error: \"text-fg-danger\" } as const;\n\nlet warnedCut = false;\n/** `shape=\"cut\"` (the chamfer) is retired: one warning per page in development, never in production. */\nfunction warnCut() {\n if (warnedCut || typeof process === \"undefined\" || process.env.NODE_ENV === \"production\") return;\n warnedCut = true;\n console.warn('@krizaka/ui/button: shape=\"cut\" is deprecated (krizaka-ui#393) and now draws the default rounded shape. Remove the prop.');\n}\n\nexport function Button({\n asChild,\n loading,\n progress,\n status,\n announce,\n indicator = true,\n shimmer: _shimmer,\n magnetic: _magnetic,\n variant,\n size,\n shape,\n className,\n disabled,\n children,\n ...props\n}: ButtonProps) {\n const Comp = asChild ? Slot.Root : \"button\";\n if (shape === \"cut\") warnCut();\n const known = loading && typeof progress === \"number\" && Number.isFinite(progress);\n const ratio = known ? Math.min(1, Math.max(0, progress)) : 0;\n const glyph = indicator && !asChild && (loading || status) ? (status ?? \"loading\") : null;\n // On a filled variant the glyph stays in the label's colour; on the others it takes the status colour.\n const filled = variant === \"primary\" || variant === \"gradient\";\n const button = (\n <Comp\n type={asChild ? undefined : \"button\"}\n aria-busy={loading || undefined}\n data-loading={loading ? \"\" : undefined}\n data-variant={variant ?? \"secondary\"}\n data-kz-status={status ?? undefined}\n disabled={asChild ? undefined : disabled || loading}\n aria-disabled={asChild && (disabled || loading) ? true : undefined}\n className={buttonVariants({\n variant,\n size,\n shape,\n className: cn(known && \"relative isolate overflow-hidden\", className),\n })}\n {...props}\n >\n {asChild ? (\n children\n ) : (\n <>\n {known && (\n <span aria-hidden className=\"absolute inset-y-0 left-0 -z-10 bg-current opacity-15 transition-[width] duration-500\" style={{ width: `${ratio * 100}%` }} />\n )}\n {glyph && (\n <span\n aria-hidden\n data-slot=\"indicator\"\n className=\"-my-1 grid grid-cols-[1fr] transition-[grid-template-columns,margin,opacity] duration-300 starting:-mr-2 starting:grid-cols-[0fr] starting:opacity-0\"\n >\n <span className=\"overflow-hidden\">\n <LoaderGlyph state={glyph} value={known ? ratio : null} className={cn(\"h-4 w-4\", glyph !== \"loading\" && !filled && STATUS_TEXT[glyph])} />\n </span>\n </span>\n )}\n {children}\n </>\n )}\n </Comp>\n );\n if (announce === undefined || asChild) return button;\n return (\n <>\n {button}\n <span role=\"status\" className=\"sr-only\">\n {announce}\n </span>\n </>\n );\n}\n\nexport type IconButtonProps = Omit<ButtonProps, \"size\"> & {\n /** The accessible name (and tooltip) of the button — required, passed translated. */\n label: string;\n /**\n * sm · md · lg, or `icon` (a square).\n * @default \"icon\"\n */\n size?: ButtonProps[\"size\"];\n};\n\n/** An icon-only button: `label` is required, it is its accessible name. Loading or with a status, the glyph takes the icon's place. */\nexport function IconButton({ label, size = \"icon\", children, ...props }: IconButtonProps) {\n const swap = props.indicator !== false && !props.asChild && (props.loading || props.status);\n return (\n <Button aria-label={label} title={label} size={size} {...props}>\n {swap ? null : children}\n </Button>\n );\n}\n"
|
|
647
647
|
},
|
|
648
648
|
{
|
|
649
649
|
"path": "button/index.ts",
|
|
@@ -651,11 +651,11 @@
|
|
|
651
651
|
},
|
|
652
652
|
{
|
|
653
653
|
"path": "button/meta.ts",
|
|
654
|
-
"content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Button\",\n summary:\n \"The action: six looks, three sizes,
|
|
654
|
+
"content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Button\",\n summary:\n \"The action: six looks, three sizes, two shapes (an 8 px radius, the pill) — and the whole life of an action built in: a wait traced by the loader glyph, its progress, a success or a failure drawn and announced.\",\n status: \"stable\",\n category: \"actions\",\n platforms: \"both\",\n parity: { desktop: \"web\" },\n whenToUse: [\n \"To run an action: submit a form, open a dialog, start an upload, save a draft.\",\n \"One `primary` button for the main action of a view; `secondary`, `outline` or `ghost` for the others.\",\n \"`IconButton` for a compact action shown by its icon alone (close, add, more), with a `label` for its name.\",\n ],\n whenNotToUse: [\n { when: \"To go to another page: use a link (`asChild` with your router's `<Link>` keeps the button look).\" },\n { when: \"To turn a setting on or off, with an immediate effect.\", use: \"switch\" },\n { when: \"For a destructive action that needs a second press to confirm, in place.\", use: \"confirm-button\" },\n { when: \"To choose one option among several, or filter a list.\", use: \"chip\" },\n ],\n bestPractices: [\n \"Name the action with a verb: “Save”, “Send the invitation” — not “OK” or “Yes”.\",\n \"One primary per view; the danger variant only for what destroys or cannot be undone.\",\n \"`loading` while the action runs: the button is disabled, says it is busy and draws the glyph; add `progress` when you know how far it is.\",\n \"End with `status` (`success` / `error`) and `announce` the result in words: sighted people see the check, everyone hears “Saved”. Clear the status after a moment.\",\n \"One shape for every action (an 8 px radius, the radius of a field); the pill only for a chip-like action. The hover changes a colour, never the position. `shape=\\\"cut\\\"`, `shimmer` and `magnetic` are deprecated since 3.31 (krizaka-ui#393) and do nothing.\",\n \"Style a link without the component with `buttonVariants({ variant, size })`.\",\n ],\n accessibility: {\n keyboard: [\n { keys: \"Enter / Space\", action: \"Runs the action.\" },\n { keys: \"Tab\", action: \"Moves the focus to the next control; the focus ring uses `--kz-ring`.\" },\n ],\n notes: [\n \"A native `<button type=\\\"button\\\">`: the role, the focus and the keyboard come from the platform.\",\n \"`IconButton` requires `label`: it becomes the `aria-label` of a button that shows no text.\",\n \"`loading` sets `aria-busy` and disables the button; `disabled` keeps it out of the tab order.\",\n \"`announce` renders a polite live region next to the button: the result of the action is heard, not only seen.\",\n \"Under `prefers-reduced-motion` nothing moves (no shake, no lean, no sheen): the check, the cross and the status colour still say it.\",\n ],\n },\n related: [\"confirm-button\", \"dialog\", \"dropdown-menu\", \"tooltip\"],\n web: {\n imports: [\"Button\", \"IconButton\"],\n examples: [\n { name: \"save-flow\", title: \"Save, then confirm\", description: \"Press it: the glyph traces the wait, a check draws itself, “Changes saved” is announced, then it returns to rest.\" },\n { name: \"upload-progress\", title: \"An export with progress\", description: \"`progress`: the trace and a light fill grow across the button; it keeps its width and its colour.\" },\n { name: \"error\", title: \"A failure\", description: \"`status=\\\"error\\\"`: a cross, one shake of the head, a ring of the danger colour — and the reason announced.\" },\n { name: \"signature\", title: \"The signature action\", description: \"The gradient beside a quiet outline: the one call to action of a hero; the arrow leans forward on hover, the button never moves.\" },\n { name: \"primary\", title: \"Primary\", description: \"The main action of a view: the accent.\" },\n { name: \"gradient\", title: \"Gradient\", description: \"The brand's signature, accent → accent-2: a hero or a closing call to action, once per page.\" },\n { name: \"secondary\", title: \"Secondary\", description: \"The default: a raised surface, for the other actions.\" },\n { name: \"outline\", title: \"Outline\", description: \"A lighter action next to a primary one.\" },\n { name: \"ghost\", title: \"Ghost\", description: \"In toolbars and dense lists: no frame until hovered.\" },\n { name: \"danger\", title: \"Danger\", description: \"A destructive action: the border and the tint carry the danger, the label stays legible in both themes.\" },\n { name: \"sizes\", title: \"Sizes\", description: \"`sm`, `md` (default) and `lg`.\" },\n { name: \"pill\", title: \"Pill\", description: \"`shape=\\\"pill\\\"`: fully rounded.\" },\n { name: \"disabled\", title: \"Disabled\", description: \"Not available yet: out of the tab order.\" },\n { name: \"loading\", title: \"Loading\", description: \"While the action runs: disabled, `aria-busy`, `data-loading`, the glyph before the label.\" },\n { name: \"as-child-link\", title: \"As a link\", description: \"`asChild` renders your `<a>` (or router link) with the button's look.\" },\n { name: \"icon\", title: \"Icon button\", description: \"`IconButton`: a square button holding an icon; `label` is its accessible name.\" },\n ],\n },\n native: {\n imports: [\"Button\", \"IconButton\"],\n differences: [\n \"The text is the `label` prop (a string), not children: it is also the accessible name.\",\n \"`onPress` instead of `onClick` (a `Pressable`); haptics, if any, belong to your `onPress`.\",\n \"`icon` places an icon before the label; there is no `asChild`.\",\n \"`loading` shows the platform's `ActivityIndicator` in place of the icon.\",\n \"`variant=\\\"gradient\\\"` draws its fill with react-native-svg (React Native has no CSS gradient).\",\n ],\n examples: [\n { name: \"primary\", title: \"Primary\", description: \"The main action of a screen.\" },\n { name: \"gradient\", title: \"Gradient\", description: \"accent → accent-2, drawn with react-native-svg: the hero action of a screen.\" },\n { name: \"secondary\", title: \"Secondary\", description: \"The default look.\" },\n { name: \"outline\", title: \"Outline\", description: \"A lighter action.\" },\n { name: \"ghost\", title: \"Ghost\", description: \"No frame: toolbars, headers.\" },\n { name: \"danger\", title: \"Danger\", description: \"A destructive action.\" },\n { name: \"sizes\", title: \"Sizes\", description: \"`sm`, `md`, `lg`, and `shape=\\\"pill\\\"`.\" },\n { name: \"icon\", title: \"With an icon\", description: \"`icon` before the label.\" },\n { name: \"disabled\", title: \"Disabled\", description: \"Not available yet.\" },\n { name: \"loading\", title: \"Loading\", description: \"Disabled and busy, a spinner in place of the icon.\" },\n { name: \"icon-only\", title: \"Icon button\", description: \"`IconButton`: `label` is required, it is the accessible name.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
|
|
655
655
|
},
|
|
656
656
|
{
|
|
657
657
|
"path": "button/recipe.ts",
|
|
658
|
-
"content": "// The button's variants, written once as classes of the Krizaka tokens: the web wears them with `tv(buttonRecipe)`\n// (button.tsx), React Native reads the same classes into styles (native/button.tsx, `nativeRecipe`).\nimport { defineRecipe } from \"../recipes/define\";\n\nexport const buttonRecipe = defineRecipe({\n base:\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-
|
|
658
|
+
"content": "// The button's variants, written once as classes of the Krizaka tokens: the web wears them with `tv(buttonRecipe)`\n// (button.tsx), React Native reads the same classes into styles (native/button.tsx, `nativeRecipe`).\nimport { defineRecipe } from \"../recipes/define\";\n\nexport const buttonRecipe = defineRecipe({\n base:\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition duration-150 \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 \" +\n \"disabled:pointer-events-none disabled:opacity-40 data-loading:cursor-progress active:scale-[0.98] \" +\n // Busy is not unavailable: a loading button keeps its colour (it is disabled only so it is not pressed twice).\n \"[&[data-loading]]:opacity-100\",\n variants: {\n variant: {\n primary: \"bg-accent text-on-accent shadow-sm hover:bg-accent-hover\",\n // The brand's signature: accent → accent-2 (on-accent reads on both stops, tested in @krizaka/tokens).\n gradient: \"bg-linear-to-r from-accent to-accent-2 text-on-accent shadow-sm hover:brightness-110\",\n secondary: \"border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3\",\n outline: \"border border-border-default bg-transparent text-fg hover:border-accent hover:text-fg-accent\",\n ghost: \"text-fg-secondary hover:bg-surface-2 hover:text-fg\",\n // The border and the tint carry the danger; the label stays the primary text role, legible on the tint at rest\n // and hovered over every surface (`text-fg-danger` is for text set directly on a surface).\n danger: \"border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20\",\n },\n size: { sm: \"h-8 px-3 text-xs\", md: \"h-10 px-4 text-sm\", lg: \"h-12 px-6 text-sm\", icon: \"h-10 w-10\" },\n // One clean shape (krizaka-ui#393): an 8 px radius (`--kz-radius-sm`, the radius of a field — a button beside an\n // input lines up with it), the pill on demand. `cut` (the retired chamfer) is a deprecated alias of `rounded`.\n shape: { rounded: \"rounded-sm\", pill: \"rounded-full\", cut: \"rounded-sm\" },\n },\n defaultVariants: { variant: \"secondary\", size: \"md\", shape: \"rounded\" },\n});\n"
|
|
659
659
|
},
|
|
660
660
|
{
|
|
661
661
|
"path": "meta.ts",
|
|
@@ -712,7 +712,7 @@
|
|
|
712
712
|
"name": "magnetic",
|
|
713
713
|
"type": "boolean",
|
|
714
714
|
"default": null,
|
|
715
|
-
"description": "
|
|
715
|
+
"description": "@deprecated Since 3.31 (krizaka-ui#393): does nothing — a button never moves under the pointer. Removed in 4.0.",
|
|
716
716
|
"required": false
|
|
717
717
|
},
|
|
718
718
|
{
|
|
@@ -726,14 +726,14 @@
|
|
|
726
726
|
"name": "shape",
|
|
727
727
|
"type": "\"rounded\" | \"pill\" | \"cut\"",
|
|
728
728
|
"default": "rounded",
|
|
729
|
-
"description": "rounded · pill
|
|
729
|
+
"description": "`rounded` (an 8 px radius, the radius of a field) · `pill`. `cut` is deprecated (krizaka-ui#393: the chamfer is\nretired) — it draws `rounded` and warns in development; it will be removed in 4.0.",
|
|
730
730
|
"required": false
|
|
731
731
|
},
|
|
732
732
|
{
|
|
733
733
|
"name": "shimmer",
|
|
734
734
|
"type": "boolean",
|
|
735
735
|
"default": null,
|
|
736
|
-
"description": "
|
|
736
|
+
"description": "@deprecated Since 3.31 (krizaka-ui#393): does nothing — the hover is quiet. Removed in 4.0.",
|
|
737
737
|
"required": false
|
|
738
738
|
},
|
|
739
739
|
{
|
|
@@ -802,7 +802,7 @@
|
|
|
802
802
|
"name": "magnetic",
|
|
803
803
|
"type": "boolean",
|
|
804
804
|
"default": null,
|
|
805
|
-
"description": "
|
|
805
|
+
"description": "@deprecated Since 3.31 (krizaka-ui#393): does nothing — a button never moves under the pointer. Removed in 4.0.",
|
|
806
806
|
"required": false
|
|
807
807
|
},
|
|
808
808
|
{
|
|
@@ -816,14 +816,14 @@
|
|
|
816
816
|
"name": "shape",
|
|
817
817
|
"type": "\"rounded\" | \"pill\" | \"cut\"",
|
|
818
818
|
"default": "rounded",
|
|
819
|
-
"description": "rounded · pill
|
|
819
|
+
"description": "`rounded` (an 8 px radius, the radius of a field) · `pill`. `cut` is deprecated (krizaka-ui#393: the chamfer is\nretired) — it draws `rounded` and warns in development; it will be removed in 4.0.",
|
|
820
820
|
"required": false
|
|
821
821
|
},
|
|
822
822
|
{
|
|
823
823
|
"name": "shimmer",
|
|
824
824
|
"type": "boolean",
|
|
825
825
|
"default": null,
|
|
826
|
-
"description": "
|
|
826
|
+
"description": "@deprecated Since 3.31 (krizaka-ui#393): does nothing — the hover is quiet. Removed in 4.0.",
|
|
827
827
|
"required": false
|
|
828
828
|
},
|
|
829
829
|
{
|
package/registry/card-grid.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"name": "card-grid",
|
|
3
3
|
"type": "primitive",
|
|
4
4
|
"title": "Card grid",
|
|
5
|
-
"summary": "A responsive grid of cards: as many columns as the width allows (one on a phone), the cells of a row at one height, a staggered reveal
|
|
6
|
-
"description": "A responsive grid of cards: as many columns as the width allows (one on a phone), the cells of a row at one height, a staggered reveal
|
|
5
|
+
"summary": "A responsive grid of cards: as many columns as the width allows (one on a phone), the cells of a row at one height, a staggered reveal; each card keeps its own quiet hover.",
|
|
6
|
+
"description": "A responsive grid of cards: as many columns as the width allows (one on a phone), the cells of a row at one height, a staggered reveal; each card keeps its own quiet hover.",
|
|
7
7
|
"status": "beta",
|
|
8
8
|
"deprecated": null,
|
|
9
9
|
"category": "blocks",
|
|
@@ -42,21 +42,19 @@
|
|
|
42
42
|
"Keep `reveal` on below the first screen, off on it; `columns` makes the stagger restart on each row.",
|
|
43
43
|
"The default `align=\"stretch\"` gives a row one height; the cards pin their foot to the bottom (`LinkCard` facts + way in, `ArgumentCard` actions) so the footers line up. `align=\"start\"` for cards that unfold.",
|
|
44
44
|
"`as=\"ul\"` when the cards are a list of links.",
|
|
45
|
-
"`hover=\"quiet\"` quiets every card of the grid (no glow, a 2 px lift, a ring on focus); a card may still say `hover=\"light\"`.",
|
|
46
45
|
"`foundation` when one thing (an engine, a platform) carries all the others: it takes its own card, wide, above (`foundationPosition=\"end\"` for under), and the cards sit in a hairline frame joined to it. Say the relation with `foundationLabel`; set the hue on `className`."
|
|
47
46
|
],
|
|
48
47
|
"accessibility": {
|
|
49
48
|
"keyboard": [],
|
|
50
49
|
"notes": [
|
|
51
50
|
"The grid adds no role; `as=\"ul\"` makes it a list (each cell an `li`).",
|
|
52
|
-
"
|
|
51
|
+
"Nothing follows the pointer: `light` and `hover` are deprecated since 3.31 (krizaka-ui#393) and do nothing.",
|
|
53
52
|
"Revealed cells are only hidden visually until they enter the viewport; under reduced motion they never move."
|
|
54
53
|
]
|
|
55
54
|
},
|
|
56
55
|
"related": [
|
|
57
56
|
"link-card",
|
|
58
|
-
"argument-card"
|
|
59
|
-
"pointer-light"
|
|
57
|
+
"argument-card"
|
|
60
58
|
],
|
|
61
59
|
"web": {
|
|
62
60
|
"entry": "@krizaka/ui/card-grid",
|
|
@@ -64,7 +62,7 @@
|
|
|
64
62
|
"props": [
|
|
65
63
|
{
|
|
66
64
|
"component": "CardGrid",
|
|
67
|
-
"description": "A responsive grid of cards: equal rows, a staggered reveal
|
|
65
|
+
"description": "A responsive grid of cards: equal rows, a staggered reveal.",
|
|
68
66
|
"props": [
|
|
69
67
|
{
|
|
70
68
|
"name": "children",
|
|
@@ -125,15 +123,15 @@
|
|
|
125
123
|
{
|
|
126
124
|
"name": "hover",
|
|
127
125
|
"type": "CardHover",
|
|
128
|
-
"default":
|
|
129
|
-
"description": "
|
|
126
|
+
"default": null,
|
|
127
|
+
"description": "@deprecated Since 3.31 (krizaka-ui#393): does nothing — every card has the one quiet hover. Removed in 4.0.",
|
|
130
128
|
"required": false
|
|
131
129
|
},
|
|
132
130
|
{
|
|
133
131
|
"name": "light",
|
|
134
132
|
"type": "boolean",
|
|
135
|
-
"default":
|
|
136
|
-
"description": "
|
|
133
|
+
"default": null,
|
|
134
|
+
"description": "@deprecated Since 3.31 (krizaka-ui#393): does nothing — no light follows the pointer. Removed in 4.0.",
|
|
137
135
|
"required": false
|
|
138
136
|
},
|
|
139
137
|
{
|
|
@@ -188,11 +186,11 @@
|
|
|
188
186
|
},
|
|
189
187
|
{
|
|
190
188
|
"name": "hover-quiet",
|
|
191
|
-
"title": "
|
|
192
|
-
"description": "
|
|
189
|
+
"title": "The hover",
|
|
190
|
+
"description": "The grid adds no hover: each card's surface and hairline go one step up, a ring on focus.",
|
|
193
191
|
"path": "examples/card-grid/hover-quiet.tsx",
|
|
194
192
|
"module": "@krizaka/ui/registry/examples/card-grid/hover-quiet",
|
|
195
|
-
"code": "import { ProductLogo } from \"@krizaka/ui\";\nimport { CardGrid } from \"@krizaka/ui/card-grid\";\nimport { LinkCard } from \"@krizaka/ui/link-card\";\n\nconst shortcuts = [\n { id: \"cli\", logo: \"orazaka\", title: \"The CLI\", text: \"npx orazaka install, start, dev — then every command and option.\" },\n { id: \"packs\", logo: \"orazaka\", title: \"Packs & Studios\", text: \"The business offers Orazaka installs without code.\" },\n { id: \"admin\", logo: \"orochia\", title: \"Orochia admin console\", text: \"Verification, moderation, payouts — behind four gates.\" },\n] as const;\n\n// A whole grid quiet: `hover=\"quiet\"` on the grid, the cards inherit it (a card can still say `hover=\"light\"`).\nexport default function CardGridHoverQuiet() {\n return (\n <CardGrid className=\"w-full max-w-4xl\" min={260} reveal={false}
|
|
193
|
+
"code": "import { ProductLogo } from \"@krizaka/ui\";\nimport { CardGrid } from \"@krizaka/ui/card-grid\";\nimport { LinkCard } from \"@krizaka/ui/link-card\";\n\nconst shortcuts = [\n { id: \"cli\", logo: \"orazaka\", title: \"The CLI\", text: \"npx orazaka install, start, dev — then every command and option.\" },\n { id: \"packs\", logo: \"orazaka\", title: \"Packs & Studios\", text: \"The business offers Orazaka installs without code.\" },\n { id: \"admin\", logo: \"orochia\", title: \"Orochia admin console\", text: \"Verification, moderation, payouts — behind four gates.\" },\n] as const;\n\n// A whole grid quiet: `hover=\"quiet\"` on the grid, the cards inherit it (a card can still say `hover=\"light\"`).\nexport default function CardGridHoverQuiet() {\n return (\n <CardGrid className=\"w-full max-w-4xl\" min={260} reveal={false}>\n {shortcuts.map((s) => (\n <LinkCard key={s.id} href={`#${s.id}`} icon={<ProductLogo id={s.logo} size={24} animated={false} />} title={s.title} description={s.text} cta=\"Open\" />\n ))}\n </CardGrid>\n );\n}\n"
|
|
196
194
|
}
|
|
197
195
|
]
|
|
198
196
|
},
|
|
@@ -200,15 +198,15 @@
|
|
|
200
198
|
"files": [
|
|
201
199
|
{
|
|
202
200
|
"path": "card-grid/card-grid.tsx",
|
|
203
|
-
"content": "//
|
|
201
|
+
"content": "// A responsive grid of cards (blocks.css): one column on a phone, the cells of a row share their height, each card rises\n// once as it enters the viewport — staggered by column. The hover is the cards' own quiet one (krizaka-ui#393).\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport type { CardHover } from \"../link-card/link-card\";\n\nconst STEP_MS = 70;\n\nexport type CardGridProps = Omit<React.HTMLAttributes<HTMLElement>, \"children\"> & {\n /** The cards: one cell each. */\n children: React.ReactNode;\n /**\n * The narrowest a column may be, in pixels: the grid fits as many columns as the width allows.\n * @default 300\n */\n min?: number;\n /**\n * `fill` keeps empty tracks (a lone card keeps its width); `fit` stretches the cards of a short row across the width.\n * @default \"fill\"\n */\n fit?: \"fill\" | \"fit\";\n /**\n * `stretch` gives the cells of a row one height; `start` lets each card keep its own (cards that open a panel).\n * @default \"stretch\"\n */\n align?: \"stretch\" | \"start\";\n /**\n * The cards rise once into place (`[data-reveal]`, MotionObserver), staggered by column. `false` on the first screen.\n * @default true\n */\n reveal?: boolean;\n /**\n * The columns the stagger counts (the delay restarts on every row).\n * @default 3\n */\n columns?: number;\n /** @deprecated Since 3.31 (krizaka-ui#393): does nothing — no light follows the pointer. Removed in 4.0. */\n light?: boolean;\n /** `ul` when the cards are a list (each cell an `li`). */\n as?: \"div\" | \"ul\" | \"ol\";\n /**\n * A foundation: one wide card that the cards of the grid stand on (an engine, a platform, a shared service). It spans\n * the full width beside the grid, and a hairline joins it to a frame around the cards — \"everything inside runs on it\".\n * The frame takes the hue of `className` (a `data-hue` or a brand class on the grid sets it for the whole block).\n */\n foundation?: React.ReactNode;\n /**\n * Where the foundation sits: above the cards, or under them.\n * @default \"start\"\n */\n foundationPosition?: \"start\" | \"end\";\n /** A short mono label on the frame's edge, naming the relation (`Powered by Orazaka`). Only with `foundation`. */\n foundationLabel?: React.ReactNode;\n /** @deprecated Since 3.31 (krizaka-ui#393): does nothing — every card has the one quiet hover. Removed in 4.0. */\n hover?: CardHover;\n};\n\n/** A responsive grid of cards: equal rows, a staggered reveal. */\nexport function CardGrid({\n children,\n min = 300,\n fit = \"fill\",\n align = \"stretch\",\n reveal = true,\n columns = 3,\n light: _light,\n as: Tag = \"div\",\n foundation,\n foundationPosition = \"start\",\n foundationLabel,\n hover: _hover,\n className,\n style,\n ...props\n}: CardGridProps) {\n const Cell = Tag === \"div\" ? \"div\" : \"li\";\n const grid = (\n <Tag\n className={cn(\"kz-cards\", !foundation && className)}\n data-fit={fit === \"fit\" ? \"\" : undefined}\n data-align={align === \"start\" ? \"start\" : undefined}\n style={{ \"--kz-cards-min\": `${min}px`, ...(foundation ? null : style) } as React.CSSProperties}\n {...props}\n >\n {React.Children.toArray(children).map((child, i) => {\n const step = Math.min(i % Math.max(columns, 1), 5);\n return (\n <Cell\n key={React.isValidElement(child) && child.key != null ? child.key : i}\n className=\"kz-cards-cell\"\n data-reveal={reveal ? \"\" : undefined}\n style={reveal && step ? ({ \"--kz-delay\": `${step * STEP_MS}ms` } as React.CSSProperties) : undefined}\n >\n {child}\n </Cell>\n );\n })}\n </Tag>\n );\n if (!foundation) return grid;\n return (\n <div className={cn(\"kz-foundation\", className)} data-position={foundationPosition} style={style}>\n <div className=\"kz-foundation-base\" data-reveal={reveal ? \"\" : undefined}>\n {foundation}\n </div>\n <div className=\"kz-foundation-group\">\n {foundationLabel && <span className=\"kz-foundation-label\">{foundationLabel}</span>}\n {grid}\n </div>\n </div>\n );\n}\n\n"
|
|
204
202
|
},
|
|
205
203
|
{
|
|
206
204
|
"path": "card-grid/index.ts",
|
|
207
|
-
"content": "/** @krizaka/ui/card-grid — `CardGrid`: a responsive grid of cards, a staggered reveal, the
|
|
205
|
+
"content": "/** @krizaka/ui/card-grid — `CardGrid`: a responsive grid of cards, a staggered reveal, the cards' quiet hover. Client. */\nexport { CardGrid, type CardGridProps } from \"./card-grid\";\n"
|
|
208
206
|
},
|
|
209
207
|
{
|
|
210
208
|
"path": "card-grid/meta.ts",
|
|
211
|
-
"content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Card grid\",\n summary:\n \"A responsive grid of cards: as many columns as the width allows (one on a phone), the cells of a row at one height, a staggered reveal
|
|
209
|
+
"content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Card grid\",\n summary:\n \"A responsive grid of cards: as many columns as the width allows (one on a phone), the cells of a row at one height, a staggered reveal; each card keeps its own quiet hover.\",\n status: \"beta\",\n category: \"blocks\",\n platforms: \"web\",\n parity: { native: { status: \"n/a\", reason: \"A block of a public site's page; an app screen on a phone is built from Screen, Header and Card.\", use: \"card\" }, desktop: { status: \"n/a\", reason: \"A public site's page, not a window of the Mac app.\" } },\n whenToUse: [\n \"Entry points of a hub (`LinkCard`), the reasons of a product page (`ArgumentCard`), plans, products.\",\n \"Any set of peer cards that should read as one group with one rhythm.\",\n ],\n whenNotToUse: [\n { when: \"For a sequence the reader follows in order.\", use: \"stepper\" },\n { when: \"For rows of data to compare or sort.\", use: \"data-table\" },\n ],\n bestPractices: [\n \"Set `min` to the narrowest a card still reads well; the grid does the rest at every width.\",\n \"`fit=\\\"fit\\\"` for two or three cards that should share the whole width; `fill` keeps a lone card at its size.\",\n \"Keep `reveal` on below the first screen, off on it; `columns` makes the stagger restart on each row.\",\n \"The default `align=\\\"stretch\\\"` gives a row one height; the cards pin their foot to the bottom (`LinkCard` facts + way in, `ArgumentCard` actions) so the footers line up. `align=\\\"start\\\"` for cards that unfold.\",\n \"`as=\\\"ul\\\"` when the cards are a list of links.\",\n \"`foundation` when one thing (an engine, a platform) carries all the others: it takes its own card, wide, above (`foundationPosition=\\\"end\\\"` for under), and the cards sit in a hairline frame joined to it. Say the relation with `foundationLabel`; set the hue on `className`.\",\n ],\n accessibility: {\n keyboard: [],\n notes: [\n \"The grid adds no role; `as=\\\"ul\\\"` makes it a list (each cell an `li`).\",\n \"Nothing follows the pointer: `light` and `hover` are deprecated since 3.31 (krizaka-ui#393) and do nothing.\",\n \"Revealed cells are only hidden visually until they enter the viewport; under reduced motion they never move.\",\n ],\n },\n related: [\"link-card\", \"argument-card\"],\n web: {\n imports: [\"CardGrid\"],\n examples: [\n { name: \"products\", title: \"Two halves\", description: \"`fit=\\\"fit\\\"`: two cards share the whole width.\" },\n { name: \"aligned\", title: \"An aligned row\", description: \"Cards with sentences of different lengths: one height, and the facts and the way in of every card on the same line.\" },\n { name: \"foundation\", title: \"A foundation\", description: \"`foundation`: one wide card the others stand on, a hairline to a frame around them.\" },\n { name: \"reveal\", title: \"A list of sections\", description: \"`as=\\\"ul\\\"`, six links that rise staggered by column on a real page.\" },\n { name: \"hover-quiet\", title: \"The hover\", description: \"The grid adds no hover: each card's surface and hairline go one step up, a ring on focus.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
|
|
212
210
|
},
|
|
213
211
|
{
|
|
214
212
|
"path": "meta.ts",
|
|
@@ -218,8 +216,7 @@
|
|
|
218
216
|
"dependencies": [],
|
|
219
217
|
"registryDependencies": [
|
|
220
218
|
"cn",
|
|
221
|
-
"link-card"
|
|
222
|
-
"pointer-light"
|
|
219
|
+
"link-card"
|
|
223
220
|
],
|
|
224
221
|
"demo": {
|
|
225
222
|
"path": "examples/card-grid/products.tsx",
|
|
@@ -228,7 +225,7 @@
|
|
|
228
225
|
"props": [
|
|
229
226
|
{
|
|
230
227
|
"component": "CardGrid",
|
|
231
|
-
"description": "A responsive grid of cards: equal rows, a staggered reveal
|
|
228
|
+
"description": "A responsive grid of cards: equal rows, a staggered reveal.",
|
|
232
229
|
"props": [
|
|
233
230
|
{
|
|
234
231
|
"name": "children",
|
|
@@ -289,15 +286,15 @@
|
|
|
289
286
|
{
|
|
290
287
|
"name": "hover",
|
|
291
288
|
"type": "CardHover",
|
|
292
|
-
"default":
|
|
293
|
-
"description": "
|
|
289
|
+
"default": null,
|
|
290
|
+
"description": "@deprecated Since 3.31 (krizaka-ui#393): does nothing — every card has the one quiet hover. Removed in 4.0.",
|
|
294
291
|
"required": false
|
|
295
292
|
},
|
|
296
293
|
{
|
|
297
294
|
"name": "light",
|
|
298
295
|
"type": "boolean",
|
|
299
|
-
"default":
|
|
300
|
-
"description": "
|
|
296
|
+
"default": null,
|
|
297
|
+
"description": "@deprecated Since 3.31 (krizaka-ui#393): does nothing — no light follows the pointer. Removed in 4.0.",
|
|
301
298
|
"required": false
|
|
302
299
|
},
|
|
303
300
|
{
|
package/registry/card.json
CHANGED
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"name": "interactive",
|
|
83
83
|
"type": "boolean",
|
|
84
84
|
"default": null,
|
|
85
|
-
"description": "The
|
|
85
|
+
"description": "The quiet hover — the hairline and the surface one step up, nothing moves (krizaka-ui#393): for a card that is a link.",
|
|
86
86
|
"required": false
|
|
87
87
|
},
|
|
88
88
|
{
|
|
@@ -221,10 +221,10 @@
|
|
|
221
221
|
{
|
|
222
222
|
"name": "interactive-link",
|
|
223
223
|
"title": "Interactive link",
|
|
224
|
-
"description": "`asChild` + `<a>`: the whole card is a link
|
|
224
|
+
"description": "`asChild` + `<a>`: the whole card is a link; its hairline and surface go one step up under the pointer.",
|
|
225
225
|
"path": "examples/card/interactive-link.tsx",
|
|
226
226
|
"module": "@krizaka/ui/registry/examples/card/interactive-link",
|
|
227
|
-
"code": "import { Card } from \"@krizaka/ui/card\";\n\n// `asChild` + `<a>`: the whole card is one link; `interactive` adds the
|
|
227
|
+
"code": "import { Card } from \"@krizaka/ui/card\";\n\n// `asChild` + `<a>`: the whole card is one link; `interactive` adds the quiet hover (a hairline and surface step).\nexport default function CardInteractiveLink() {\n return (\n <Card.Root asChild interactive>\n <a href=\"#guide\">\n <Card.Body>\n <Card.Title as=\"h2\">Getting started</Card.Title>\n <Card.Description>Install the preset, import the primitives, ship both themes.</Card.Description>\n <Card.Footer>Read the guide →</Card.Footer>\n </Card.Body>\n </a>\n </Card.Root>\n );\n}\n"
|
|
228
228
|
},
|
|
229
229
|
{
|
|
230
230
|
"name": "stat-card",
|
|
@@ -425,7 +425,7 @@
|
|
|
425
425
|
"files": [
|
|
426
426
|
{
|
|
427
427
|
"path": "card/card.tsx",
|
|
428
|
-
"content": "// Server-safe: no hook, no context. One `tv` definition with slots: each part takes its slot, and a product overrides\n// any part through `className` (merged last by tailwind-merge).\nimport { Slot } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { cardRecipe } from \"./recipe\";\n\nexport const card = tv(cardRecipe);\n\ntype CardVariants = VariantProps<typeof card>;\n/** The parts without a variant read the default slots: no context, so server-safe. */\nconst slots = card();\n\nexport type CardRootProps = React.ComponentProps<\"div\"> &\n Pick<CardVariants, \"radius\" | \"tone\" | \"interactive\"> & {\n /**\n * md · lg · xl.\n * @default \"xl\"\n */\n radius?: CardVariants[\"radius\"];\n /**\n * default (the base surface) · elevated (raised, a shadow) · glass (translucent, blurred).\n * @default \"default\"\n */\n tone?: CardVariants[\"tone\"];\n /** The
|
|
428
|
+
"content": "// Server-safe: no hook, no context. One `tv` definition with slots: each part takes its slot, and a product overrides\n// any part through `className` (merged last by tailwind-merge).\nimport { Slot } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { cardRecipe } from \"./recipe\";\n\nexport const card = tv(cardRecipe);\n\ntype CardVariants = VariantProps<typeof card>;\n/** The parts without a variant read the default slots: no context, so server-safe. */\nconst slots = card();\n\nexport type CardRootProps = React.ComponentProps<\"div\"> &\n Pick<CardVariants, \"radius\" | \"tone\" | \"interactive\"> & {\n /**\n * md · lg · xl.\n * @default \"xl\"\n */\n radius?: CardVariants[\"radius\"];\n /**\n * default (the base surface) · elevated (raised, a shadow) · glass (translucent, blurred).\n * @default \"default\"\n */\n tone?: CardVariants[\"tone\"];\n /** The quiet hover — the hairline and the surface one step up, nothing moves (krizaka-ui#393): for a card that is a link. */\n interactive?: CardVariants[\"interactive\"];\n /** Renders the child (a link, an article) instead of the <div>, with props, classes and ref merged. */\n asChild?: boolean;\n /** Enters on scroll (MotionObserver): the index in the grid becomes the delay (50 ms a step, 8 steps at most). */\n reveal?: number;\n };\n\nexport function CardRoot({ asChild, reveal, radius, tone, interactive, className, style, ...props }: CardRootProps) {\n const Comp = asChild ? Slot.Root : \"div\";\n const revealStyle =\n reveal === undefined ? style : ({ ...style, \"--kz-delay\": `${Math.min(Math.max(reveal, 0), 8) * 50}ms` } as React.CSSProperties);\n return (\n <Comp\n data-reveal={reveal === undefined ? undefined : \"\"}\n data-interactive={interactive ? \"\" : undefined}\n style={revealStyle}\n className={card({ radius, tone, interactive }).root({ className })}\n {...props}\n />\n );\n}\n\nconst ASPECT = { video: \"aspect-video\", square: \"aspect-square\", portrait: \"aspect-[3/4]\", auto: \"\" } as const;\nexport type CardMediaProps = React.ComponentProps<\"div\"> & {\n /** The ratio of the media: video (16:9) · square · portrait (3:4) · auto (the content's). */\n aspect?: keyof typeof ASPECT;\n};\n\nexport function CardMedia({ aspect = \"video\", className, ...props }: CardMediaProps) {\n return <div data-aspect={aspect} className={slots.media({ className: cn(ASPECT[aspect], className) })} {...props} />;\n}\n\nexport type CardImageProps = Omit<React.ComponentProps<\"img\">, \"src\"> & {\n /** The image's URL; `null` or nothing shows the `fallback`. */\n src?: string | null;\n /** Shown when there is no image: an icon, an illustration (decorative). */\n fallback?: React.ReactNode;\n /**\n * When the browser loads it: `lazy` (default, a card in a list or below the fold) or `eager` for the first cards\n * of a page — the image that is the largest contentful paint must not wait (add `fetchPriority=\"high\"`).\n * @default \"lazy\"\n */\n loading?: \"lazy\" | \"eager\";\n};\n\n/** The image of a media, or its `fallback` when there is none. `alt` is empty by default: the title names the card. */\nexport function CardImage({ src, alt = \"\", fallback, loading = \"lazy\", className, ...props }: CardImageProps) {\n if (!src) {\n return (\n <div data-fallback=\"\" aria-hidden className={slots.fallback({ className })}>\n {fallback}\n </div>\n );\n }\n return <img src={src} alt={alt} loading={loading} decoding=\"async\" className={slots.image({ className })} {...props} />;\n}\n\nconst CORNER = {\n \"top-left\": \"left-2.5 top-2.5\",\n \"top-right\": \"right-2.5 top-2.5\",\n \"bottom-left\": \"bottom-2.5 left-2.5\",\n \"bottom-right\": \"bottom-2.5 right-2.5\",\n} as const;\nexport type CardOverlayProps = React.ComponentProps<\"div\"> & {\n /** The corner of the media it sits in. */\n corner?: keyof typeof CORNER;\n};\n\n/** What sits on the media (badges, a caption). `scrim` and `fg-on-media` are invariant: nothing to do for light. */\nexport function CardOverlay({ corner = \"top-left\", className, ...props }: CardOverlayProps) {\n return <div data-corner={corner} className={slots.overlay({ className: cn(CORNER[corner], className) })} {...props} />;\n}\n\nexport type CardBodyProps = React.ComponentProps<\"div\"> & {\n /**\n * none · sm · md · lg.\n * @default \"md\"\n */\n padding?: CardVariants[\"padding\"];\n};\n\nexport function CardBody({ padding, className, ...props }: CardBodyProps) {\n return <div className={card({ padding }).body({ className })} {...props} />;\n}\n\nexport type CardTitleProps = React.ComponentProps<\"h3\"> & {\n /** The heading level, to fit the page's outline. */\n as?: \"h2\" | \"h3\" | \"h4\";\n};\n\nexport function CardTitle({ as: Tag = \"h3\", className, ...props }: CardTitleProps) {\n return <Tag className={slots.title({ className })} {...props} />;\n}\n\nexport function CardDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return <p className={slots.description({ className })} {...props} />;\n}\n\nexport type CardStatProps = React.ComponentProps<\"div\"> & {\n /** What the figure is, in small capitals above it (the figure is the children). */\n label: React.ReactNode;\n};\n\n/** A figure put forward: the label in capitals, the value in tabular digits. */\nexport function CardStat({ label, className, children, ...props }: CardStatProps) {\n return (\n <div className={slots.stat({ className })} {...props}>\n <p className={slots.statLabel()}>{label}</p>\n <p className={slots.statValue()}>{children}</p>\n </div>\n );\n}\n\nexport function CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={slots.footer({ className })} {...props} />;\n}\n\n/** `Card.Root/Media/Image/Overlay/Body/Title/Description/Stat/Footer`. */\nexport const Card = {\n Root: CardRoot,\n Media: CardMedia,\n Image: CardImage,\n Overlay: CardOverlay,\n Body: CardBody,\n Title: CardTitle,\n Description: CardDescription,\n Stat: CardStat,\n Footer: CardFooter,\n};\n"
|
|
429
429
|
},
|
|
430
430
|
{
|
|
431
431
|
"path": "card/index.ts",
|
|
@@ -433,11 +433,11 @@
|
|
|
433
433
|
},
|
|
434
434
|
{
|
|
435
435
|
"path": "card/meta.ts",
|
|
436
|
-
"content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Card\",\n summary: \"The composed chassis of every card: a media with overlays, a body with a title, a description, stats and a footer.\",\n status: \"stable\",\n category: \"layout\",\n platforms: \"both\",\n parity: { desktop: \"web\" },\n whenToUse: [\n \"To present one item of a collection: a video, a creator, a guide, a plan.\",\n \"As a link to the item (`asChild` + `interactive`): the whole card is one target.\",\n \"To group a few figures under a title (`Card.Stat`).\",\n ],\n whenNotToUse: [\n { when: \"To frame a whole page section: use the page layout, not a card around everything.\" },\n { when: \"For a single key figure without a frame.\", use: \"stat\" },\n { when: \"For a message about the page.\", use: \"alert\" },\n ],\n bestPractices: [\n \"Build product cards from these parts and override any of them with `className` — never fork the card.\",\n \"Keep one primary target per card: either the whole card is a link, or it holds buttons — not both.\",\n \"Give `Card.Media` a fixed `aspect` so a grid stays aligned while images load.\",\n \"`Card.Image` loads lazily; pass `loading=\\\"eager\\\"` (and `fetchPriority=\\\"high\\\"`) to the first cards of a page, above the fold.\",\n \"`reveal={index}` with one `MotionObserver` per page for the entrance; it is shown at once under reduced motion.\",\n ],\n accessibility: {\n keyboard: [{ keys: \"Tab / Enter\", action: \"An `asChild` link card is one focusable link that Enter follows.\" }],\n notes: [\n \"`Card.Title` is a heading (`h3` by default, `as` to change the level) so cards are reachable by heading.\",\n \"A card that is a link is named by its content: keep the title first.\",\n \"The image fallback is decorative and hidden from assistive technology.\",\n ],\n },\n related: [\"badge\", \"stat\", \"avatar\", \"skeleton\"],\n web: {\n imports: [\"Card\"],\n examples: [\n { name: \"media-card\", title: \"Media card\", description: \"An image, badges on the media, a title, a description and a footer.\" },\n { name: \"media-fallback\", title: \"Media fallback\", description: \"No image: the `fallback` on the accent gradient.\" },\n { name: \"interactive-link\", title: \"Interactive link\", description: \"`asChild` + `<a>`: the whole card is a link
|
|
436
|
+
"content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Card\",\n summary: \"The composed chassis of every card: a media with overlays, a body with a title, a description, stats and a footer.\",\n status: \"stable\",\n category: \"layout\",\n platforms: \"both\",\n parity: { desktop: \"web\" },\n whenToUse: [\n \"To present one item of a collection: a video, a creator, a guide, a plan.\",\n \"As a link to the item (`asChild` + `interactive`): the whole card is one target.\",\n \"To group a few figures under a title (`Card.Stat`).\",\n ],\n whenNotToUse: [\n { when: \"To frame a whole page section: use the page layout, not a card around everything.\" },\n { when: \"For a single key figure without a frame.\", use: \"stat\" },\n { when: \"For a message about the page.\", use: \"alert\" },\n ],\n bestPractices: [\n \"Build product cards from these parts and override any of them with `className` — never fork the card.\",\n \"Keep one primary target per card: either the whole card is a link, or it holds buttons — not both.\",\n \"Give `Card.Media` a fixed `aspect` so a grid stays aligned while images load.\",\n \"`Card.Image` loads lazily; pass `loading=\\\"eager\\\"` (and `fetchPriority=\\\"high\\\"`) to the first cards of a page, above the fold.\",\n \"`reveal={index}` with one `MotionObserver` per page for the entrance; it is shown at once under reduced motion.\",\n ],\n accessibility: {\n keyboard: [{ keys: \"Tab / Enter\", action: \"An `asChild` link card is one focusable link that Enter follows.\" }],\n notes: [\n \"`Card.Title` is a heading (`h3` by default, `as` to change the level) so cards are reachable by heading.\",\n \"A card that is a link is named by its content: keep the title first.\",\n \"The image fallback is decorative and hidden from assistive technology.\",\n ],\n },\n related: [\"badge\", \"stat\", \"avatar\", \"skeleton\"],\n web: {\n imports: [\"Card\"],\n examples: [\n { name: \"media-card\", title: \"Media card\", description: \"An image, badges on the media, a title, a description and a footer.\" },\n { name: \"media-fallback\", title: \"Media fallback\", description: \"No image: the `fallback` on the accent gradient.\" },\n { name: \"interactive-link\", title: \"Interactive link\", description: \"`asChild` + `<a>`: the whole card is a link; its hairline and surface go one step up under the pointer.\" },\n { name: \"stat-card\", title: \"Stat card\", description: \"Figures put forward with `Card.Stat`, `tone=\\\"elevated\\\"`.\" },\n { name: \"reveal-grid\", title: \"Reveal grid\", description: \"Cards entering in cascade with `reveal` and `MotionObserver`.\" },\n ],\n },\n native: {\n imports: [\"Card\"],\n differences: [\n \"`onPress` on `Card.Root` makes the whole card a button (no `asChild`, no `interactive`).\",\n \"Built on `View`, `Image` and `Text`: style with `style`, not `className`.\",\n \"No `Card.Stat` and no `reveal`.\",\n ],\n examples: [\n { name: \"default\", title: \"Default\", description: \"A media, a body and a footer.\" },\n { name: \"elevated\", title: \"Elevated\", description: \"`tone=\\\"elevated\\\"`: one step higher, with a shadow.\" },\n { name: \"pressable\", title: \"Pressable\", description: \"`onPress`: the whole card is a button.\" },\n { name: \"body\", title: \"Text and an action\", description: \"A body only, with a button.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
|
|
437
437
|
},
|
|
438
438
|
{
|
|
439
439
|
"path": "card/recipe.ts",
|
|
440
|
-
"content": "// The card's parts, radii, tones and paddings, written once as classes of the Krizaka tokens: the web wears them with\n// `tv(cardRecipe)`, React Native reads the same classes into styles (native/card.tsx): a part of the card that exists only\n// on the web (the
|
|
440
|
+
"content": "// The card's parts, radii, tones and paddings, written once as classes of the Krizaka tokens: the web wears them with\n// `tv(cardRecipe)`, React Native reads the same classes into styles (native/card.tsx): a part of the card that exists only\n// on the web (the hover's tint) is simply ignored there.\nimport { defineRecipe } from \"../recipes/define\";\n\nexport const cardRecipe = defineRecipe({\n slots: {\n root:\n \"group relative flex flex-col overflow-hidden border border-border-default bg-surface-1 text-fg transition-colors \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n media: \"relative overflow-hidden bg-media\",\n image: \"h-full w-full object-cover\",\n fallback: \"flex h-full w-full items-center justify-center bg-linear-to-br from-accent/15 via-media to-accent-2/15 text-accent/60\",\n overlay: \"absolute z-10 flex items-center gap-1.5\",\n body: \"relative flex flex-1 flex-col gap-3\",\n title: \"line-clamp-1 text-sm font-semibold text-fg transition-colors group-hover:text-fg-accent\",\n description: \"line-clamp-2 text-xs text-fg-secondary\",\n stat: \"min-w-0\",\n statLabel: \"text-[10px] font-semibold uppercase tracking-wider text-fg-secondary\",\n statValue: \"font-display text-xl font-black tabular-nums text-fg\",\n footer: \"relative mt-auto flex items-center gap-2 border-t border-border-subtle pt-3 text-xs text-fg-secondary\",\n },\n variants: {\n radius: { md: { root: \"rounded-md\" }, lg: { root: \"rounded-lg\" }, xl: { root: \"rounded-xl\" } },\n tone: { default: {}, elevated: { root: \"bg-surface-2 shadow-md\" }, glass: { root: \"bg-surface-1/70 backdrop-blur-md\" } },\n interactive: { true: { root: \"duration-150 hover:border-border-strong hover:bg-surface-2\" } },\n padding: { none: { body: \"p-0\" }, sm: { body: \"p-3\" }, md: { body: \"p-4\" }, lg: { body: \"p-6\" } },\n },\n defaultVariants: { radius: \"xl\", tone: \"default\", padding: \"md\" },\n});\n"
|
|
441
441
|
},
|
|
442
442
|
{
|
|
443
443
|
"path": "meta.ts",
|
|
@@ -472,7 +472,7 @@
|
|
|
472
472
|
"name": "interactive",
|
|
473
473
|
"type": "boolean",
|
|
474
474
|
"default": null,
|
|
475
|
-
"description": "The
|
|
475
|
+
"description": "The quiet hover — the hairline and the surface one step up, nothing moves (krizaka-ui#393): for a card that is a link.",
|
|
476
476
|
"required": false
|
|
477
477
|
},
|
|
478
478
|
{
|
|
@@ -136,7 +136,7 @@
|
|
|
136
136
|
"why": "A builder decides whether a component fits, sees it live and copies it, all on one page.",
|
|
137
137
|
"path": "examples/component-page/button.tsx",
|
|
138
138
|
"module": "@krizaka/ui/registry/examples/component-page/button",
|
|
139
|
-
"code": "import { Button } from \"@krizaka/ui/button\";\nimport { ComponentPage } from \"@krizaka/ui/component-page\";\nimport { LinkCard } from \"@krizaka/ui/link-card\";\n\n// TEMPLATE — a component's page (what ui.krizaka.com generates from the registry): name, summary, status and\n// platforms, the live preview, the import line, its sections; related components aside (under it on a phone).\nexport default function ComponentPageButton() {\n return (\n <ComponentPage\n className=\"w-full\"\n back={<a href=\"#catalogue\">← Components</a>}\n eyebrow=\"Actions\"\n title=\"Button\"\n summary=\"The action: six looks, three sizes, the Krizaka cut, and the whole life of an action built in.\"\n facts={[{ label: \"Web + Mobile\", tone: \"ok\" }, { label: \"Stable\" }]}\n preview={\n <div className=\"flex flex-wrap items-center justify-center gap-3 p-8\">\n <Button variant=\"primary\"
|
|
139
|
+
"code": "import { Button } from \"@krizaka/ui/button\";\nimport { ComponentPage } from \"@krizaka/ui/component-page\";\nimport { LinkCard } from \"@krizaka/ui/link-card\";\n\n// TEMPLATE — a component's page (what ui.krizaka.com generates from the registry): name, summary, status and\n// platforms, the live preview, the import line, its sections; related components aside (under it on a phone).\nexport default function ComponentPageButton() {\n return (\n <ComponentPage\n className=\"w-full\"\n back={<a href=\"#catalogue\">← Components</a>}\n eyebrow=\"Actions\"\n title=\"Button\"\n summary=\"The action: six looks, three sizes, the Krizaka cut, and the whole life of an action built in.\"\n facts={[{ label: \"Web + Mobile\", tone: \"ok\" }, { label: \"Stable\" }]}\n preview={\n <div className=\"flex flex-wrap items-center justify-center gap-3 p-8\">\n <Button variant=\"primary\">Publish</Button>\n <Button variant=\"secondary\">Save a draft</Button>\n </div>\n }\n install={{ code: 'import { Button } from \"@krizaka/ui/button\";', language: \"ts\", copyLabel: \"Copy\", copiedLabel: \"Copied\" }}\n sections={[\n { id: \"when\", title: \"When to use\", children: <p className=\"text-sm text-fg-secondary\">For the action a block is about; links that look like actions use `asChild`.</p> },\n { id: \"a11y\", title: \"Accessibility\", children: <p className=\"text-sm text-fg-secondary\">A real button; while loading it says so in a live region.</p> },\n ]}\n aside={<LinkCard href=\"#confirm-button\" title=\"Confirm button\" description=\"A destructive action in two presses.\" titleAs=\"span\" />}\n />\n );\n}\n"
|
|
140
140
|
}
|
|
141
141
|
]
|
|
142
142
|
},
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
],
|
|
168
168
|
"demo": {
|
|
169
169
|
"path": "examples/component-page/button.tsx",
|
|
170
|
-
"content": "import { Button } from \"@krizaka/ui/button\";\nimport { ComponentPage } from \"@krizaka/ui/component-page\";\nimport { LinkCard } from \"@krizaka/ui/link-card\";\n\n// TEMPLATE — a component's page (what ui.krizaka.com generates from the registry): name, summary, status and\n// platforms, the live preview, the import line, its sections; related components aside (under it on a phone).\nexport default function ComponentPageButton() {\n return (\n <ComponentPage\n className=\"w-full\"\n back={<a href=\"#catalogue\">← Components</a>}\n eyebrow=\"Actions\"\n title=\"Button\"\n summary=\"The action: six looks, three sizes, the Krizaka cut, and the whole life of an action built in.\"\n facts={[{ label: \"Web + Mobile\", tone: \"ok\" }, { label: \"Stable\" }]}\n preview={\n <div className=\"flex flex-wrap items-center justify-center gap-3 p-8\">\n <Button variant=\"primary\"
|
|
170
|
+
"content": "import { Button } from \"@krizaka/ui/button\";\nimport { ComponentPage } from \"@krizaka/ui/component-page\";\nimport { LinkCard } from \"@krizaka/ui/link-card\";\n\n// TEMPLATE — a component's page (what ui.krizaka.com generates from the registry): name, summary, status and\n// platforms, the live preview, the import line, its sections; related components aside (under it on a phone).\nexport default function ComponentPageButton() {\n return (\n <ComponentPage\n className=\"w-full\"\n back={<a href=\"#catalogue\">← Components</a>}\n eyebrow=\"Actions\"\n title=\"Button\"\n summary=\"The action: six looks, three sizes, the Krizaka cut, and the whole life of an action built in.\"\n facts={[{ label: \"Web + Mobile\", tone: \"ok\" }, { label: \"Stable\" }]}\n preview={\n <div className=\"flex flex-wrap items-center justify-center gap-3 p-8\">\n <Button variant=\"primary\">Publish</Button>\n <Button variant=\"secondary\">Save a draft</Button>\n </div>\n }\n install={{ code: 'import { Button } from \"@krizaka/ui/button\";', language: \"ts\", copyLabel: \"Copy\", copiedLabel: \"Copied\" }}\n sections={[\n { id: \"when\", title: \"When to use\", children: <p className=\"text-sm text-fg-secondary\">For the action a block is about; links that look like actions use `asChild`.</p> },\n { id: \"a11y\", title: \"Accessibility\", children: <p className=\"text-sm text-fg-secondary\">A real button; while loading it says so in a live region.</p> },\n ]}\n aside={<LinkCard href=\"#confirm-button\" title=\"Confirm button\" description=\"A destructive action in two presses.\" titleAs=\"span\" />}\n />\n );\n}\n"
|
|
171
171
|
},
|
|
172
172
|
"props": [
|
|
173
173
|
{
|