@wangs-ui/create-react-app 1.0.49 → 1.0.51
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/dist/bin.js +22 -1222
- package/package.json +3 -3
- package/template/agents/AGENTS.md +5 -0
- package/template/index.html +4 -3
- package/template/package.json +21 -18
- package/template/src/App.tsx +21 -61
- package/template/src/components/AuthLayout.tsx +31 -0
- package/template/src/components/Footer.tsx +41 -0
- package/template/src/index.css +1 -1
- package/template/src/main.tsx +19 -2
- package/template/src/pages/Landing.tsx +312 -0
- package/template/src/pages/Login.tsx +151 -0
- package/template/src/pages/Register.tsx +165 -0
- package/template/tsconfig.app.json +3 -2
- package/template/vite.config.ts +14 -1
- package/template/agents/CLAUDE.md +0 -22
- /package/template/{pnpm-workspace.yaml → _pnpm-workspace.yaml} +0 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { useFormControl } from '@wangs-ui/form/react';
|
|
2
|
+
import { Link, Text } from '@wangs-ui/foundation/theme';
|
|
3
|
+
import Button from '@wangs-ui/react-core/primitive/button';
|
|
4
|
+
import Divider from '@wangs-ui/react-core/primitive/divider';
|
|
5
|
+
import Field from '@wangs-ui/react-core/primitive/field';
|
|
6
|
+
import Form from '@wangs-ui/react-core/primitive/form';
|
|
7
|
+
import Input from '@wangs-ui/react-core/primitive/input';
|
|
8
|
+
import PasswordInput from '@wangs-ui/react-core/primitive/passwordinput';
|
|
9
|
+
import { useI18n } from '@wangs-ui/react-i18n';
|
|
10
|
+
import { ArrowRightLine, LockLine, MailLine } from '@wangs-ui/react-icons';
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import { useNavigate } from 'react-router-dom';
|
|
13
|
+
|
|
14
|
+
import AuthLayout from '../components/AuthLayout';
|
|
15
|
+
|
|
16
|
+
export default function Login(): React.JSX.Element {
|
|
17
|
+
const navigate = useNavigate();
|
|
18
|
+
const { t } = useI18n();
|
|
19
|
+
const formControl = useFormControl();
|
|
20
|
+
|
|
21
|
+
const handleSubmit = (values: any) => {
|
|
22
|
+
// oxlint-disable-next-line no-console
|
|
23
|
+
console.log('Login values:', values);
|
|
24
|
+
// In a real app, you would authenticate here.
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<AuthLayout>
|
|
29
|
+
{/* Logo Section */}
|
|
30
|
+
<div className="mb-10 flex flex-col items-center text-center">
|
|
31
|
+
<div className="bg-surface-container-low border-outline-variant/30 shadow-level-1 mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg border">
|
|
32
|
+
<img src="/wangs_ui_logo.png" alt="Wangs UI Logo" className="h-7 w-7 opacity-80" />
|
|
33
|
+
</div>
|
|
34
|
+
<Text as="h1" variant="headlineLarge" color="on-surface" weight="semibold">
|
|
35
|
+
{t('Welcome back')}
|
|
36
|
+
</Text>
|
|
37
|
+
<Text variant="bodyMedium" color="secondary" className="mt-2">
|
|
38
|
+
{t('Sign in to your Wangs UI account')}
|
|
39
|
+
</Text>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
{/* Login Card */}
|
|
43
|
+
<div className="bg-surface-container-lowest border-outline-variant/30 shadow-level-1 rounded-xl border p-10">
|
|
44
|
+
<Form control={formControl} className="space-y-6" onSubmit={handleSubmit}>
|
|
45
|
+
{/* Email Field */}
|
|
46
|
+
<Field label={t('Email Address')} name="email" required>
|
|
47
|
+
<Input
|
|
48
|
+
name="email"
|
|
49
|
+
type="email"
|
|
50
|
+
placeholder="name@company.com"
|
|
51
|
+
startElement={<MailLine className="text-on-surface-variant ml-2 size-5" />}
|
|
52
|
+
className="w-full"
|
|
53
|
+
size="md"
|
|
54
|
+
/>
|
|
55
|
+
</Field>
|
|
56
|
+
|
|
57
|
+
{/* Password Field */}
|
|
58
|
+
<Field
|
|
59
|
+
label={
|
|
60
|
+
<div className="flex w-full items-center justify-between">
|
|
61
|
+
<span>{t('Password')}</span>
|
|
62
|
+
<Link href="#">{t('Forgot Password?')}</Link>
|
|
63
|
+
</div>
|
|
64
|
+
}
|
|
65
|
+
name="password"
|
|
66
|
+
required
|
|
67
|
+
>
|
|
68
|
+
<PasswordInput
|
|
69
|
+
name="password"
|
|
70
|
+
placeholder="••••••••"
|
|
71
|
+
startElement={<LockLine className="text-on-surface-variant ml-2 size-5" />}
|
|
72
|
+
className="w-full"
|
|
73
|
+
size="md"
|
|
74
|
+
/>
|
|
75
|
+
</Field>
|
|
76
|
+
|
|
77
|
+
{/* Sign In Button */}
|
|
78
|
+
<Button
|
|
79
|
+
type="submit"
|
|
80
|
+
className="group mt-10 flex w-full items-center justify-center gap-2"
|
|
81
|
+
variant="filled"
|
|
82
|
+
severity="primary"
|
|
83
|
+
size="lg"
|
|
84
|
+
label={t('Sign In')}
|
|
85
|
+
rightIcon={
|
|
86
|
+
<ArrowRightLine className="size-5 transition-transform group-hover:translate-x-1" />
|
|
87
|
+
}
|
|
88
|
+
/>
|
|
89
|
+
</Form>
|
|
90
|
+
|
|
91
|
+
{/* Divider */}
|
|
92
|
+
<Divider className="my-10" label={t('Or continue with')} />
|
|
93
|
+
|
|
94
|
+
{/* Social Logins */}
|
|
95
|
+
<div className="grid grid-cols-2 gap-4">
|
|
96
|
+
<Button
|
|
97
|
+
type="button"
|
|
98
|
+
variant="outline"
|
|
99
|
+
severity="secondary"
|
|
100
|
+
size="md"
|
|
101
|
+
label={t('GitHub')}
|
|
102
|
+
leftIcon={
|
|
103
|
+
<svg className="h-5 w-5 fill-current" viewBox="0 0 24 24">
|
|
104
|
+
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
|
|
105
|
+
</svg>
|
|
106
|
+
}
|
|
107
|
+
className="w-full"
|
|
108
|
+
/>
|
|
109
|
+
<Button
|
|
110
|
+
type="button"
|
|
111
|
+
variant="outline"
|
|
112
|
+
severity="secondary"
|
|
113
|
+
size="md"
|
|
114
|
+
label={t('Google')}
|
|
115
|
+
leftIcon={
|
|
116
|
+
<svg className="h-5 w-5" viewBox="0 0 24 24">
|
|
117
|
+
<path
|
|
118
|
+
fill="#4285F4"
|
|
119
|
+
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
|
|
120
|
+
/>
|
|
121
|
+
<path
|
|
122
|
+
fill="#34A853"
|
|
123
|
+
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
|
|
124
|
+
/>
|
|
125
|
+
<path
|
|
126
|
+
fill="#FBBC05"
|
|
127
|
+
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
|
|
128
|
+
/>
|
|
129
|
+
<path
|
|
130
|
+
fill="#EA4335"
|
|
131
|
+
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
|
|
132
|
+
/>
|
|
133
|
+
</svg>
|
|
134
|
+
}
|
|
135
|
+
className="w-full"
|
|
136
|
+
/>
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
{/* Register Link */}
|
|
140
|
+
<div className="mt-8 text-center">
|
|
141
|
+
<Text variant="bodyMedium" color="secondary">
|
|
142
|
+
{t("Don't have an account?")}{' '}
|
|
143
|
+
<Link onClick={() => navigate('/register')} className="font-semibold" color="primary">
|
|
144
|
+
{t('Sign up')}
|
|
145
|
+
</Link>
|
|
146
|
+
</Text>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
</AuthLayout>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { useFormControl } from '@wangs-ui/form/react';
|
|
2
|
+
import { Link, Text } from '@wangs-ui/foundation/theme';
|
|
3
|
+
import Button from '@wangs-ui/react-core/primitive/button';
|
|
4
|
+
import Checkbox from '@wangs-ui/react-core/primitive/checkbox';
|
|
5
|
+
import Divider from '@wangs-ui/react-core/primitive/divider';
|
|
6
|
+
import Field from '@wangs-ui/react-core/primitive/field';
|
|
7
|
+
import Form from '@wangs-ui/react-core/primitive/form';
|
|
8
|
+
import Input from '@wangs-ui/react-core/primitive/input';
|
|
9
|
+
import PasswordInput from '@wangs-ui/react-core/primitive/passwordinput';
|
|
10
|
+
import { useI18n } from '@wangs-ui/react-i18n';
|
|
11
|
+
import { ArrowRightLine, LockLine, MailLine, UserLine } from '@wangs-ui/react-icons';
|
|
12
|
+
import React, { useState } from 'react';
|
|
13
|
+
import { useNavigate } from 'react-router-dom';
|
|
14
|
+
|
|
15
|
+
import AuthLayout from '../components/AuthLayout';
|
|
16
|
+
|
|
17
|
+
export default function Register(): React.JSX.Element {
|
|
18
|
+
const navigate = useNavigate();
|
|
19
|
+
const { t } = useI18n();
|
|
20
|
+
const formControl = useFormControl();
|
|
21
|
+
const [agreeTerms, setAgreeTerms] = useState(false);
|
|
22
|
+
|
|
23
|
+
const handleSubmit = (values: any) => {
|
|
24
|
+
// oxlint-disable-next-line no-console
|
|
25
|
+
console.log('Register values:', values, 'agreeTerms:', agreeTerms);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<AuthLayout>
|
|
30
|
+
<div className="bg-surface border-outline-variant/30 shadow-level-1 rounded-xl border p-10">
|
|
31
|
+
{/* Logo Section */}
|
|
32
|
+
<div className="mb-10 flex flex-col items-center text-center">
|
|
33
|
+
<div className="bg-surface-container-low border-outline-variant/30 shadow-level-1 mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg border">
|
|
34
|
+
<img src="/wangs_ui_logo.png" alt="Wangs UI Logo" className="h-7 w-7 opacity-80" />
|
|
35
|
+
</div>
|
|
36
|
+
<Text as="h1" variant="headlineLarge" color="on-surface" weight="semibold">
|
|
37
|
+
{t('Create an account')}
|
|
38
|
+
</Text>
|
|
39
|
+
<Text variant="bodyMedium" color="secondary" className="mt-2">
|
|
40
|
+
{t('Join Wangs UI to get started')}
|
|
41
|
+
</Text>
|
|
42
|
+
</div>{' '}
|
|
43
|
+
<Form control={formControl} className="space-y-6" onSubmit={handleSubmit}>
|
|
44
|
+
{/* Full Name Field */}
|
|
45
|
+
<Field label={t('Full Name')} name="fullName" required>
|
|
46
|
+
<Input
|
|
47
|
+
name="fullName"
|
|
48
|
+
type="text"
|
|
49
|
+
placeholder="Jane Doe"
|
|
50
|
+
startElement={<UserLine className="text-on-surface-variant ml-2 size-5" />}
|
|
51
|
+
className="w-full"
|
|
52
|
+
size="md"
|
|
53
|
+
/>
|
|
54
|
+
</Field>
|
|
55
|
+
|
|
56
|
+
{/* Email Field */}
|
|
57
|
+
<Field label={t('Email Address')} name="email" required>
|
|
58
|
+
<Input
|
|
59
|
+
name="email"
|
|
60
|
+
type="email"
|
|
61
|
+
placeholder="jane@example.com"
|
|
62
|
+
startElement={<MailLine className="text-on-surface-variant ml-2 size-5" />}
|
|
63
|
+
className="w-full"
|
|
64
|
+
size="md"
|
|
65
|
+
/>
|
|
66
|
+
</Field>
|
|
67
|
+
|
|
68
|
+
{/* Password Field */}
|
|
69
|
+
<Field label={t('Password')} name="password" required>
|
|
70
|
+
<PasswordInput
|
|
71
|
+
name="password"
|
|
72
|
+
placeholder="••••••••"
|
|
73
|
+
startElement={<LockLine className="text-on-surface-variant ml-2 size-5" />}
|
|
74
|
+
className="w-full"
|
|
75
|
+
size="md"
|
|
76
|
+
/>
|
|
77
|
+
</Field>
|
|
78
|
+
|
|
79
|
+
{/* Terms and Conditions */}
|
|
80
|
+
<div className="flex items-start gap-3">
|
|
81
|
+
<Checkbox
|
|
82
|
+
id="terms"
|
|
83
|
+
name="terms"
|
|
84
|
+
checked={agreeTerms}
|
|
85
|
+
onChange={setAgreeTerms}
|
|
86
|
+
className="mt-1"
|
|
87
|
+
/>
|
|
88
|
+
<Text as="label" htmlFor="terms" variant="bodyMedium" color="secondary">
|
|
89
|
+
{t('I agree to the')} <Link href="#">{t('Terms of Service')}</Link> {t('and')}{' '}
|
|
90
|
+
<Link href="#">{t('Privacy Policy')}</Link>.
|
|
91
|
+
</Text>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
{/* Create Account Button */}
|
|
95
|
+
<Button
|
|
96
|
+
type="submit"
|
|
97
|
+
className="group flex w-full items-center justify-center gap-2"
|
|
98
|
+
variant="filled"
|
|
99
|
+
severity="primary"
|
|
100
|
+
size="lg"
|
|
101
|
+
label={t('Create Account')}
|
|
102
|
+
rightIcon={
|
|
103
|
+
<ArrowRightLine className="size-5 transition-transform group-hover:translate-x-1" />
|
|
104
|
+
}
|
|
105
|
+
/>
|
|
106
|
+
</Form>
|
|
107
|
+
{/* Divider */}
|
|
108
|
+
<Divider className="mt-8" label={t('Or continue with')} />
|
|
109
|
+
{/* Social Logins */}
|
|
110
|
+
<div className="mt-8 grid grid-cols-2 gap-4">
|
|
111
|
+
<Button
|
|
112
|
+
type="button"
|
|
113
|
+
variant="outline"
|
|
114
|
+
severity="secondary"
|
|
115
|
+
size="md"
|
|
116
|
+
label={t('Google')}
|
|
117
|
+
leftIcon={
|
|
118
|
+
<svg className="h-5 w-5" viewBox="0 0 24 24">
|
|
119
|
+
<path
|
|
120
|
+
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
|
|
121
|
+
fill="#4285F4"
|
|
122
|
+
/>
|
|
123
|
+
<path
|
|
124
|
+
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
|
|
125
|
+
fill="#34A853"
|
|
126
|
+
/>
|
|
127
|
+
<path
|
|
128
|
+
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
|
|
129
|
+
fill="#FBBC05"
|
|
130
|
+
/>
|
|
131
|
+
<path
|
|
132
|
+
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
|
|
133
|
+
fill="#EA4335"
|
|
134
|
+
/>
|
|
135
|
+
</svg>
|
|
136
|
+
}
|
|
137
|
+
className="w-full"
|
|
138
|
+
/>
|
|
139
|
+
<Button
|
|
140
|
+
type="button"
|
|
141
|
+
variant="outline"
|
|
142
|
+
severity="secondary"
|
|
143
|
+
size="md"
|
|
144
|
+
label={t('GitHub')}
|
|
145
|
+
leftIcon={
|
|
146
|
+
<svg className="h-5 w-5 fill-current" viewBox="0 0 24 24">
|
|
147
|
+
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
|
|
148
|
+
</svg>
|
|
149
|
+
}
|
|
150
|
+
className="w-full"
|
|
151
|
+
/>
|
|
152
|
+
</div>
|
|
153
|
+
{/* Login Link */}
|
|
154
|
+
<div className="mt-8 text-center">
|
|
155
|
+
<Text variant="bodyMedium" color="secondary">
|
|
156
|
+
{t('Already have an account?')}{' '}
|
|
157
|
+
<Link onClick={() => navigate('/login')} className="font-semibold" color="primary">
|
|
158
|
+
{t('Log in')}
|
|
159
|
+
</Link>
|
|
160
|
+
</Text>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</AuthLayout>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
-
"target": "
|
|
4
|
+
"target": "ES2023",
|
|
5
5
|
"useDefineForClassFields": true,
|
|
6
|
-
"lib": ["
|
|
6
|
+
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
|
7
7
|
"module": "ESNext",
|
|
8
8
|
"skipLibCheck": true,
|
|
9
9
|
|
|
10
10
|
/* Bundler mode */
|
|
11
11
|
"moduleResolution": "bundler",
|
|
12
|
+
"customConditions": ["wangs-ui-dev"],
|
|
12
13
|
"allowImportingTsExtensions": false,
|
|
13
14
|
"isolatedModules": true,
|
|
14
15
|
"moduleDetection": "force",
|
package/template/vite.config.ts
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import tailwindcss from '@tailwindcss/vite';
|
|
2
2
|
import react from '@vitejs/plugin-react';
|
|
3
|
+
import { visualizer } from 'rollup-plugin-visualizer';
|
|
3
4
|
import { defineConfig } from 'vite';
|
|
4
5
|
|
|
5
6
|
// https://vite.dev/config/
|
|
6
7
|
export default defineConfig({
|
|
7
|
-
plugins: [
|
|
8
|
+
plugins: [
|
|
9
|
+
react(),
|
|
10
|
+
tailwindcss(),
|
|
11
|
+
visualizer({
|
|
12
|
+
filename: 'dist/stats.html',
|
|
13
|
+
gzipSize: true,
|
|
14
|
+
brotliSize: true,
|
|
15
|
+
open: process.env.ANALYZE === 'true',
|
|
16
|
+
}),
|
|
17
|
+
],
|
|
18
|
+
resolve: {
|
|
19
|
+
conditions: ['wangs-ui-dev'],
|
|
20
|
+
},
|
|
8
21
|
});
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Claude Code Project Guidelines
|
|
2
|
-
|
|
3
|
-
This project uses **Wangs UI**, React 19, and Vite 8.
|
|
4
|
-
|
|
5
|
-
## MCP Tools
|
|
6
|
-
|
|
7
|
-
The `@wangs-ui/mcp` server is configured in `.mcp.json`. Use it to inspect Wangs UI component documentation and story specifications before implementing new views.
|
|
8
|
-
|
|
9
|
-
## Development Commands
|
|
10
|
-
|
|
11
|
-
- `pnpm dev`: Start local development server
|
|
12
|
-
- `pnpm build`: Type check and build production bundle
|
|
13
|
-
- `pnpm lint`: Run Oxlint linter
|
|
14
|
-
- `pnpm format`: Run Oxfmt formatter
|
|
15
|
-
|
|
16
|
-
## Key Coding Rules
|
|
17
|
-
|
|
18
|
-
- Use `@wangs-ui/react-core` for all UI elements (do not use unstyled raw HTML inputs/buttons).
|
|
19
|
-
- Use `@wangs-ui/react-icons` for iconography.
|
|
20
|
-
- Wrap all UI strings in `t('...')` from `useI18n()`.
|
|
21
|
-
- Use `useLocaleFormatter()` for date, number, and currency formatting.
|
|
22
|
-
- See `AGENTS.md` and `.agents/skills/` for in-depth design system standards.
|
|
File without changes
|