create-vite-taro 0.5.13 → 0.5.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-vite-taro",
3
- "version": "0.5.13",
3
+ "version": "0.5.16",
4
4
  "description": "Create Vite 8 + React 19 + Taro apps for H5 and WeChat Mini Program targets.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -23,6 +23,6 @@
23
23
  "cross-env": "^10.1.0",
24
24
  "rolldown": "1.2.3",
25
25
  "vite": "8.2.1",
26
- "vite-plugin-taro": "^0.5.13"
26
+ "vite-plugin-taro": "^0.5.16"
27
27
  }
28
28
  }
@@ -4,6 +4,34 @@
4
4
 
5
5
  @source "./";
6
6
 
7
+ @theme static {
8
+ --color-canvas: #fbfaf1;
9
+ --color-foreground: #315f44;
10
+ --color-heading: #174f32;
11
+ --color-primary: #17673d;
12
+ --color-primary-control: #197342;
13
+ --color-primary-label: #207344;
14
+ --color-primary-stem: #237648;
15
+ --color-action: #78dc91;
16
+ --color-action-foreground: #0d2b18;
17
+ --color-on-primary-accent: #a9e2b4;
18
+ --color-on-primary-muted: #d5ead9;
19
+ --color-primary-surface: #e3f4df;
20
+ --color-surface-muted: #edf5e8;
21
+ --color-surface-subtle: #f8fbf4;
22
+ --color-muted: #64786a;
23
+ --color-quiet: #819185;
24
+ --color-outline: rgba(30, 102, 61, 0.15);
25
+ --color-divider: rgba(30, 102, 61, 0.1);
26
+ --color-coral: #e98a72;
27
+ --color-petal: #ef977f;
28
+ --color-sun: #fff1bd;
29
+ --background-image-canvas-botanical:
30
+ radial-gradient(ellipse at 12% 5%, rgba(101, 190, 119, 0.11), rgba(101, 190, 119, 0.04) 28%, transparent 62%),
31
+ radial-gradient(ellipse at 90% 18%, rgba(234, 139, 115, 0.08), rgba(234, 139, 115, 0.03) 32%, transparent 68%);
32
+ --background-image-botanical-leaf: linear-gradient(145deg, #9cd88b, #43a760);
33
+ }
34
+
7
35
  *,
8
36
  *::before,
9
37
  *::after {
@@ -15,12 +43,11 @@ button::after {
15
43
  border: none;
16
44
  }
17
45
 
18
- /* biome-ignore lint/correctness/noUnknownTypeSelector: WeChat Mini Program uses page as its document root. */
19
46
  page,
20
47
  body {
21
48
  margin: 0;
22
- background: #fbfaf1;
23
- color: #315f44;
49
+ background: var(--color-canvas);
50
+ color: var(--color-foreground);
24
51
  }
25
52
 
26
53
  button {
@@ -30,130 +57,3 @@ button {
30
57
  .brand-serif {
31
58
  font-family: Georgia, "Times New Roman", serif;
32
59
  }
33
-
34
- .starter-canvas {
35
- background:
36
- radial-gradient(ellipse at 12% 5%, rgba(101, 190, 119, 0.11), rgba(101, 190, 119, 0.04) 28%, transparent 62%),
37
- radial-gradient(ellipse at 90% 18%, rgba(234, 139, 115, 0.08), rgba(234, 139, 115, 0.03) 32%, transparent 68%),
38
- #fbfaf1;
39
- }
40
-
41
- .botanical-sprig {
42
- position: absolute;
43
- z-index: 0;
44
- width: 15rem;
45
- height: 10rem;
46
- opacity: 0.68;
47
- pointer-events: none;
48
- }
49
-
50
- .botanical-sprig-top {
51
- top: -2.25rem;
52
- left: -4.25rem;
53
- transform: rotate(-7deg);
54
- }
55
-
56
- .botanical-sprig-side {
57
- right: -5rem;
58
- bottom: -1.75rem;
59
- opacity: 0.42;
60
- transform: scaleX(-1) rotate(-11deg);
61
- }
62
-
63
- .botanical-sprig-cta {
64
- z-index: 0;
65
- right: -3rem;
66
- bottom: -2.5rem;
67
- opacity: 0.18;
68
- transform: scale(1.15) rotate(-8deg);
69
- }
70
-
71
- .botanical-stem {
72
- position: absolute;
73
- top: 7rem;
74
- left: 0.5rem;
75
- width: 14rem;
76
- height: 0.3rem;
77
- border-radius: 999px;
78
- background: #237648;
79
- transform: rotate(-24deg);
80
- transform-origin: left center;
81
- }
82
-
83
- .botanical-leaf {
84
- position: absolute;
85
- width: 3.2rem;
86
- height: 1.55rem;
87
- border-radius: 72% 28% 70% 30%;
88
- background: linear-gradient(145deg, #9cd88b, #43a760);
89
- }
90
-
91
- .botanical-leaf-one {
92
- top: 5.65rem;
93
- left: 3rem;
94
- transform: rotate(28deg);
95
- }
96
-
97
- .botanical-leaf-two {
98
- top: 3.95rem;
99
- left: 6.1rem;
100
- transform: rotate(-20deg);
101
- }
102
-
103
- .botanical-leaf-three {
104
- top: 2.55rem;
105
- left: 9.1rem;
106
- transform: rotate(25deg);
107
- }
108
-
109
- .botanical-leaf-four {
110
- top: 0.85rem;
111
- left: 11.8rem;
112
- transform: rotate(-17deg);
113
- }
114
-
115
- .botanical-flower {
116
- position: absolute;
117
- top: 4.9rem;
118
- left: 4.35rem;
119
- width: 2.8rem;
120
- height: 2.8rem;
121
- }
122
-
123
- .botanical-petal,
124
- .botanical-flower-center {
125
- position: absolute;
126
- top: 50%;
127
- left: 50%;
128
- border-radius: 999px;
129
- transform: translate(-50%, -50%);
130
- }
131
-
132
- .botanical-petal {
133
- width: 1.05rem;
134
- height: 1.55rem;
135
- background: #ef977f;
136
- }
137
-
138
- .botanical-petal-one {
139
- transform: translate(-50%, -100%);
140
- }
141
-
142
- .botanical-petal-two {
143
- transform: translate(0, -50%) rotate(90deg);
144
- }
145
-
146
- .botanical-petal-three {
147
- transform: translate(-50%, 0);
148
- }
149
-
150
- .botanical-petal-four {
151
- transform: translate(-100%, -50%) rotate(90deg);
152
- }
153
-
154
- .botanical-flower-center {
155
- z-index: 1;
156
- width: 0.7rem;
157
- height: 0.7rem;
158
- background: #fff1bd;
159
- }
@@ -0,0 +1,115 @@
1
+ .botanicalSprig {
2
+ position: absolute;
3
+ z-index: 0;
4
+ width: 15rem;
5
+ height: 10rem;
6
+ opacity: 0.68;
7
+ pointer-events: none;
8
+ }
9
+
10
+ .botanicalSprigTop {
11
+ top: -2.25rem;
12
+ left: -4.25rem;
13
+ transform: rotate(-7deg);
14
+ }
15
+
16
+ .botanicalSprigSide {
17
+ right: -5rem;
18
+ bottom: -1.75rem;
19
+ opacity: 0.42;
20
+ transform: scaleX(-1) rotate(-11deg);
21
+ }
22
+
23
+ .botanicalSprigCta {
24
+ z-index: 0;
25
+ right: -3rem;
26
+ bottom: -2.5rem;
27
+ opacity: 0.18;
28
+ transform: scale(1.15) rotate(-8deg);
29
+ }
30
+
31
+ .botanicalStem {
32
+ position: absolute;
33
+ top: 7rem;
34
+ left: 0.5rem;
35
+ width: 14rem;
36
+ height: 0.3rem;
37
+ border-radius: 999px;
38
+ transform: rotate(-24deg);
39
+ transform-origin: left center;
40
+ }
41
+
42
+ .botanicalLeaf {
43
+ position: absolute;
44
+ width: 3.2rem;
45
+ height: 1.55rem;
46
+ border-radius: 72% 28% 70% 30%;
47
+ }
48
+
49
+ .botanicalLeafOne {
50
+ top: 5.65rem;
51
+ left: 3rem;
52
+ transform: rotate(28deg);
53
+ }
54
+
55
+ .botanicalLeafTwo {
56
+ top: 3.95rem;
57
+ left: 6.1rem;
58
+ transform: rotate(-20deg);
59
+ }
60
+
61
+ .botanicalLeafThree {
62
+ top: 2.55rem;
63
+ left: 9.1rem;
64
+ transform: rotate(25deg);
65
+ }
66
+
67
+ .botanicalLeafFour {
68
+ top: 0.85rem;
69
+ left: 11.8rem;
70
+ transform: rotate(-17deg);
71
+ }
72
+
73
+ .botanicalFlower {
74
+ position: absolute;
75
+ top: 4.9rem;
76
+ left: 4.35rem;
77
+ width: 2.8rem;
78
+ height: 2.8rem;
79
+ }
80
+
81
+ .botanicalPetal,
82
+ .botanicalFlowerCenter {
83
+ position: absolute;
84
+ top: 50%;
85
+ left: 50%;
86
+ border-radius: 999px;
87
+ transform: translate(-50%, -50%);
88
+ }
89
+
90
+ .botanicalPetal {
91
+ width: 1.05rem;
92
+ height: 1.55rem;
93
+ }
94
+
95
+ .botanicalPetalOne {
96
+ transform: translate(-50%, -100%);
97
+ }
98
+
99
+ .botanicalPetalTwo {
100
+ transform: translate(0, -50%) rotate(90deg);
101
+ }
102
+
103
+ .botanicalPetalThree {
104
+ transform: translate(-50%, 0);
105
+ }
106
+
107
+ .botanicalPetalFour {
108
+ transform: translate(-100%, -50%) rotate(90deg);
109
+ }
110
+
111
+ .botanicalFlowerCenter {
112
+ z-index: 1;
113
+ width: 0.7rem;
114
+ height: 0.7rem;
115
+ }
@@ -0,0 +1,31 @@
1
+ import { View } from 'virtual:taro/components'
2
+ import styles from './botanical-sprig.module.css'
3
+
4
+ const placementClasses = {
5
+ top: styles.botanicalSprigTop,
6
+ side: styles.botanicalSprigSide,
7
+ cta: styles.botanicalSprigCta
8
+ } as const
9
+
10
+ interface BotanicalSprigProps {
11
+ placement: keyof typeof placementClasses
12
+ }
13
+
14
+ export function BotanicalSprig({ placement }: BotanicalSprigProps) {
15
+ return (
16
+ <View className={`${styles.botanicalSprig} ${placementClasses[placement]}`} aria-hidden="true">
17
+ <View className={`${styles.botanicalStem} bg-primary-stem`} />
18
+ <View className={`${styles.botanicalLeaf} ${styles.botanicalLeafOne} bg-botanical-leaf`} />
19
+ <View className={`${styles.botanicalLeaf} ${styles.botanicalLeafTwo} bg-botanical-leaf`} />
20
+ <View className={`${styles.botanicalLeaf} ${styles.botanicalLeafThree} bg-botanical-leaf`} />
21
+ <View className={`${styles.botanicalLeaf} ${styles.botanicalLeafFour} bg-botanical-leaf`} />
22
+ <View className={styles.botanicalFlower}>
23
+ <View className={`${styles.botanicalPetal} ${styles.botanicalPetalOne} bg-petal`} />
24
+ <View className={`${styles.botanicalPetal} ${styles.botanicalPetalTwo} bg-petal`} />
25
+ <View className={`${styles.botanicalPetal} ${styles.botanicalPetalThree} bg-petal`} />
26
+ <View className={`${styles.botanicalPetal} ${styles.botanicalPetalFour} bg-petal`} />
27
+ <View className={`${styles.botanicalFlowerCenter} bg-sun`} />
28
+ </View>
29
+ </View>
30
+ )
31
+ }
@@ -0,0 +1,23 @@
1
+ // #ifdef wx
2
+ import { NativeCounter } from './native-counter.tsx'
3
+ // #endif
4
+
5
+ // #ifdef h5
6
+ import { WebCounter } from './web-counter.tsx'
7
+ // #endif
8
+
9
+ export interface CounterProps {
10
+ count: number
11
+ onDecrement: () => void
12
+ onIncrement: () => void
13
+ }
14
+
15
+ export function Counter(props: CounterProps) {
16
+ // #ifdef wx
17
+ return <NativeCounter {...props} />
18
+ // #endif
19
+
20
+ // #ifdef h5
21
+ return <WebCounter {...props} />
22
+ // #endif
23
+ }
@@ -0,0 +1,18 @@
1
+ Component({
2
+ properties: {
3
+ count: {
4
+ type: Number,
5
+ value: 0
6
+ }
7
+ },
8
+
9
+ methods: {
10
+ decrement() {
11
+ this.triggerEvent('decrement')
12
+ },
13
+
14
+ increment() {
15
+ this.triggerEvent('increment')
16
+ }
17
+ }
18
+ })
@@ -0,0 +1,4 @@
1
+ {
2
+ "component": true,
3
+ "styleIsolation": "isolated"
4
+ }
@@ -0,0 +1,24 @@
1
+ <view class="native-counter">
2
+ <text class="native-counter__title">SHARED COUNTER</text>
3
+ <view class="native-counter__control">
4
+ <button
5
+ aria-label="Decrease counter"
6
+ class="native-counter__button native-counter__button--decrement"
7
+ hover-class="native-counter__button--pressed"
8
+ bindtap="decrement"
9
+ >
10
+ <text>−</text>
11
+ </button>
12
+ <view class="native-counter__value">
13
+ <text>{{ count }}</text>
14
+ </view>
15
+ <button
16
+ aria-label="Increase counter"
17
+ class="native-counter__button native-counter__button--increment"
18
+ hover-class="native-counter__button--pressed"
19
+ bindtap="increment"
20
+ >
21
+ <text>+</text>
22
+ </button>
23
+ </view>
24
+ </view>
@@ -0,0 +1,82 @@
1
+ :host {
2
+ display: block;
3
+ }
4
+
5
+ .native-counter {
6
+ display: flex;
7
+ flex-direction: column;
8
+ padding: 32rpx;
9
+ border-radius: 32rpx;
10
+ background: var(--color-surface-muted);
11
+ }
12
+
13
+ .native-counter__title {
14
+ color: var(--color-foreground);
15
+ font-size: 24rpx;
16
+ font-weight: 700;
17
+ letter-spacing: 2.4rpx;
18
+ line-height: 1;
19
+ text-align: center;
20
+ }
21
+
22
+ .native-counter__control {
23
+ display: flex;
24
+ height: 112rpx;
25
+ margin-top: 24rpx;
26
+ overflow: hidden;
27
+ border: 2rpx solid var(--color-outline);
28
+ border-radius: 9999rpx;
29
+ background: var(--color-white);
30
+ box-sizing: border-box;
31
+ }
32
+
33
+ .native-counter__button {
34
+ display: flex;
35
+ width: 112rpx;
36
+ height: 100%;
37
+ flex-shrink: 0;
38
+ align-items: center;
39
+ justify-content: center;
40
+ margin: 0;
41
+ padding: 0;
42
+ border-radius: 0;
43
+ background: var(--color-white);
44
+ color: var(--color-foreground);
45
+ font-size: 36rpx;
46
+ font-weight: 700;
47
+ line-height: 1;
48
+ }
49
+
50
+ .native-counter__button::after {
51
+ border: 0;
52
+ }
53
+
54
+ .native-counter__button--decrement {
55
+ border-radius: 9999rpx 0 0 9999rpx;
56
+ }
57
+
58
+ .native-counter__button--increment {
59
+ border-radius: 0 9999rpx 9999rpx 0;
60
+ background: var(--color-primary-control);
61
+ color: var(--color-white);
62
+ }
63
+
64
+ .native-counter__button--pressed {
65
+ opacity: 0.82;
66
+ }
67
+
68
+ .native-counter__value {
69
+ display: flex;
70
+ min-width: 0;
71
+ flex: 1;
72
+ align-items: center;
73
+ justify-content: center;
74
+ border-right: 2rpx solid var(--color-divider);
75
+ border-left: 2rpx solid var(--color-divider);
76
+ background: var(--color-surface-subtle);
77
+ box-sizing: border-box;
78
+ color: var(--color-primary-control);
79
+ font-family: Georgia, "Times New Roman", serif;
80
+ font-size: 60rpx;
81
+ font-weight: 600;
82
+ }
@@ -0,0 +1,9 @@
1
+ import { defineNativeComponent } from 'virtual:taro/native'
2
+
3
+ type NativeCounterProps = {
4
+ count: number
5
+ onDecrement: () => void
6
+ onIncrement: () => void
7
+ }
8
+
9
+ export const NativeCounter = defineNativeComponent<NativeCounterProps>(() => import('./native-counter/counter.js'))
@@ -0,0 +1,33 @@
1
+ import { Button, Text, View } from 'virtual:taro/components'
2
+ import type { CounterProps } from './counter.tsx'
3
+
4
+ export function WebCounter({ count, onDecrement, onIncrement }: CounterProps) {
5
+ return (
6
+ <View className="flex flex-col rounded-2xl bg-surface-muted p-4">
7
+ <Text className="text-center text-xs font-bold tracking-widest text-foreground">SHARED COUNTER</Text>
8
+ <View className="mt-3 flex h-14 w-full flex-row overflow-hidden rounded-full border border-outline bg-white">
9
+ <View className="flex h-full w-14 shrink-0">
10
+ <Button
11
+ aria-label="Decrease counter"
12
+ className="m-0 flex h-full w-full items-center justify-center rounded-l-full rounded-r-none bg-white p-0 text-lg font-bold leading-none text-foreground after:border-0"
13
+ onClick={onDecrement}
14
+ >
15
+ <Text>−</Text>
16
+ </Button>
17
+ </View>
18
+ <View className="flex min-w-0 flex-1 items-center justify-center border-x border-divider bg-surface-subtle">
19
+ <Text className="brand-serif text-3xl font-semibold text-primary-control">{count}</Text>
20
+ </View>
21
+ <View className="flex h-full w-14 shrink-0">
22
+ <Button
23
+ aria-label="Increase counter"
24
+ className="m-0 flex h-full w-full items-center justify-center rounded-l-none rounded-r-full bg-primary-control p-0 text-lg font-bold leading-none text-white after:border-0"
25
+ onClick={onIncrement}
26
+ >
27
+ <Text>+</Text>
28
+ </Button>
29
+ </View>
30
+ </View>
31
+ </View>
32
+ )
33
+ }
@@ -18,13 +18,13 @@ export function NavigationBar({ title }: NavigationBarProps) {
18
18
  const sideStyle: CSSProperties = { flexBasis: px(menuInfo.width), width: px(menuInfo.width) }
19
19
 
20
20
  return (
21
- <View className="flex w-full flex-col text-[#17673d]" style={containerStyle}>
21
+ <View className="flex w-full flex-col text-primary" style={containerStyle}>
22
22
  <View className="shrink-0" style={statusBarStyle} />
23
23
  <View className="flex w-full flex-1 flex-row items-center" style={contentStyle}>
24
24
  <View className="flex h-full shrink-0" style={sideStyle} />
25
25
  <View className="flex h-full min-w-0 flex-1 flex-row items-center justify-center gap-2 text-center">
26
26
  <Text className="brand-serif text-xl font-semibold tracking-[0.12em]">{title}</Text>
27
- <View className="h-1.5 w-1.5 rounded-full bg-[#e98a72]" />
27
+ <View className="h-1.5 w-1.5 rounded-full bg-coral" />
28
28
  </View>
29
29
  <View className="flex h-full shrink-0" style={sideStyle} />
30
30
  </View>
@@ -0,0 +1,149 @@
1
+ import { ScrollView, Text, View } from 'virtual:taro/components'
2
+ import { lazy, Suspense, useState } from 'react'
3
+ import { Counter } from '../../components/counter/counter.tsx'
4
+ import { BotanicalSprig } from '../../components/botanical-sprig/botanical-sprig.tsx'
5
+ import { NavigationBar } from '../../components/navigation-bar/navigation-bar.tsx'
6
+
7
+ const featureCards = [
8
+ {
9
+ number: '01',
10
+ title: 'Vite-speed feedback',
11
+ description: 'Save a React component and see the smallest possible update in WeChat DevTools or the browser.',
12
+ tiltClass: 'rotate-[-0.35deg]'
13
+ },
14
+ {
15
+ number: '02',
16
+ title: 'One React tree',
17
+ description: 'Share components, hooks and application state between WeChat Mini Program and H5.',
18
+ tiltClass: 'translate-y-1 rotate-[0.25deg]'
19
+ },
20
+ {
21
+ number: '03',
22
+ title: 'Native when needed',
23
+ description: 'Use familiar Taro components and APIs without stepping away from a modern frontend workflow.',
24
+ tiltClass: 'rotate-[0.4deg]'
25
+ }
26
+ ] as const
27
+
28
+ const ApiCard = lazy(() => import('./lazy/api-card.tsx'))
29
+
30
+ function HomePage() {
31
+ // This local state intentionally demonstrates that VPT preserves React state during hot updates.
32
+ const [count, setCount] = useState(0)
33
+
34
+ return (
35
+ <View className="flex h-screen flex-col overflow-hidden bg-canvas bg-canvas-botanical text-foreground">
36
+ <NavigationBar title="VPT" />
37
+ <ScrollView scrollY className="flex min-h-0 flex-1 flex-col">
38
+ <View className="relative flex shrink-0 flex-col items-center overflow-hidden px-5 pb-8 pt-6">
39
+ <BotanicalSprig placement="top" />
40
+ <BotanicalSprig placement="side" />
41
+
42
+ <View className="relative z-10 flex w-full max-w-4xl flex-col items-center text-center">
43
+ <Text className="brand-serif mt-7 block text-[7rem] font-semibold leading-none tracking-[-0.08em] text-primary sm:text-[9rem]">
44
+ VPT
45
+ </Text>
46
+ <Text className="mt-5 block max-w-2xl text-2xl font-bold leading-tight text-heading sm:text-3xl">
47
+ Build naturally. Ship everywhere.
48
+ </Text>
49
+ <Text className="mt-4 block max-w-xl text-sm leading-7 text-muted sm:text-base">
50
+ A botanical little starter for building polished WeChat Mini Programs and Web apps with one
51
+ modern React codebase.
52
+ </Text>
53
+
54
+ <View className="mt-7 flex flex-row flex-wrap items-center justify-center gap-3">
55
+ <View className="rounded-full border border-outline bg-white/75 px-4 py-2">
56
+ <Text className="text-sm font-bold text-primary">Vite 8</Text>
57
+ </View>
58
+ <Text className="text-coral">✿</Text>
59
+ <View className="rounded-full border border-outline bg-white/75 px-4 py-2">
60
+ <Text className="text-sm font-bold text-primary">React 19</Text>
61
+ </View>
62
+ <Text className="text-coral">✿</Text>
63
+ <View className="rounded-full border border-outline bg-white/75 px-4 py-2">
64
+ <Text className="text-sm font-bold text-primary">Tailwind 4</Text>
65
+ </View>
66
+ </View>
67
+ </View>
68
+ </View>
69
+
70
+ <View className="mx-6 mb-8 shrink-0 sm:mx-auto sm:w-64">
71
+ <Counter
72
+ count={count}
73
+ onDecrement={() => {
74
+ setCount((currentCount) => currentCount - 1)
75
+ }}
76
+ onIncrement={() => {
77
+ setCount((currentCount) => currentCount + 1)
78
+ }}
79
+ />
80
+ </View>
81
+
82
+ <View className="relative z-10 flex shrink-0 flex-col items-center px-5">
83
+ <View className="flex w-full max-w-4xl flex-col gap-5 overflow-hidden rounded-3xl border border-outline bg-white/85 p-6 shadow-xl sm:flex-row sm:items-center sm:p-8">
84
+ <View className="flex min-w-0 flex-1 flex-col">
85
+ <Text className="brand-serif mt-2 block text-3xl font-semibold text-heading">
86
+ Edit. Save. Stay in flow.
87
+ </Text>
88
+ <Text className="mt-3 block text-sm leading-6 text-muted">
89
+ Change this counter, then edit src/pages/home/index.tsx. Your state stays exactly where
90
+ you left it.
91
+ </Text>
92
+ </View>
93
+ </View>
94
+ </View>
95
+
96
+ <View className="flex shrink-0 flex-col items-center px-5 pb-12 pt-14">
97
+ <View className="flex w-full max-w-4xl flex-col">
98
+ <View className="flex flex-col items-center text-center">
99
+ <Text className="text-xs font-bold tracking-widest text-primary-label">
100
+ A SMALL START, A MODERN FOUNDATION
101
+ </Text>
102
+ <Text className="brand-serif mt-3 block text-4xl font-semibold text-heading">
103
+ Everything is ready to grow.
104
+ </Text>
105
+ <Text className="mt-3 block max-w-xl text-sm leading-7 text-muted">
106
+ Keep the pieces you need, replace the rest, and let VPT handle the cross-platform build.
107
+ </Text>
108
+ </View>
109
+
110
+ <View className="mt-8 flex flex-row flex-wrap items-start gap-4">
111
+ {featureCards.map((feature) => (
112
+ <View
113
+ key={feature.number}
114
+ className={`flex min-w-64 flex-1 flex-col rounded-3xl border border-outline bg-white/80 p-6 shadow-lg ${feature.tiltClass}`}
115
+ >
116
+ <View className="flex flex-row items-center gap-4">
117
+ <View className="flex h-11 w-11 shrink-0 items-center justify-center rounded-2xl bg-primary-surface">
118
+ <Text className="brand-serif block text-base font-bold leading-none text-primary-control">
119
+ {feature.number}
120
+ </Text>
121
+ </View>
122
+ <Text className="block min-w-0 flex-1 text-lg font-bold text-heading">
123
+ {feature.title}
124
+ </Text>
125
+ </View>
126
+ <Text className="mt-4 block text-sm leading-6 text-muted">
127
+ {feature.description}
128
+ </Text>
129
+ </View>
130
+ ))}
131
+ </View>
132
+
133
+ <Suspense fallback={<View className="mt-8 min-h-48 rounded-3xl bg-primary" />}>
134
+ <ApiCard />
135
+ </Suspense>
136
+
137
+ <View className="flex flex-col items-center px-2 pb-2 pt-9">
138
+ <Text className="text-center text-xs font-bold tracking-widest text-quiet">
139
+ VPT · OPEN SOURCE · MIT
140
+ </Text>
141
+ </View>
142
+ </View>
143
+ </View>
144
+ </ScrollView>
145
+ </View>
146
+ )
147
+ }
148
+
149
+ export default HomePage
@@ -0,0 +1,26 @@
1
+ import Taro from 'virtual:taro/api'
2
+ import { Button, Text, View } from 'virtual:taro/components'
3
+ import { BotanicalSprig } from '../../../components/botanical-sprig/botanical-sprig.tsx'
4
+
5
+ export default function ApiCard() {
6
+ return (
7
+ <View className="relative mt-8 flex flex-col overflow-hidden rounded-3xl bg-primary p-7 text-white sm:flex-row sm:items-center sm:justify-between sm:p-9">
8
+ <BotanicalSprig placement="cta" />
9
+ <View className="relative z-10 flex max-w-lg flex-col">
10
+ <Text className="text-xs font-bold tracking-widest text-on-primary-accent">TARO API READY</Text>
11
+ <Text className="brand-serif mt-2 block text-3xl font-semibold text-white">
12
+ Make this starter yours.
13
+ </Text>
14
+ <Text className="mt-3 block text-sm leading-6 text-on-primary-muted">
15
+ Add pages, connect your data and ship the same experience to WeChat and H5.
16
+ </Text>
17
+ </View>
18
+ <Button
19
+ className="relative z-10 mt-6 flex items-center justify-center self-start rounded-full bg-action px-6 py-3 text-sm font-bold text-action-foreground after:border-0 sm:mt-0"
20
+ onClick={() => Taro.showToast({ title: 'Hello from VPT!' })}
21
+ >
22
+ Try a Taro toast →
23
+ </Button>
24
+ </View>
25
+ )
26
+ }
@@ -31,7 +31,7 @@ export default defineConfig(({ mode }) => {
31
31
  app: 'src/app.tsx',
32
32
  pages: [
33
33
  {
34
- path: 'pages/index/index',
34
+ path: 'pages/home/index',
35
35
  config: {
36
36
  navigationStyle: 'custom',
37
37
  navigationBarTextStyle: 'black'
@@ -1,203 +0,0 @@
1
- import Taro from 'virtual:taro/api'
2
- import { Button, ScrollView, Text, View } from 'virtual:taro/components'
3
- import { useState } from 'react'
4
- import { NavigationBar } from '../../components/navigation-bar/navigation-bar.tsx'
5
-
6
- const featureCards = [
7
- {
8
- number: '01',
9
- title: 'Vite-speed feedback',
10
- description: 'Save a React component and see the smallest possible update in WeChat DevTools or the browser.',
11
- tiltClass: 'rotate-[-0.35deg]'
12
- },
13
- {
14
- number: '02',
15
- title: 'One React tree',
16
- description: 'Share components, hooks and application state between WeChat Mini Program and H5.',
17
- tiltClass: 'translate-y-1 rotate-[0.25deg]'
18
- },
19
- {
20
- number: '03',
21
- title: 'Native when needed',
22
- description: 'Use familiar Taro components and APIs without stepping away from a modern frontend workflow.',
23
- tiltClass: 'rotate-[0.4deg]'
24
- }
25
- ] as const
26
-
27
- interface BotanicalSprigProps {
28
- className: string
29
- }
30
-
31
- function BotanicalSprig({ className }: BotanicalSprigProps) {
32
- return (
33
- <View className={`botanical-sprig ${className}`} aria-hidden="true">
34
- <View className="botanical-stem" />
35
- <View className="botanical-leaf botanical-leaf-one" />
36
- <View className="botanical-leaf botanical-leaf-two" />
37
- <View className="botanical-leaf botanical-leaf-three" />
38
- <View className="botanical-leaf botanical-leaf-four" />
39
- <View className="botanical-flower">
40
- <View className="botanical-petal botanical-petal-one" />
41
- <View className="botanical-petal botanical-petal-two" />
42
- <View className="botanical-petal botanical-petal-three" />
43
- <View className="botanical-petal botanical-petal-four" />
44
- <View className="botanical-flower-center" />
45
- </View>
46
- </View>
47
- )
48
- }
49
-
50
- function IndexPage() {
51
- // This local state intentionally demonstrates that VPT preserves React state during hot updates.
52
- const [count, setCount] = useState(0)
53
-
54
- return (
55
- <View className="starter-canvas flex h-screen flex-col overflow-hidden text-[#315f44]">
56
- <NavigationBar title="VPT" />
57
- <ScrollView scrollY className="flex min-h-0 flex-1 flex-col">
58
- <View className="relative flex shrink-0 flex-col items-center overflow-hidden px-5 pb-12 pt-10">
59
- <BotanicalSprig className="botanical-sprig-top" />
60
- <BotanicalSprig className="botanical-sprig-side" />
61
-
62
- <View className="relative z-10 flex w-full max-w-4xl flex-col items-center text-center">
63
- <View className="flex flex-row items-center gap-2 rounded-full border border-[#1e663d]/15 bg-white/70 px-4 py-2">
64
- <View className="h-2 w-2 rounded-full bg-[#63bd74]" />
65
- <Text className="text-xs font-bold tracking-widest text-[#207344]">
66
- VITE × REACT × TARO
67
- </Text>
68
- </View>
69
-
70
- <Text className="brand-serif mt-7 block text-[7rem] font-semibold leading-none tracking-[-0.08em] text-[#17673d] sm:text-[9rem]">
71
- VPT
72
- </Text>
73
- <Text className="mt-5 block max-w-2xl text-2xl font-bold leading-tight text-[#174f32] sm:text-3xl">
74
- Build naturally. Ship everywhere.
75
- </Text>
76
- <Text className="mt-4 block max-w-xl text-sm leading-7 text-[#64786a] sm:text-base">
77
- A botanical little starter for building polished WeChat Mini Programs and Web apps with one
78
- modern React codebase.
79
- </Text>
80
-
81
- <View className="mt-7 flex flex-row flex-wrap items-center justify-center gap-3">
82
- <View className="rounded-full border border-[#1e663d]/15 bg-white/75 px-4 py-2">
83
- <Text className="text-sm font-bold text-[#17673d]">Vite 8</Text>
84
- </View>
85
- <Text className="text-[#e98a72]">✿</Text>
86
- <View className="rounded-full border border-[#1e663d]/15 bg-white/75 px-4 py-2">
87
- <Text className="text-sm font-bold text-[#17673d]">React 19</Text>
88
- </View>
89
- <Text className="text-[#e98a72]">✿</Text>
90
- <View className="rounded-full border border-[#1e663d]/15 bg-white/75 px-4 py-2">
91
- <Text className="text-sm font-bold text-[#17673d]">Tailwind 4</Text>
92
- </View>
93
- </View>
94
- </View>
95
- </View>
96
-
97
- <View className="relative z-10 flex shrink-0 flex-col items-center px-5">
98
- <View className="flex w-full max-w-4xl flex-col gap-5 overflow-hidden rounded-3xl border border-[#1e663d]/15 bg-white/85 p-6 shadow-xl sm:flex-row sm:items-center sm:p-8">
99
- <View className="flex min-w-0 flex-1 flex-col">
100
- <Text className="text-xs font-bold tracking-widest text-[#e17f68]">
101
- STATE-PRESERVING HMR
102
- </Text>
103
- <Text className="brand-serif mt-2 block text-3xl font-semibold text-[#174f32]">
104
- Edit. Save. Stay in flow.
105
- </Text>
106
- <Text className="mt-3 block text-sm leading-6 text-[#64786a]">
107
- Change this counter, then edit src/pages/index/index.tsx. Your state stays exactly where
108
- you left it.
109
- </Text>
110
- </View>
111
-
112
- <View className="flex shrink-0 flex-col rounded-2xl bg-[#edf5e8] p-4 sm:w-64">
113
- <Text className="text-center text-xs font-bold tracking-widest text-[#315f44]">
114
- SHARED COUNTER
115
- </Text>
116
- <View className="mt-3 flex h-14 w-full flex-row overflow-hidden rounded-xl border border-[#1e663d]/15 bg-white">
117
- <View className="flex h-full w-14 shrink-0">
118
- <Button
119
- className="m-0 flex h-full w-full items-center justify-center rounded-none bg-white p-0 text-lg font-bold leading-none text-[#315f44] after:border-0"
120
- onClick={() => setCount((currentCount) => currentCount - 1)}
121
- >
122
- <Text>−</Text>
123
- </Button>
124
- </View>
125
- <View className="flex min-w-0 flex-1 items-center justify-center border-x border-[#1e663d]/10 bg-[#f8fbf4]">
126
- <Text className="brand-serif text-3xl font-semibold text-[#197342]">{count}</Text>
127
- </View>
128
- <View className="flex h-full w-14 shrink-0">
129
- <Button
130
- className="m-0 flex h-full w-full items-center justify-center rounded-none bg-[#197342] p-0 text-lg font-bold leading-none text-white after:border-0"
131
- onClick={() => setCount((currentCount) => currentCount + 1)}
132
- >
133
- <Text>+</Text>
134
- </Button>
135
- </View>
136
- </View>
137
- </View>
138
- </View>
139
- </View>
140
-
141
- <View className="flex shrink-0 flex-col items-center px-5 pb-12 pt-14">
142
- <View className="flex w-full max-w-4xl flex-col">
143
- <View className="flex flex-col items-center text-center">
144
- <Text className="text-xs font-bold tracking-widest text-[#207344]">
145
- A SMALL START, A MODERN FOUNDATION
146
- </Text>
147
- <Text className="brand-serif mt-3 block text-4xl font-semibold text-[#174f32]">
148
- Everything is ready to grow.
149
- </Text>
150
- <Text className="mt-3 block max-w-xl text-sm leading-7 text-[#64786a]">
151
- Keep the pieces you need, replace the rest, and let VPT handle the cross-platform build.
152
- </Text>
153
- </View>
154
-
155
- <View className="mt-8 grid grid-cols-1 gap-4 sm:grid-cols-3">
156
- {featureCards.map((feature) => (
157
- <View
158
- key={feature.number}
159
- className={`flex min-h-52 flex-col rounded-3xl border border-[#1e663d]/15 bg-white/80 p-6 shadow-lg ${feature.tiltClass}`}
160
- >
161
- <View className="brand-serif flex h-11 w-11 items-center justify-center rounded-2xl bg-[#e3f4df] text-base font-bold text-[#197342]">
162
- {feature.number}
163
- </View>
164
- <Text className="mt-5 block text-lg font-bold text-[#174f32]">{feature.title}</Text>
165
- <Text className="mt-3 block text-sm leading-6 text-[#64786a]">
166
- {feature.description}
167
- </Text>
168
- </View>
169
- ))}
170
- </View>
171
-
172
- <View className="relative mt-8 flex flex-col overflow-hidden rounded-3xl bg-[#17673d] p-7 text-white sm:flex-row sm:items-center sm:justify-between sm:p-9">
173
- <BotanicalSprig className="botanical-sprig-cta" />
174
- <View className="relative z-10 flex max-w-lg flex-col">
175
- <Text className="text-xs font-bold tracking-widest text-[#a9e2b4]">TARO API READY</Text>
176
- <Text className="brand-serif mt-2 block text-3xl font-semibold text-white">
177
- Make this starter yours.
178
- </Text>
179
- <Text className="mt-3 block text-sm leading-6 text-[#d5ead9]">
180
- Add pages, connect your data and ship the same experience to WeChat and H5.
181
- </Text>
182
- </View>
183
- <Button
184
- className="relative z-10 mt-6 flex items-center justify-center self-start rounded-full bg-[#78dc91] px-6 py-3 text-sm font-bold text-[#0d2b18] after:border-0 sm:mt-0"
185
- onClick={() => Taro.showToast({ title: 'Hello from VPT!' })}
186
- >
187
- Try a Taro toast →
188
- </Button>
189
- </View>
190
-
191
- <View className="flex flex-col items-center px-2 pb-2 pt-9">
192
- <Text className="text-center text-xs font-bold tracking-widest text-[#819185]">
193
- VPT · OPEN SOURCE · MIT
194
- </Text>
195
- </View>
196
- </View>
197
- </View>
198
- </ScrollView>
199
- </View>
200
- )
201
- }
202
-
203
- export default IndexPage