@expokit/cli 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +32 -2
- package/bin/expo-kit.js +1204 -0
- package/bin/lib.mjs +343 -0
- package/bin/mcp.mjs +338 -0
- package/package.json +44 -4
- package/registry/_docs/accordion.json +99 -0
- package/registry/_docs/action-sheet.json +110 -0
- package/registry/_docs/alert.json +127 -0
- package/registry/_docs/avatar.json +203 -0
- package/registry/_docs/badge.json +117 -0
- package/registry/_docs/bottom-nav.json +119 -0
- package/registry/_docs/bottom-sheet.json +158 -0
- package/registry/_docs/bullet.json +24 -0
- package/registry/_docs/button-3d.json +122 -0
- package/registry/_docs/button.json +115 -0
- package/registry/_docs/calendar.json +182 -0
- package/registry/_docs/card-stack.json +108 -0
- package/registry/_docs/card.json +111 -0
- package/registry/_docs/carousel.json +102 -0
- package/registry/_docs/checkbox.json +93 -0
- package/registry/_docs/checkout.json +102 -0
- package/registry/_docs/chip-group.json +116 -0
- package/registry/_docs/color-swatch.json +66 -0
- package/registry/_docs/confetti.json +82 -0
- package/registry/_docs/coupon.json +176 -0
- package/registry/_docs/cube-pager.json +84 -0
- package/registry/_docs/dashboard.json +120 -0
- package/registry/_docs/date-picker.json +249 -0
- package/registry/_docs/dialog.json +162 -0
- package/registry/_docs/drawer.json +171 -0
- package/registry/_docs/fab.json +120 -0
- package/registry/_docs/flip-card.json +111 -0
- package/registry/_docs/floating-input.json +191 -0
- package/registry/_docs/gift-card.json +108 -0
- package/registry/_docs/glass-button.json +118 -0
- package/registry/_docs/glass-nav-bar.json +78 -0
- package/registry/_docs/glass-search-bar.json +90 -0
- package/registry/_docs/glass-segmented.json +66 -0
- package/registry/_docs/glass-sheet.json +108 -0
- package/registry/_docs/glass-tab-bar.json +76 -0
- package/registry/_docs/glass.json +78 -0
- package/registry/_docs/inbox.json +72 -0
- package/registry/_docs/isometric-bar.json +72 -0
- package/registry/_docs/kit.json +11 -0
- package/registry/_docs/kpi-card.json +11 -0
- package/registry/_docs/like-button.json +72 -0
- package/registry/_docs/liquidglass-tab.json +27 -0
- package/registry/_docs/list-item.json +200 -0
- package/registry/_docs/loyalty-card.json +108 -0
- package/registry/_docs/morph-button.json +108 -0
- package/registry/_docs/number-ticker.json +96 -0
- package/registry/_docs/offers.json +78 -0
- package/registry/_docs/onboarding.json +66 -0
- package/registry/_docs/otp-input.json +134 -0
- package/registry/_docs/pagination-dots.json +88 -0
- package/registry/_docs/parallax-layers.json +84 -0
- package/registry/_docs/parallax-scroll.json +186 -0
- package/registry/_docs/password-input.json +92 -0
- package/registry/_docs/payment-card.json +153 -0
- package/registry/_docs/pixel-bar.json +66 -0
- package/registry/_docs/polar-area.json +78 -0
- package/registry/_docs/profile.json +84 -0
- package/registry/_docs/progress-steps.json +92 -0
- package/registry/_docs/progress.json +132 -0
- package/registry/_docs/radio-group.json +92 -0
- package/registry/_docs/rating.json +90 -0
- package/registry/_docs/ring-carousel.json +102 -0
- package/registry/_docs/scratch-card.json +90 -0
- package/registry/_docs/search-bar.json +140 -0
- package/registry/_docs/search-results.json +120 -0
- package/registry/_docs/segmented-control.json +103 -0
- package/registry/_docs/select.json +252 -0
- package/registry/_docs/settings.json +72 -0
- package/registry/_docs/shimmer-button.json +78 -0
- package/registry/_docs/sign-in.json +198 -0
- package/registry/_docs/skeleton.json +142 -0
- package/registry/_docs/slide-to-confirm.json +84 -0
- package/registry/_docs/slider.json +157 -0
- package/registry/_docs/spin-wheel.json +114 -0
- package/registry/_docs/spinner.json +91 -0
- package/registry/_docs/stepper.json +168 -0
- package/registry/_docs/swipe-deck.json +102 -0
- package/registry/_docs/swipeable-row.json +72 -0
- package/registry/_docs/switch.json +104 -0
- package/registry/_docs/tabs.json +105 -0
- package/registry/_docs/tag-input.json +128 -0
- package/registry/_docs/textarea.json +175 -0
- package/registry/_docs/ticket-card.json +174 -0
- package/registry/_docs/ticket-shape.json +11 -0
- package/registry/_docs/tilt-card.json +141 -0
- package/registry/_docs/time-picker.json +253 -0
- package/registry/_docs/timeline-chart.json +30 -0
- package/registry/_docs/timeline.json +156 -0
- package/registry/_docs/toast.json +161 -0
- package/registry/_docs/treemap.json +30 -0
- package/registry/_docs/waterfall.json +36 -0
- package/registry/_docs/wheel-list.json +102 -0
- package/registry/accordion/files/src/components/ui/accordion.tsx +233 -0
- package/registry/accordion/files/src/lib/kit.tsx +219 -0
- package/registry/accordion.json +17 -0
- package/registry/action-sheet/files/src/components/ui/action-sheet.tsx +580 -0
- package/registry/action-sheet/files/src/lib/kit.tsx +219 -0
- package/registry/action-sheet.json +18 -0
- package/registry/alert/files/src/components/ui/alert.tsx +654 -0
- package/registry/alert/files/src/components/ui/button.tsx +274 -0
- package/registry/alert/files/src/lib/kit.tsx +219 -0
- package/registry/alert.json +20 -0
- package/registry/avatar/files/src/components/ui/avatar.tsx +790 -0
- package/registry/avatar/files/src/lib/kit.tsx +219 -0
- package/registry/avatar.json +18 -0
- package/registry/badge/files/src/components/ui/badge.tsx +316 -0
- package/registry/badge/files/src/lib/kit.tsx +219 -0
- package/registry/badge.json +17 -0
- package/registry/bottom-nav/files/src/components/ui/bottom-nav.tsx +1050 -0
- package/registry/bottom-nav/files/src/lib/kit.tsx +219 -0
- package/registry/bottom-nav.json +18 -0
- package/registry/bottom-sheet/files/src/components/ui/bottom-sheet.tsx +585 -0
- package/registry/bottom-sheet/files/src/lib/kit.tsx +219 -0
- package/registry/bottom-sheet.json +17 -0
- package/registry/bullet.json +14 -0
- package/registry/button/files/src/components/ui/button.tsx +274 -0
- package/registry/button/files/src/lib/kit.tsx +219 -0
- package/registry/button-3d/files/src/components/ui/button-3d.tsx +212 -0
- package/registry/button-3d/files/src/lib/kit.tsx +219 -0
- package/registry/button-3d.json +18 -0
- package/registry/button.json +18 -0
- package/registry/calendar/files/src/components/ui/calendar.tsx +822 -0
- package/registry/calendar/files/src/lib/kit.tsx +219 -0
- package/registry/calendar.json +17 -0
- package/registry/card/files/src/components/ui/card.tsx +300 -0
- package/registry/card/files/src/lib/kit.tsx +219 -0
- package/registry/card-stack.json +15 -0
- package/registry/card.json +17 -0
- package/registry/carousel.json +15 -0
- package/registry/checkbox/files/src/components/ui/checkbox.tsx +150 -0
- package/registry/checkbox/files/src/lib/kit.tsx +219 -0
- package/registry/checkbox.json +17 -0
- package/registry/checkout.json +26 -0
- package/registry/chip-group/files/src/components/ui/chip-group.tsx +269 -0
- package/registry/chip-group/files/src/lib/kit.tsx +219 -0
- package/registry/chip-group.json +17 -0
- package/registry/color-swatch.json +17 -0
- package/registry/confetti/files/src/components/ui/confetti.tsx +222 -0
- package/registry/confetti/files/src/lib/kit.tsx +219 -0
- package/registry/confetti.json +15 -0
- package/registry/coupon/files/src/components/ui/coupon.tsx +698 -0
- package/registry/coupon/files/src/components/ui/flip-card.tsx +205 -0
- package/registry/coupon/files/src/components/ui/tilt-card.tsx +635 -0
- package/registry/coupon/files/src/lib/kit.tsx +219 -0
- package/registry/coupon/files/src/lib/ticket-shape.tsx +543 -0
- package/registry/coupon.json +23 -0
- package/registry/cube-pager.json +15 -0
- package/registry/dashboard.json +32 -0
- package/registry/date-picker/files/src/components/ui/calendar.tsx +822 -0
- package/registry/date-picker/files/src/components/ui/date-picker.tsx +796 -0
- package/registry/date-picker/files/src/lib/kit.tsx +219 -0
- package/registry/date-picker.json +19 -0
- package/registry/dialog/files/src/components/ui/dialog.tsx +759 -0
- package/registry/dialog/files/src/lib/kit.tsx +219 -0
- package/registry/dialog.json +18 -0
- package/registry/drawer/files/src/components/ui/drawer.tsx +1135 -0
- package/registry/drawer/files/src/lib/kit.tsx +219 -0
- package/registry/drawer.json +18 -0
- package/registry/fab.json +18 -0
- package/registry/flip-card/files/src/components/ui/flip-card.tsx +205 -0
- package/registry/flip-card/files/src/lib/kit.tsx +219 -0
- package/registry/flip-card.json +15 -0
- package/registry/floating-input/files/src/components/ui/floating-input.tsx +528 -0
- package/registry/floating-input/files/src/lib/kit.tsx +219 -0
- package/registry/floating-input.json +17 -0
- package/registry/gift-card.json +21 -0
- package/registry/glass-button.json +22 -0
- package/registry/glass-nav-bar.json +21 -0
- package/registry/glass-search-bar.json +21 -0
- package/registry/glass-segmented.json +22 -0
- package/registry/glass-sheet.json +22 -0
- package/registry/glass-tab-bar.json +22 -0
- package/registry/glass.json +19 -0
- package/registry/inbox.json +30 -0
- package/registry/isometric-bar.json +14 -0
- package/registry/kit/files/src/lib/kit.tsx +219 -0
- package/registry/kit.json +11 -0
- package/registry/kpi-card/files/src/components/charts/kpi-card.tsx +45 -0
- package/registry/kpi-card.json +14 -0
- package/registry/like-button.json +18 -0
- package/registry/liquidglass-tab/files/src/app/(tabs)/_layout.tsx +97 -0
- package/registry/liquidglass-tab/files/src/app/(tabs)/alerts.tsx +5 -0
- package/registry/liquidglass-tab/files/src/app/(tabs)/explore.tsx +5 -0
- package/registry/liquidglass-tab/files/src/app/(tabs)/index.tsx +5 -0
- package/registry/liquidglass-tab/files/src/app/(tabs)/profile.tsx +5 -0
- package/registry/liquidglass-tab/files/src/app/_layout.tsx +33 -0
- package/registry/liquidglass-tab/files/src/components/GlassTabBar.tsx +259 -0
- package/registry/liquidglass-tab/files/src/components/TabScreen.tsx +122 -0
- package/registry/liquidglass-tab/files/src/lib/tab-bar.ts +61 -0
- package/registry/liquidglass-tab/files/src/lib/tab-icons.ts +130 -0
- package/registry/liquidglass-tab/files/src/lib/tabs.ts +108 -0
- package/registry/liquidglass-tab.json +23 -0
- package/registry/list-item/files/src/components/ui/list-item.tsx +508 -0
- package/registry/list-item/files/src/lib/kit.tsx +219 -0
- package/registry/list-item.json +17 -0
- package/registry/loyalty-card.json +23 -0
- package/registry/morph-button.json +18 -0
- package/registry/number-ticker.json +15 -0
- package/registry/offers.json +24 -0
- package/registry/onboarding.json +17 -0
- package/registry/otp-input/files/src/components/ui/otp-input.tsx +380 -0
- package/registry/otp-input/files/src/lib/kit.tsx +219 -0
- package/registry/otp-input.json +17 -0
- package/registry/pagination-dots/files/src/components/ui/pagination-dots.tsx +262 -0
- package/registry/pagination-dots/files/src/lib/kit.tsx +219 -0
- package/registry/pagination-dots.json +15 -0
- package/registry/parallax-layers.json +15 -0
- package/registry/parallax-scroll.json +17 -0
- package/registry/password-input/files/src/components/ui/floating-input.tsx +528 -0
- package/registry/password-input/files/src/components/ui/password-input.tsx +271 -0
- package/registry/password-input/files/src/lib/kit.tsx +219 -0
- package/registry/password-input.json +19 -0
- package/registry/payment-card/files/src/components/ui/flip-card.tsx +205 -0
- package/registry/payment-card/files/src/components/ui/payment-card.tsx +385 -0
- package/registry/payment-card/files/src/components/ui/tilt-card.tsx +635 -0
- package/registry/payment-card/files/src/lib/kit.tsx +219 -0
- package/registry/payment-card.json +21 -0
- package/registry/pixel-bar.json +14 -0
- package/registry/polar-area.json +14 -0
- package/registry/profile.json +17 -0
- package/registry/progress/files/src/components/ui/progress.tsx +883 -0
- package/registry/progress/files/src/lib/kit.tsx +219 -0
- package/registry/progress-steps/files/src/components/ui/progress-steps.tsx +559 -0
- package/registry/progress-steps/files/src/lib/kit.tsx +219 -0
- package/registry/progress-steps.json +18 -0
- package/registry/progress.json +17 -0
- package/registry/radio-group/files/src/components/ui/radio-group.tsx +327 -0
- package/registry/radio-group/files/src/lib/kit.tsx +219 -0
- package/registry/radio-group.json +18 -0
- package/registry/rating.json +18 -0
- package/registry/ring-carousel.json +15 -0
- package/registry/scratch-card.json +18 -0
- package/registry/search-bar/files/src/components/ui/search-bar.tsx +530 -0
- package/registry/search-bar/files/src/lib/kit.tsx +219 -0
- package/registry/search-bar.json +17 -0
- package/registry/search-results.json +30 -0
- package/registry/segmented-control/files/src/components/ui/segmented-control.tsx +341 -0
- package/registry/segmented-control/files/src/lib/kit.tsx +219 -0
- package/registry/segmented-control.json +18 -0
- package/registry/select/files/src/components/ui/select.tsx +1398 -0
- package/registry/select/files/src/lib/kit.tsx +219 -0
- package/registry/select.json +17 -0
- package/registry/settings.json +26 -0
- package/registry/shimmer-button.json +17 -0
- package/registry/sign-in.json +26 -0
- package/registry/skeleton/files/src/components/ui/skeleton.tsx +799 -0
- package/registry/skeleton/files/src/lib/kit.tsx +219 -0
- package/registry/skeleton.json +17 -0
- package/registry/slide-to-confirm.json +18 -0
- package/registry/slider/files/src/components/ui/slider.tsx +716 -0
- package/registry/slider/files/src/lib/kit.tsx +219 -0
- package/registry/slider.json +17 -0
- package/registry/spin-wheel.json +18 -0
- package/registry/spinner/files/src/components/ui/spinner.tsx +335 -0
- package/registry/spinner/files/src/lib/kit.tsx +219 -0
- package/registry/spinner.json +17 -0
- package/registry/stepper/files/src/components/ui/stepper.tsx +646 -0
- package/registry/stepper/files/src/lib/kit.tsx +219 -0
- package/registry/stepper.json +17 -0
- package/registry/swipe-deck.json +15 -0
- package/registry/swipeable-row.json +15 -0
- package/registry/switch/files/src/components/ui/switch.tsx +344 -0
- package/registry/switch/files/src/lib/kit.tsx +219 -0
- package/registry/switch.json +18 -0
- package/registry/tabs/files/src/components/ui/tabs.tsx +539 -0
- package/registry/tabs/files/src/lib/kit.tsx +219 -0
- package/registry/tabs.json +17 -0
- package/registry/tag-input/files/src/components/ui/tag-input.tsx +720 -0
- package/registry/tag-input/files/src/lib/kit.tsx +219 -0
- package/registry/tag-input.json +17 -0
- package/registry/textarea/files/src/components/ui/textarea.tsx +553 -0
- package/registry/textarea/files/src/lib/kit.tsx +219 -0
- package/registry/textarea.json +17 -0
- package/registry/ticket-card.json +24 -0
- package/registry/ticket-shape/files/src/lib/kit.tsx +219 -0
- package/registry/ticket-shape/files/src/lib/ticket-shape.tsx +543 -0
- package/registry/ticket-shape.json +17 -0
- package/registry/tilt-card/files/src/components/ui/tilt-card.tsx +635 -0
- package/registry/tilt-card/files/src/lib/kit.tsx +219 -0
- package/registry/tilt-card.json +17 -0
- package/registry/time-picker/files/src/components/ui/time-picker.tsx +1159 -0
- package/registry/time-picker/files/src/lib/kit.tsx +219 -0
- package/registry/time-picker.json +17 -0
- package/registry/timeline/files/src/components/ui/avatar.tsx +790 -0
- package/registry/timeline/files/src/components/ui/timeline.tsx +1059 -0
- package/registry/timeline/files/src/lib/kit.tsx +219 -0
- package/registry/timeline-chart.json +14 -0
- package/registry/timeline.json +20 -0
- package/registry/toast/files/src/components/ui/button.tsx +274 -0
- package/registry/toast/files/src/components/ui/toast.tsx +1284 -0
- package/registry/toast/files/src/lib/kit.tsx +219 -0
- package/registry/toast.json +20 -0
- package/registry/treemap.json +14 -0
- package/registry/waterfall.json +14 -0
- package/registry/wheel-list.json +17 -0
- package/schema/components.schema.json +13 -0
package/package.json
CHANGED
|
@@ -1,6 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expokit/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "shadcn-style CLI for Expo — add native UI blocks and components to your app",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"expo-kit": "bin/expo-kit.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"registry",
|
|
13
|
+
"schema",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"keywords": [
|
|
17
|
+
"expo",
|
|
18
|
+
"react-native",
|
|
19
|
+
"cli",
|
|
20
|
+
"ui",
|
|
21
|
+
"shadcn",
|
|
22
|
+
"liquid-glass",
|
|
23
|
+
"native-tabs",
|
|
24
|
+
"expo-router"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://expokit.karandev.in",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/Anshkaran7/expokit.git",
|
|
33
|
+
"directory": "packages/cli"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/Anshkaran7/expokit/issues"
|
|
37
|
+
},
|
|
38
|
+
"author": "anshkaran7",
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"test": "node --test test/*.test.mjs",
|
|
44
|
+
"prepublishOnly": "node ../../scripts/build-registry.mjs"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "accordion",
|
|
3
|
+
"category": "Display",
|
|
4
|
+
"aliases": [],
|
|
5
|
+
"exportName": "Accordion",
|
|
6
|
+
"files": [
|
|
7
|
+
"src/components/ui/accordion.tsx"
|
|
8
|
+
],
|
|
9
|
+
"props": [
|
|
10
|
+
[
|
|
11
|
+
"type",
|
|
12
|
+
"\"single\" | \"multiple\"",
|
|
13
|
+
"\"single\"",
|
|
14
|
+
"One open item at a time, or any number."
|
|
15
|
+
],
|
|
16
|
+
[
|
|
17
|
+
"value / defaultValue",
|
|
18
|
+
"string[]",
|
|
19
|
+
"[]",
|
|
20
|
+
"Open item values (controlled / uncontrolled)."
|
|
21
|
+
],
|
|
22
|
+
[
|
|
23
|
+
"onValueChange",
|
|
24
|
+
"(value: string[]) => void",
|
|
25
|
+
"—",
|
|
26
|
+
"Called when items open or close."
|
|
27
|
+
],
|
|
28
|
+
[
|
|
29
|
+
"collapsible",
|
|
30
|
+
"boolean",
|
|
31
|
+
"true",
|
|
32
|
+
"Single mode: allow closing the open item."
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
"variant",
|
|
36
|
+
"\"default\" | \"bordered\" | \"separated\"",
|
|
37
|
+
"\"default\"",
|
|
38
|
+
"Divided list, one bordered box, or separate cards."
|
|
39
|
+
],
|
|
40
|
+
[
|
|
41
|
+
"accent",
|
|
42
|
+
"string",
|
|
43
|
+
"theme accent",
|
|
44
|
+
"Chevron colour of open items."
|
|
45
|
+
],
|
|
46
|
+
[
|
|
47
|
+
"AccordionItem.value",
|
|
48
|
+
"string",
|
|
49
|
+
"—",
|
|
50
|
+
"Identifies the item in the Accordion's value array."
|
|
51
|
+
],
|
|
52
|
+
[
|
|
53
|
+
"AccordionItem.title / subtitle",
|
|
54
|
+
"ReactNode / string",
|
|
55
|
+
"—",
|
|
56
|
+
"Header text."
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
"AccordionItem.icon",
|
|
60
|
+
"ReactNode",
|
|
61
|
+
"—",
|
|
62
|
+
"Leading icon; content indents to line up with the title."
|
|
63
|
+
],
|
|
64
|
+
[
|
|
65
|
+
"AccordionItem.disabled",
|
|
66
|
+
"boolean",
|
|
67
|
+
"false",
|
|
68
|
+
"Can't be toggled."
|
|
69
|
+
],
|
|
70
|
+
[
|
|
71
|
+
"style",
|
|
72
|
+
"StyleProp<ViewStyle>",
|
|
73
|
+
"—",
|
|
74
|
+
"Style for the Accordion's root view (the card in the bordered variant); AccordionItem takes its own."
|
|
75
|
+
]
|
|
76
|
+
],
|
|
77
|
+
"examples": [
|
|
78
|
+
{
|
|
79
|
+
"name": "Default",
|
|
80
|
+
"title": "Default",
|
|
81
|
+
"code": "import { Accordion, AccordionItem } from '@/components/ui/accordion';\n\nexport default function Default() {\n return (\n <Accordion defaultValue={['shipping']}>\n <AccordionItem value=\"shipping\" title=\"How long does shipping take?\">\n Orders leave our warehouse within 24 hours. Standard delivery takes 3–5 business days; express arrives the next day in most cities.\n </AccordionItem>\n <AccordionItem value=\"returns\" title=\"Can I return an item?\">\n Yes — you have 30 days to send anything back for a full refund. Return labels are free and printable from your order page.\n </AccordionItem>\n <AccordionItem value=\"warranty\" title=\"Is there a warranty?\">\n Every product comes with a two-year warranty covering manufacturing defects.\n </AccordionItem>\n </Accordion>\n );\n}\n"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "Bordered",
|
|
85
|
+
"title": "Bordered",
|
|
86
|
+
"code": "import { Accordion, AccordionItem } from '@/components/ui/accordion';\n\nexport default function Bordered() {\n return (\n <Accordion variant=\"bordered\" type=\"multiple\" defaultValue={['account']}>\n <AccordionItem value=\"account\" title=\"Account\" subtitle=\"Email, password, two-factor\">\n Change your sign-in email, rotate your password and manage the devices that can approve logins.\n </AccordionItem>\n <AccordionItem value=\"billing\" title=\"Billing\" subtitle=\"Plan, invoices, payment method\">\n You are on the Pro plan, renewing on 14 November. Invoices are emailed to finance@northwind.io.\n </AccordionItem>\n <AccordionItem value=\"danger\" title=\"Delete workspace\" subtitle=\"Owners only\" disabled>\n This can't be undone.\n </AccordionItem>\n </Accordion>\n );\n}\n"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "SeparatedCards",
|
|
90
|
+
"title": "Separated Cards",
|
|
91
|
+
"code": "import { Text, View } from 'react-native';\nimport { Accordion, AccordionItem } from '@/components/ui/accordion';\n\nexport default function SeparatedCards() {\n return (\n <Accordion variant=\"separated\">\n {[\n ['🔒', 'Is my data encrypted?', 'Everything is encrypted in transit with TLS 1.3 and at rest with AES-256. Keys rotate every 90 days.'],\n ['💳', 'Do you offer refunds?', 'If ExpoKit is not for you, email us within 14 days of purchase and we will refund you in full.'],\n ['🌍', 'Which regions do you host in?', 'Frankfurt, Virginia and Singapore. Pick a region when you create a project.'],\n ].map(([icon, q, a]) => (\n <AccordionItem key={q} value={q} title={q} icon={<Text style={{ fontSize: 18 }}>{icon}</Text>}>\n {a}\n </AccordionItem>\n ))}\n </Accordion>\n );\n}\n"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "Controlled",
|
|
95
|
+
"title": "Controlled",
|
|
96
|
+
"code": "import React, { useState } from 'react';\nimport { Text, View } from 'react-native';\nimport { Accordion, AccordionItem } from '@/components/ui/accordion';\nimport { useKit } from '@/lib/kit';\n\nexport default function Controlled() {\n const { colors } = useKit();\n const [open, setOpen] = useState<string[]>([]);\n return (\n <View style={{ gap: 10 }}>\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>Open: {open.length ? open.join(', ') : 'none'}</Text>\n <Accordion variant=\"bordered\" type=\"multiple\" value={open} onValueChange={setOpen}>\n <AccordionItem value=\"Ingredients\" title=\"Ingredients\">\n <View style={{ gap: 6 }}>\n {['200 g spaghetti', '2 egg yolks + 1 whole egg', '60 g pecorino romano', '120 g guanciale', 'Black pepper'].map((x) => (\n <Text key={x} style={{ fontSize: 14.5, color: colors.mutedForeground }}>• {x}</Text>\n ))}\n </View>\n </AccordionItem>\n <AccordionItem value=\"Method\" title=\"Method\">\n Crisp the guanciale, toss with hot pasta off the heat, then stir in the egg and cheese with a splash of pasta water until glossy.\n </AccordionItem>\n </Accordion>\n </View>\n );\n}\n"
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "action-sheet",
|
|
3
|
+
"category": "Overlays",
|
|
4
|
+
"aliases": [],
|
|
5
|
+
"exportName": "ActionSheet",
|
|
6
|
+
"files": [
|
|
7
|
+
"src/components/ui/action-sheet.tsx"
|
|
8
|
+
],
|
|
9
|
+
"props": [
|
|
10
|
+
[
|
|
11
|
+
"open / defaultOpen",
|
|
12
|
+
"boolean",
|
|
13
|
+
"false",
|
|
14
|
+
"Controlled / uncontrolled visibility."
|
|
15
|
+
],
|
|
16
|
+
[
|
|
17
|
+
"onOpenChange",
|
|
18
|
+
"(open: boolean) => void",
|
|
19
|
+
"—",
|
|
20
|
+
"Called on actions, Cancel, backdrop tap, drag-down, back and Escape."
|
|
21
|
+
],
|
|
22
|
+
[
|
|
23
|
+
"actions",
|
|
24
|
+
"{ label, icon?, destructive?, disabled?, color?, onPress? }[]",
|
|
25
|
+
"—",
|
|
26
|
+
"The options. `icon` is a built-in name (camera, image, trash, reply, forward, copy, pin, edit, share, link, mail, …) or a node; destructive rows use the danger colour; return false from onPress to stay open; `color` tints grid tiles."
|
|
27
|
+
],
|
|
28
|
+
[
|
|
29
|
+
"title / message",
|
|
30
|
+
"string",
|
|
31
|
+
"—",
|
|
32
|
+
"Header text above the actions."
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
"cancelLabel",
|
|
36
|
+
"string | null",
|
|
37
|
+
"\"Cancel\"",
|
|
38
|
+
"Separate cancel button; null hides it."
|
|
39
|
+
],
|
|
40
|
+
[
|
|
41
|
+
"onCancel",
|
|
42
|
+
"() => void",
|
|
43
|
+
"—",
|
|
44
|
+
"Called on Cancel, backdrop tap and drag-to-dismiss."
|
|
45
|
+
],
|
|
46
|
+
[
|
|
47
|
+
"variant",
|
|
48
|
+
"\"inset\" | \"list\" | \"grid\"",
|
|
49
|
+
"\"inset\"",
|
|
50
|
+
"iOS grouped cards (text-only rows centred in the accent; rows with icons read like a menu), Material edge-to-edge list with a drag handle, or share-sheet tiles."
|
|
51
|
+
],
|
|
52
|
+
[
|
|
53
|
+
"bottomInset",
|
|
54
|
+
"number",
|
|
55
|
+
"platform safe inset",
|
|
56
|
+
"Padding above the home indicator; pass useSafeAreaInsets().bottom for the device."
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
"accent",
|
|
60
|
+
"string",
|
|
61
|
+
"theme accent",
|
|
62
|
+
"Colour of text-only actions and Cancel in the inset variant."
|
|
63
|
+
],
|
|
64
|
+
[
|
|
65
|
+
"dismissible",
|
|
66
|
+
"boolean",
|
|
67
|
+
"true",
|
|
68
|
+
"Close on scrim tap, drag, back and Escape. When false the sheet only rubber-bands."
|
|
69
|
+
],
|
|
70
|
+
[
|
|
71
|
+
"haptics",
|
|
72
|
+
"boolean",
|
|
73
|
+
"true",
|
|
74
|
+
"Light impact on open, selection tick when an action is picked."
|
|
75
|
+
],
|
|
76
|
+
[
|
|
77
|
+
"style",
|
|
78
|
+
"StyleProp<ViewStyle>",
|
|
79
|
+
"—",
|
|
80
|
+
"Sheet container style."
|
|
81
|
+
]
|
|
82
|
+
],
|
|
83
|
+
"examples": [
|
|
84
|
+
{
|
|
85
|
+
"name": "Photo",
|
|
86
|
+
"title": "Photo",
|
|
87
|
+
"code": "import React, { useState } from 'react';\nimport { Pressable, Text, View } from 'react-native';\nimport { ActionSheet } from '@/components/ui/action-sheet';\nimport { Avatar } from '@/components/ui/avatar';\nimport { readableOn, useKit } from '@/lib/kit';\n\nfunction useMuted() {\n const { colors } = useKit();\n return { fontSize: 13, color: colors.mutedForeground, textAlign: 'center' as const };\n}\n\nexport default function Photo() {\n const muted = useMuted();\n const [open, setOpen] = useState(false);\n const [status, setStatus] = useState('Tap the photo to change it');\n return (\n <View style={{ alignItems: 'center', gap: 12 }}>\n <Avatar name=\"Maya Patel\" size=\"xl\" ring=\"accent\" onPress={() => setOpen(true)} />\n <Text style={muted}>{status}</Text>\n <ActionSheet\n open={open}\n onOpenChange={setOpen}\n title=\"Profile photo\"\n message=\"Your photo is visible to everyone in Northwind.\"\n actions={[\n { label: 'Take photo', onPress: () => setStatus('Opening camera…') },\n { label: 'Choose from library', onPress: () => setStatus('Opening library…') },\n { label: 'Remove photo', destructive: true, onPress: () => setStatus('Photo removed') },\n ]}\n />\n </View>\n );\n}\n"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"name": "MessageActions",
|
|
91
|
+
"title": "Message Actions",
|
|
92
|
+
"code": "import React, { useState } from 'react';\nimport { Pressable, Text, View } from 'react-native';\nimport { ActionSheet } from '@/components/ui/action-sheet';\nimport { readableOn, useKit } from '@/lib/kit';\n\nfunction useMuted() {\n const { colors } = useKit();\n return { fontSize: 13, color: colors.mutedForeground, textAlign: 'center' as const };\n}\n\nexport default function MessageActions() {\n const { colors, radius } = useKit();\n const muted = useMuted();\n const [open, setOpen] = useState(false);\n const [pinned, setPinned] = useState(false);\n const [status, setStatus] = useState('Long-press the message');\n return (\n <View style={{ alignSelf: 'stretch', gap: 12, paddingHorizontal: 16 }}>\n <Pressable\n onLongPress={() => setOpen(true)}\n delayLongPress={300}\n accessibilityRole=\"button\"\n accessibilityHint=\"Long-press for message actions\"\n style={({ pressed }) => ({\n alignSelf: 'flex-end',\n maxWidth: '82%',\n paddingHorizontal: 14,\n paddingVertical: 10,\n borderRadius: radius.scale(20),\n borderBottomRightRadius: radius.scale(6),\n backgroundColor: colors.accent,\n transform: [{ scale: pressed ? 0.97 : 1 }],\n })}\n >\n <Text style={{ color: readableOn(colors.accent), fontSize: 15, lineHeight: 20 }}>\n Running 10 min late — grab us a table by the window?\n </Text>\n </Pressable>\n <Text style={muted}>{status}</Text>\n <ActionSheet\n open={open}\n onOpenChange={setOpen}\n actions={[\n { label: 'Reply', icon: 'reply', onPress: () => setStatus('Replying to Maya') },\n { label: 'Forward', icon: 'forward', onPress: () => setStatus('Choose a chat') },\n { label: 'Copy text', icon: 'copy', onPress: () => setStatus('Copied to clipboard') },\n {\n label: pinned ? 'Unpin' : 'Pin',\n icon: 'pin',\n onPress: () => {\n setPinned((p) => !p);\n setStatus(pinned ? 'Unpinned' : 'Pinned to the top of the chat');\n },\n },\n { label: 'Edit', icon: 'edit', disabled: true },\n { label: 'Delete for everyone', icon: 'trash', destructive: true, onPress: () => setStatus('Message deleted') },\n ]}\n />\n </View>\n );\n}\n"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"name": "Share",
|
|
96
|
+
"title": "Share",
|
|
97
|
+
"code": "import React, { useState } from 'react';\nimport { Pressable, Text, View } from 'react-native';\nimport { ActionSheet } from '@/components/ui/action-sheet';\nimport { Button } from '@/components/ui/button';\nimport { readableOn, useKit } from '@/lib/kit';\n\nexport default function Share() {\n const { colors } = useKit();\n const [open, setOpen] = useState(false);\n return (\n <View style={{ alignItems: 'center' }}>\n <Button variant=\"accent\" onPress={() => setOpen(true)}>\n Share trip\n </Button>\n <ActionSheet\n open={open}\n onOpenChange={setOpen}\n variant=\"grid\"\n title=\"Share “Lisbon, May 12–16”\"\n actions={[\n { label: 'Messages', icon: 'message', color: colors.success },\n { label: 'Mail', icon: 'mail', color: colors.accent },\n { label: 'Send to…', icon: 'send', color: colors.primary },\n { label: 'Copy link', icon: 'link' },\n { label: 'Save PDF', icon: 'download' },\n { label: 'Print', icon: 'printer' },\n { label: 'Invite', icon: 'user' },\n { label: 'More', icon: 'more' },\n ]}\n />\n </View>\n );\n}\n"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "PostOptions",
|
|
101
|
+
"title": "Post Options",
|
|
102
|
+
"code": "import React, { useState } from 'react';\nimport { Pressable, Text, View } from 'react-native';\nimport { ActionSheet } from '@/components/ui/action-sheet';\nimport { Button } from '@/components/ui/button';\nimport { readableOn, useKit } from '@/lib/kit';\n\nfunction useMuted() {\n const { colors } = useKit();\n return { fontSize: 13, color: colors.mutedForeground, textAlign: 'center' as const };\n}\n\nexport default function PostOptions() {\n const muted = useMuted();\n const [open, setOpen] = useState(false);\n const [saved, setSaved] = useState(false);\n return (\n <View style={{ alignItems: 'center', gap: 10 }}>\n <Button variant=\"outline\" onPress={() => setOpen(true)}>\n Post options\n </Button>\n <Text style={muted}>{saved ? 'Saved to your collection' : 'Material list with icons'}</Text>\n <ActionSheet\n open={open}\n onOpenChange={setOpen}\n variant=\"list\"\n title=\"Jonas’s post\"\n cancelLabel={null}\n actions={[\n { label: 'Edit post', icon: 'edit' },\n { label: saved ? 'Remove from saved' : 'Save post', icon: 'bookmark', onPress: () => setSaved((s) => !s) },\n { label: 'Copy link', icon: 'copy' },\n { label: 'Hide from feed', icon: 'eye-off' },\n { label: 'Report post', icon: 'flag', destructive: true },\n ]}\n />\n </View>\n );\n}\n"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "DiscardDraft",
|
|
106
|
+
"title": "Discard Draft",
|
|
107
|
+
"code": "import React, { useState } from 'react';\nimport { Pressable, Text, View } from 'react-native';\nimport { ActionSheet } from '@/components/ui/action-sheet';\nimport { Button } from '@/components/ui/button';\nimport { readableOn, useKit } from '@/lib/kit';\n\nfunction useMuted() {\n const { colors } = useKit();\n return { fontSize: 13, color: colors.mutedForeground, textAlign: 'center' as const };\n}\n\nexport default function DiscardDraft() {\n const muted = useMuted();\n const [open, setOpen] = useState(false);\n const [result, setResult] = useState('');\n return (\n <View style={{ alignItems: 'center', gap: 10 }}>\n <Button variant=\"secondary\" onPress={() => setOpen(true)}>\n Close editor\n </Button>\n {result ? <Text style={muted}>{result}</Text> : null}\n <ActionSheet\n open={open}\n onOpenChange={setOpen}\n message=\"You have unsaved changes to “Weekly update”. Save them as a draft?\"\n onCancel={() => setResult('Kept editing')}\n cancelLabel=\"Keep editing\"\n actions={[\n { label: 'Discard changes', destructive: true, onPress: () => setResult('Changes discarded') },\n { label: 'Save draft', onPress: () => setResult('Draft saved') },\n { label: 'Schedule post', disabled: true },\n ]}\n />\n </View>\n );\n}\n"
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "alert",
|
|
3
|
+
"category": "Feedback",
|
|
4
|
+
"aliases": [],
|
|
5
|
+
"exportName": "Alert",
|
|
6
|
+
"files": [
|
|
7
|
+
"src/components/ui/alert.tsx"
|
|
8
|
+
],
|
|
9
|
+
"props": [
|
|
10
|
+
[
|
|
11
|
+
"variant",
|
|
12
|
+
"\"info\" | \"success\" | \"warning\" | \"danger\"",
|
|
13
|
+
"\"info\"",
|
|
14
|
+
"Tone and living icon."
|
|
15
|
+
],
|
|
16
|
+
[
|
|
17
|
+
"appearance",
|
|
18
|
+
"\"soft\" | \"outline\" | \"solid\" | \"accent-bar\"",
|
|
19
|
+
"\"soft\"",
|
|
20
|
+
"Card with a tone glow behind the icon, transparent with a hairline tone border, or filled with the solid tone. \"accent-bar\" is deprecated and renders as \"soft\"."
|
|
21
|
+
],
|
|
22
|
+
[
|
|
23
|
+
"title",
|
|
24
|
+
"string",
|
|
25
|
+
"—",
|
|
26
|
+
"First line. Without a title (and without actions) the alert uses the compact single-line layout."
|
|
27
|
+
],
|
|
28
|
+
[
|
|
29
|
+
"description",
|
|
30
|
+
"ReactNode",
|
|
31
|
+
"—",
|
|
32
|
+
"Supporting text."
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
"action",
|
|
36
|
+
"{ label, onPress } | ReactNode",
|
|
37
|
+
"—",
|
|
38
|
+
"One action: a tone pill under the text, or an inline pill on the right in the compact layout."
|
|
39
|
+
],
|
|
40
|
+
[
|
|
41
|
+
"actions",
|
|
42
|
+
"{ primary: { label, onPress }, secondary?: { label, onPress } }",
|
|
43
|
+
"—",
|
|
44
|
+
"Pill pair on the bottom row; primary is filled with the tone."
|
|
45
|
+
],
|
|
46
|
+
[
|
|
47
|
+
"icon",
|
|
48
|
+
"ReactNode | false",
|
|
49
|
+
"living tone icon",
|
|
50
|
+
"Custom icon (shown in the halo) or none."
|
|
51
|
+
],
|
|
52
|
+
[
|
|
53
|
+
"dismissible",
|
|
54
|
+
"boolean",
|
|
55
|
+
"false",
|
|
56
|
+
"Show a 28pt close button (44pt hit area) that collapses the alert."
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
"duration",
|
|
60
|
+
"number (ms)",
|
|
61
|
+
"—",
|
|
62
|
+
"Auto-dismiss. A hairline drains along the bottom edge; pauses while pressed or hovered."
|
|
63
|
+
],
|
|
64
|
+
[
|
|
65
|
+
"visible",
|
|
66
|
+
"boolean",
|
|
67
|
+
"—",
|
|
68
|
+
"Controlled visibility (animated)."
|
|
69
|
+
],
|
|
70
|
+
[
|
|
71
|
+
"onDismiss",
|
|
72
|
+
"() => void",
|
|
73
|
+
"—",
|
|
74
|
+
"Called when closed by the button or when `duration` runs out."
|
|
75
|
+
],
|
|
76
|
+
[
|
|
77
|
+
"haptics",
|
|
78
|
+
"boolean",
|
|
79
|
+
"false",
|
|
80
|
+
"Notification haptic (success / warning / error) when the alert appears."
|
|
81
|
+
],
|
|
82
|
+
[
|
|
83
|
+
"color",
|
|
84
|
+
"string",
|
|
85
|
+
"tone colour",
|
|
86
|
+
"Override the tone colour."
|
|
87
|
+
],
|
|
88
|
+
[
|
|
89
|
+
"style",
|
|
90
|
+
"StyleProp<ViewStyle>",
|
|
91
|
+
"—",
|
|
92
|
+
"Style for the outer animated wrapper (its height collapses on dismiss)."
|
|
93
|
+
]
|
|
94
|
+
],
|
|
95
|
+
"examples": [
|
|
96
|
+
{
|
|
97
|
+
"name": "Soft",
|
|
98
|
+
"title": "Soft",
|
|
99
|
+
"code": "import { Text, View } from 'react-native';\nimport { Alert } from '@/components/ui/alert';\n\nexport default function Soft() {\n return (\n <View style={{ gap: 10 }}>\n <Alert variant=\"info\" title=\"New sign-in method\" description=\"You can now use a passkey instead of your password.\" />\n <Alert variant=\"success\" title=\"Payment received\" description=\"₹1,24,000 from Northwind Traders.\" />\n <Alert variant=\"warning\" title=\"Storage almost full\" description=\"You've used 9.4 GB of your 10 GB plan.\" />\n <Alert variant=\"danger\" title=\"Sync failed\" description=\"We couldn't reach the server. Your edits are saved on this device.\" />\n </View>\n );\n}\n"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"name": "Appearances",
|
|
103
|
+
"title": "Appearances",
|
|
104
|
+
"code": "import { Text, View } from 'react-native';\nimport { Alert } from '@/components/ui/alert';\n\nexport default function Appearances() {\n return (\n <View style={{ gap: 10 }}>\n <Alert variant=\"info\" appearance=\"outline\" title=\"Scheduled maintenance\" description=\"Sunday 02:00–03:00 UTC.\" />\n <Alert variant=\"danger\" appearance=\"outline\" title=\"2 failed sign-in attempts\" description=\"Chrome on Windows · Berlin, DE\" />\n <Alert variant=\"success\" appearance=\"solid\" title=\"Profile published\" description=\"Anyone with the link can view it.\" />\n <Alert variant=\"warning\" appearance=\"solid\" title=\"Trial ends in 3 days\" />\n </View>\n );\n}\n"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"name": "WithActions",
|
|
108
|
+
"title": "With Actions",
|
|
109
|
+
"code": "import { Text, View } from 'react-native';\nimport { Alert } from '@/components/ui/alert';\n\nexport default function WithActions() {\n return (\n <View style={{ gap: 10 }}>\n <Alert\n variant=\"info\"\n title=\"Update available\"\n description=\"Version 3.2 is ready. Restart to finish installing.\"\n actions={{ primary: { label: 'Restart', onPress: () => {} }, secondary: { label: 'Later', onPress: () => {} } }}\n />\n <Alert\n variant=\"danger\"\n title=\"Payment declined\"\n description=\"Your Visa ending 4242 was declined. Pro features pause on May 12.\"\n actions={{ primary: { label: 'Update card', onPress: () => {} }, secondary: { label: 'Contact bank', onPress: () => {} } }}\n dismissible\n />\n </View>\n );\n}\n"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"name": "AutoDismiss",
|
|
113
|
+
"title": "Auto Dismiss",
|
|
114
|
+
"code": "import React, { useState } from 'react';\nimport { Text, View } from 'react-native';\nimport { Alert } from '@/components/ui/alert';\nimport { Button } from '@/components/ui/button';\nimport { useKit } from '@/lib/kit';\n\nexport default function AutoDismiss() {\n const { colors } = useKit();\n const [visible, setVisible] = useState(true);\n return (\n <View style={{ gap: 12 }}>\n <Alert\n variant=\"success\"\n title=\"Changes saved\"\n description=\"Your team can see the new pricing page.\"\n duration={6000}\n dismissible\n visible={visible}\n onDismiss={() => setVisible(false)}\n />\n <Text style={{ fontSize: 14, color: colors.mutedForeground }}>Closes in 6 s. Touch and hold to pause the timer.</Text>\n <Button size=\"sm\" variant=\"outline\" style={{ alignSelf: 'flex-start' }} disabled={visible} onPress={() => setVisible(true)}>\n Show again\n </Button>\n </View>\n );\n}\n"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"name": "Dismissible",
|
|
118
|
+
"title": "Dismissible",
|
|
119
|
+
"code": "import React, { useState } from 'react';\nimport { Text, View } from 'react-native';\nimport { Alert } from '@/components/ui/alert';\nimport { Button } from '@/components/ui/button';\nimport { useKit } from '@/lib/kit';\n\nexport default function Dismissible() {\n const { colors } = useKit();\n const [visible, setVisible] = useState(true);\n return (\n <View style={{ gap: 12 }}>\n <Alert\n variant=\"success\"\n title=\"Backup complete\"\n description=\"2,184 photos were saved to iCloud.\"\n dismissible\n visible={visible}\n onDismiss={() => setVisible(false)}\n />\n <Text style={{ fontSize: 14, color: colors.mutedForeground }}>Content below glides up when the alert collapses.</Text>\n <Button size=\"sm\" variant=\"outline\" style={{ alignSelf: 'flex-start' }} disabled={visible} onPress={() => setVisible(true)}>\n Show again\n </Button>\n </View>\n );\n}\n"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"name": "Compact",
|
|
123
|
+
"title": "Compact",
|
|
124
|
+
"code": "import { Text, View } from 'react-native';\nimport { Alert } from '@/components/ui/alert';\n\nexport default function Compact() {\n return (\n <View style={{ gap: 10 }}>\n <Alert variant=\"info\" description=\"Prices include VAT where applicable.\" />\n <Alert variant=\"warning\" description=\"You're offline.\" action={{ label: 'Retry', onPress: () => {} }} />\n <Alert variant=\"success\" description=\"Link copied to clipboard.\" dismissible />\n <Alert variant=\"danger\" appearance=\"outline\" description=\"This action can't be undone.\" icon={false} />\n </View>\n );\n}\n"
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "avatar",
|
|
3
|
+
"category": "Display",
|
|
4
|
+
"aliases": [],
|
|
5
|
+
"exportName": "Avatar",
|
|
6
|
+
"files": [
|
|
7
|
+
"src/components/ui/avatar.tsx"
|
|
8
|
+
],
|
|
9
|
+
"props": [
|
|
10
|
+
[
|
|
11
|
+
"src",
|
|
12
|
+
"string",
|
|
13
|
+
"—",
|
|
14
|
+
"Image URL. Fades in over the initials; falls back to them on error."
|
|
15
|
+
],
|
|
16
|
+
[
|
|
17
|
+
"name",
|
|
18
|
+
"string",
|
|
19
|
+
"—",
|
|
20
|
+
"Initials, the deterministic fallback colour and the accessibility label."
|
|
21
|
+
],
|
|
22
|
+
[
|
|
23
|
+
"size",
|
|
24
|
+
"\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | number",
|
|
25
|
+
"\"md\"",
|
|
26
|
+
"24 / 32 / 40 / 56 / 72pt, or any number."
|
|
27
|
+
],
|
|
28
|
+
[
|
|
29
|
+
"shape",
|
|
30
|
+
"\"circle\" | \"rounded\"",
|
|
31
|
+
"\"circle\"",
|
|
32
|
+
"Circle or rounded square (follows the kit radius)."
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
"fallback",
|
|
36
|
+
"\"soft\" | \"solid\" | \"gradient\"",
|
|
37
|
+
"\"soft\"",
|
|
38
|
+
"Soft tint with deep ink, flat fill, or an opt-in two-tone gradient."
|
|
39
|
+
],
|
|
40
|
+
[
|
|
41
|
+
"status",
|
|
42
|
+
"\"online\" | \"away\" | \"busy\" | \"offline\"",
|
|
43
|
+
"—",
|
|
44
|
+
"Presence dot in a ring cut-out: filled, crescent, bar, hollow."
|
|
45
|
+
],
|
|
46
|
+
[
|
|
47
|
+
"pulse",
|
|
48
|
+
"boolean",
|
|
49
|
+
"true when online",
|
|
50
|
+
"Soft pulse behind the dot (off with reduce motion)."
|
|
51
|
+
],
|
|
52
|
+
[
|
|
53
|
+
"ring",
|
|
54
|
+
"\"none\" | \"story\" | \"accent\" | \"seen\"",
|
|
55
|
+
"\"none\"",
|
|
56
|
+
"Solid accent ring with a clear gap. \"seen\" = story + seen."
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
"seen",
|
|
60
|
+
"boolean",
|
|
61
|
+
"false",
|
|
62
|
+
"Story watched: the ring cross-fades to a quiet hairline."
|
|
63
|
+
],
|
|
64
|
+
[
|
|
65
|
+
"ringColors",
|
|
66
|
+
"string[]",
|
|
67
|
+
"sunset",
|
|
68
|
+
"Ring colour override; the first entry is used as a solid colour."
|
|
69
|
+
],
|
|
70
|
+
[
|
|
71
|
+
"ringSpin",
|
|
72
|
+
"boolean",
|
|
73
|
+
"false",
|
|
74
|
+
"Broken ring that spins — a loading story (circle only)."
|
|
75
|
+
],
|
|
76
|
+
[
|
|
77
|
+
"verified",
|
|
78
|
+
"boolean",
|
|
79
|
+
"false",
|
|
80
|
+
"Rosette seal with a check, bottom-right (bottom-left if a status dot is shown)."
|
|
81
|
+
],
|
|
82
|
+
[
|
|
83
|
+
"badge",
|
|
84
|
+
"number | boolean",
|
|
85
|
+
"—",
|
|
86
|
+
"Notification count (99+), or true for a dot, top-right."
|
|
87
|
+
],
|
|
88
|
+
[
|
|
89
|
+
"surface",
|
|
90
|
+
"string",
|
|
91
|
+
"theme background",
|
|
92
|
+
"Colour behind the avatar; cut-outs and group borders use it."
|
|
93
|
+
],
|
|
94
|
+
[
|
|
95
|
+
"accent",
|
|
96
|
+
"string",
|
|
97
|
+
"theme accent",
|
|
98
|
+
"Ring and verified seal colour."
|
|
99
|
+
],
|
|
100
|
+
[
|
|
101
|
+
"elevated",
|
|
102
|
+
"boolean",
|
|
103
|
+
"true for 72pt+",
|
|
104
|
+
"Soft drop shadow under the face."
|
|
105
|
+
],
|
|
106
|
+
[
|
|
107
|
+
"onPress",
|
|
108
|
+
"() => void",
|
|
109
|
+
"—",
|
|
110
|
+
"Makes it a button with spring press feedback."
|
|
111
|
+
],
|
|
112
|
+
[
|
|
113
|
+
"haptics",
|
|
114
|
+
"boolean",
|
|
115
|
+
"true",
|
|
116
|
+
"Light haptic tick on press."
|
|
117
|
+
],
|
|
118
|
+
[
|
|
119
|
+
"AvatarGroup.max",
|
|
120
|
+
"number",
|
|
121
|
+
"4",
|
|
122
|
+
"Avatars shown before the +N chip."
|
|
123
|
+
],
|
|
124
|
+
[
|
|
125
|
+
"AvatarGroup.total",
|
|
126
|
+
"number",
|
|
127
|
+
"children count",
|
|
128
|
+
"Real total when larger than what you pass."
|
|
129
|
+
],
|
|
130
|
+
[
|
|
131
|
+
"AvatarGroup.overlap",
|
|
132
|
+
"number",
|
|
133
|
+
"0.28",
|
|
134
|
+
"Overlap as a fraction of the size."
|
|
135
|
+
],
|
|
136
|
+
[
|
|
137
|
+
"AvatarGroup.surface",
|
|
138
|
+
"string",
|
|
139
|
+
"theme background",
|
|
140
|
+
"Colour of the separating borders — match the parent."
|
|
141
|
+
],
|
|
142
|
+
[
|
|
143
|
+
"AvatarGroup.animated",
|
|
144
|
+
"boolean",
|
|
145
|
+
"true",
|
|
146
|
+
"Staggered spring-in on mount."
|
|
147
|
+
],
|
|
148
|
+
[
|
|
149
|
+
"AvatarGroup.onPressMore",
|
|
150
|
+
"() => void",
|
|
151
|
+
"—",
|
|
152
|
+
"Makes the +N chip a button."
|
|
153
|
+
],
|
|
154
|
+
[
|
|
155
|
+
"style",
|
|
156
|
+
"StyleProp<ViewStyle>",
|
|
157
|
+
"—",
|
|
158
|
+
"Style for the avatar root; AvatarGroup applies it to its row."
|
|
159
|
+
]
|
|
160
|
+
],
|
|
161
|
+
"examples": [
|
|
162
|
+
{
|
|
163
|
+
"name": "ProfileHeader",
|
|
164
|
+
"title": "Profile Header",
|
|
165
|
+
"code": "import { Pressable, ScrollView, Text, View } from 'react-native';\nimport { Avatar, AvatarGroup } from '@/components/ui/avatar';\nimport { alpha, useKit } from '@/lib/kit';\n\nexport default function ProfileHeader() {\n const { colors, radius, dark } = useKit();\n return (\n <View\n style={{\n alignItems: 'center',\n gap: 12,\n paddingVertical: 20,\n paddingHorizontal: 16,\n borderRadius: radius.xl,\n backgroundColor: colors.card,\n borderWidth: 1,\n borderColor: alpha(colors.foreground, dark ? 0.1 : 0.06),\n }}\n >\n <Avatar\n size={88}\n src=\"https://i.pravatar.cc/240?img=47\"\n name=\"Ava Rossi\"\n ring=\"story\"\n verified\n surface={colors.card}\n elevated\n />\n <View style={{ alignItems: 'center', gap: 2 }}>\n <Text style={{ fontSize: 19, fontWeight: '400', letterSpacing: -0.3, color: colors.foreground }}>Ava Rossi</Text>\n <Text style={{ fontSize: 14, color: colors.mutedForeground }}>Product designer · Milan</Text>\n </View>\n <View style={{ flexDirection: 'row', gap: 24, marginTop: 4 }}>\n {[\n ['248', 'Posts'],\n ['12.4k', 'Followers'],\n ['311', 'Following'],\n ].map(([n, l]) => (\n <View key={l} style={{ alignItems: 'center' }}>\n <Text style={{ fontSize: 16, color: colors.foreground, fontVariant: ['tabular-nums'] }}>{n}</Text>\n <Text style={{ fontSize: 12, color: colors.mutedForeground }}>{l}</Text>\n </View>\n ))}\n </View>\n </View>\n );\n}\n"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"name": "ChatList",
|
|
169
|
+
"title": "Chat List",
|
|
170
|
+
"code": "import { Pressable, ScrollView, Text, View } from 'react-native';\nimport { Avatar, AvatarGroup } from '@/components/ui/avatar';\nimport { alpha, useKit } from '@/lib/kit';\n\nexport default function ChatList() {\n const { colors } = useKit();\n const chats = [\n { name: 'Noah Kim', src: 'https://i.pravatar.cc/150?img=59', status: 'online', msg: 'Pushed the fix — can you re-test?', time: '9:41', unread: 2 },\n { name: 'Priya Patel', status: 'away', msg: 'Sounds good, see you at 3.', time: '9:12', unread: 0 },\n { name: 'Diego Alvarez', src: 'https://i.pravatar.cc/150?img=12', status: 'busy', msg: 'In a call until noon', time: 'Mon', unread: 0 },\n { name: 'Hannah Lee', status: 'offline', msg: 'Thanks for the notes!', time: 'Sun', unread: 0 },\n ] as const;\n return (\n <View>\n {chats.map((c, i) => (\n <View\n key={c.name}\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: 12,\n paddingVertical: 10,\n borderTopWidth: i ? 1 : 0,\n borderTopColor: alpha(colors.foreground, 0.06),\n }}\n >\n <Avatar size={48} name={c.name} src={'src' in c ? c.src : undefined} status={c.status} />\n <View style={{ flex: 1, minWidth: 0 }}>\n <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>\n <Text style={{ fontSize: 15, color: colors.foreground }}>{c.name}</Text>\n <Text style={{ fontSize: 12, color: c.unread ? colors.accent : colors.mutedForeground }}>{c.time}</Text>\n </View>\n <Text numberOfLines={1} style={{ fontSize: 14, color: colors.mutedForeground, marginTop: 2 }}>\n {c.msg}\n </Text>\n </View>\n </View>\n ))}\n </View>\n );\n}\n"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"name": "Stories",
|
|
174
|
+
"title": "Stories",
|
|
175
|
+
"code": "import React, { useState } from 'react';\nimport { Pressable, ScrollView, Text, View } from 'react-native';\nimport { Avatar, AvatarGroup } from '@/components/ui/avatar';\nimport { alpha, useKit } from '@/lib/kit';\n\nexport default function Stories() {\n const { colors } = useKit();\n const [seen, setSeen] = useState<string[]>(['Theo']);\n const people = [\n { name: 'Kai Müller', short: 'Kai', img: 11 },\n { name: 'Mila Novak', short: 'Mila', img: 25 },\n { name: 'Theo Grant', short: 'Theo', img: 33 },\n { name: 'Nora Ali', short: 'Nora', img: 41 },\n { name: 'Sam Ortiz', short: 'Sam', img: 0 },\n { name: 'Lucía Romero', short: 'Lucía', img: 44 },\n ];\n return (\n <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ gap: 14, paddingRight: 8 }}>\n {people.map((p, i) => (\n <View key={p.short} style={{ alignItems: 'center', gap: 6 }}>\n <Avatar\n size=\"lg\"\n src={p.img ? `https://i.pravatar.cc/150?img=${p.img}` : undefined}\n name={p.name}\n ring=\"story\"\n seen={seen.includes(p.short)}\n ringSpin={i === 1 && !seen.includes(p.short)}\n onPress={() => setSeen((s) => (s.includes(p.short) ? s.filter((n) => n !== p.short) : [...s, p.short]))}\n />\n <Text style={{ fontSize: 12, color: seen.includes(p.short) ? colors.mutedForeground : colors.foreground }}>{p.short}</Text>\n </View>\n ))}\n </ScrollView>\n );\n}\n"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"name": "Group",
|
|
179
|
+
"title": "Group",
|
|
180
|
+
"code": "import { Pressable, ScrollView, Text, View } from 'react-native';\nimport { Avatar, AvatarGroup } from '@/components/ui/avatar';\nimport { alpha, useKit } from '@/lib/kit';\n\nexport default function Group() {\n const { colors, radius, dark } = useKit();\n return (\n <View style={{ gap: 14 }}>\n <View\n style={{\n padding: 14,\n gap: 12,\n borderRadius: radius.lg,\n backgroundColor: colors.card,\n borderWidth: 1,\n borderColor: alpha(colors.foreground, dark ? 0.1 : 0.06),\n }}\n >\n <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>\n <View>\n <Text style={{ fontSize: 15, color: colors.foreground }}>Mobile launch</Text>\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>Design · Engineering</Text>\n </View>\n <AvatarGroup max={4} total={9} surface={colors.card} size=\"sm\" onPressMore={() => {}}>\n {[8, 16, 26, 36, 48].map((n, i) => (\n <Avatar key={n} src={`https://i.pravatar.cc/150?img=${n}`} name={['Maya Chen', 'Leo Park', 'Ava Rossi', 'Noah Kim', 'Zoe Martin'][i]} />\n ))}\n </AvatarGroup>\n </View>\n </View>\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>\n <AvatarGroup size=\"sm\" max={3} total={1284}>\n <Avatar name=\"Ana Silva\" />\n <Avatar name=\"Ben Carter\" />\n <Avatar name=\"Chloe Dubois\" />\n </AvatarGroup>\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>1,284 members</Text>\n </View>\n <AvatarGroup size=\"lg\" shape=\"rounded\" max={5}>\n {['Priya Patel', 'Omar Haddad', 'Sven Larsen', 'Iris Okafor'].map((n) => (\n <Avatar key={n} name={n} />\n ))}\n </AvatarGroup>\n </View>\n );\n}\n"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"name": "Fallbacks",
|
|
184
|
+
"title": "Fallbacks",
|
|
185
|
+
"code": "import { Pressable, ScrollView, Text, View } from 'react-native';\nimport { Avatar, AvatarGroup } from '@/components/ui/avatar';\n\nexport default function Fallbacks() {\n const names = ['Priya Patel', 'Diego Alvarez', 'Hannah Lee', 'Omar Haddad', 'Sven Larsen'];\n return (\n <View style={{ gap: 14 }}>\n <View style={{ flexDirection: 'row', gap: 12 }}>\n {names.map((n) => (\n <Avatar key={n} name={n} size=\"lg\" />\n ))}\n </View>\n <View style={{ flexDirection: 'row', gap: 12 }}>\n {names.map((n) => (\n <Avatar key={n} name={n} size=\"lg\" fallback=\"solid\" />\n ))}\n </View>\n <View style={{ flexDirection: 'row', gap: 12 }}>\n {names.slice(0, 3).map((n) => (\n <Avatar key={n} name={n} size=\"lg\" shape=\"rounded\" fallback=\"gradient\" />\n ))}\n <Avatar size=\"lg\" shape=\"rounded\" src=\"https://example.invalid/broken.jpg\" name=\"Kenji Watanabe\" />\n <Avatar size=\"lg\" />\n </View>\n </View>\n );\n}\n"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"name": "Sizes",
|
|
189
|
+
"title": "Sizes",
|
|
190
|
+
"code": "import { Pressable, ScrollView, Text, View } from 'react-native';\nimport { Avatar, AvatarGroup } from '@/components/ui/avatar';\n\nexport default function Sizes() {\n return (\n <View style={{ flexDirection: 'row', alignItems: 'flex-end', gap: 12 }}>\n <Avatar size=\"xs\" src=\"https://i.pravatar.cc/150?img=32\" name=\"Maya Chen\" />\n <Avatar size=\"sm\" src=\"https://i.pravatar.cc/150?img=12\" name=\"Leo Park\" status=\"online\" />\n <Avatar size=\"md\" name=\"Ava Rossi\" status=\"away\" />\n <Avatar size=\"lg\" src=\"https://i.pravatar.cc/150?img=59\" name=\"Noah Kim\" verified />\n <Avatar size=\"xl\" src=\"https://i.pravatar.cc/150?img=5\" name=\"Zoe Martin\" status=\"online\" />\n </View>\n );\n}\n"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"name": "Status",
|
|
194
|
+
"title": "Status",
|
|
195
|
+
"code": "import { Pressable, ScrollView, Text, View } from 'react-native';\nimport { Avatar, AvatarGroup } from '@/components/ui/avatar';\nimport { alpha, useKit } from '@/lib/kit';\n\nexport default function Status() {\n const { colors } = useKit();\n const rows = [\n { name: 'Ethan Brooks', img: 15, status: 'online' },\n { name: 'Lina Novak', img: 44, status: 'away' },\n { name: 'Marcus Hill', img: 68, status: 'busy' },\n { name: 'Iris Okafor', img: 0, status: 'offline' },\n ] as const;\n return (\n <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>\n {rows.map((r) => (\n <View key={r.name} style={{ alignItems: 'center', gap: 6 }}>\n <Avatar size=\"lg\" src={r.img ? `https://i.pravatar.cc/150?img=${r.img}` : undefined} name={r.name} status={r.status} />\n <Text style={{ fontSize: 12, color: colors.mutedForeground }}>{r.status[0].toUpperCase() + r.status.slice(1)}</Text>\n </View>\n ))}\n </View>\n );\n}\n"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"name": "Badges",
|
|
199
|
+
"title": "Badges",
|
|
200
|
+
"code": "import React, { useState } from 'react';\nimport { Pressable, ScrollView, Text, View } from 'react-native';\nimport { Avatar, AvatarGroup } from '@/components/ui/avatar';\nimport { alpha, useKit } from '@/lib/kit';\n\nexport default function Badges() {\n const { colors } = useKit();\n const [count, setCount] = useState(3);\n return (\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 22 }}>\n <Pressable accessibilityRole=\"button\" accessibilityLabel=\"Add a notification\" onPress={() => setCount((c) => c + 1)} style={{ alignItems: 'center', gap: 6 }}>\n <Avatar size=\"lg\" src=\"https://i.pravatar.cc/150?img=22\" name=\"Maya Chen\" badge={count} />\n <Text style={{ fontSize: 12, color: colors.mutedForeground }}>Tap +1</Text>\n </Pressable>\n <View style={{ alignItems: 'center', gap: 6 }}>\n <Avatar size=\"lg\" src=\"https://i.pravatar.cc/150?img=9\" name=\"Leo Park\" badge={128} status=\"online\" />\n <Text style={{ fontSize: 12, color: colors.mutedForeground }}>Mentions</Text>\n </View>\n <View style={{ alignItems: 'center', gap: 6 }}>\n <Avatar size=\"lg\" name=\"Design Team\" shape=\"rounded\" badge verified />\n <Text style={{ fontSize: 12, color: colors.mutedForeground }}>Workspace</Text>\n </View>\n </View>\n );\n}\n"
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
}
|