Skip to content

Commit 8976344

Browse files
committed
fix: pricing style
1 parent afa87e2 commit 8976344

3 files changed

Lines changed: 260 additions & 147 deletions

File tree

apps/docs/src/containers/theme-studio/preview-components/dashboard-preview.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ export function DashboardPreview(): React.ReactElement {
597597
<Avatar>S</Avatar>
598598
{!sidebarCollapsed ? (
599599
<Flex vertical gap={2} className="theme-studio__docdash-copy">
600-
<Text strong>shadcn</Text>
600+
<Text strong>script</Text>
601601
<Text type="secondary">m@example.com</Text>
602602
</Flex>
603603
) : null}
Lines changed: 107 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,117 @@
11
import React from 'react';
2-
import { Button, Card, Flex, Grid, Heading, Paragraph, Progress, Segmented, Tag, Text } from '@tiny-design/react';
2+
import { IconArrowRight, IconCheckCircle } from '@tiny-design/icons';
3+
import { Button, Card, Flex, Switch, Text } from '@tiny-design/react';
4+
5+
type BillingCycle = 'monthly' | 'yearly';
6+
7+
type Plan = {
8+
name: string;
9+
caption: string;
10+
monthlyPrice: string;
11+
yearlyPrice: string;
12+
monthlyNote: string;
13+
yearlyNote: string;
14+
features: string[];
15+
};
16+
17+
const plans: Plan[] = [
18+
{
19+
name: 'Plus',
20+
caption: 'For personal use',
21+
monthlyPrice: '$24',
22+
yearlyPrice: '$19',
23+
monthlyNote: 'Billed monthly',
24+
yearlyNote: 'Billed $228 annually',
25+
features: [
26+
'Up to 5 team members',
27+
'Basic components library',
28+
'Community support',
29+
'1GB storage space',
30+
],
31+
},
32+
{
33+
name: 'Pro',
34+
caption: 'For professionals',
35+
monthlyPrice: '$59',
36+
yearlyPrice: '$49',
37+
monthlyNote: 'Billed monthly',
38+
yearlyNote: 'Billed $588 annually',
39+
features: [
40+
'Everything in Plus, and:',
41+
'Unlimited team members',
42+
'Advanced components',
43+
'Priority support',
44+
'Unlimited storage',
45+
],
46+
},
47+
];
348

449
export function PricingPreview(): React.ReactElement {
50+
const [billing, setBilling] = React.useState<BillingCycle>('yearly');
51+
552
return (
6-
<Flex vertical className="theme-studio__preview-stack">
7-
<Flex justify="space-between" align="flex-start" className="theme-studio__pricing-hero">
8-
<Flex vertical>
9-
<Text className="theme-studio__eyebrow">Pricing</Text>
10-
<Heading level={2}>Simple pricing for modern teams</Heading>
11-
<Paragraph>
12-
Choose a plan that scales from solo work to multi-product organizations.
13-
</Paragraph>
14-
<Flex className="theme-studio__pill-row">
15-
<Tag color="success">No setup fee</Tag>
16-
<Tag>Cancel anytime</Tag>
53+
<div className="theme-studio__pricing-shell">
54+
<Flex vertical className="theme-studio__pricing-stage">
55+
<Flex vertical align="center" className="theme-studio__pricing-intro">
56+
<h2 className="theme-studio__pricing-title">Pricing</h2>
57+
<Text className="theme-studio__pricing-subtitle">Check out our affordable pricing plans</Text>
58+
<Flex gap="sm" align='center'>
59+
<span className={billing === 'monthly' ? 'theme-studio__pricing-switch-label theme-studio__pricing-switch-label_active' : 'theme-studio__pricing-switch-label'}>
60+
Monthly
61+
</span>
62+
<Switch
63+
checked={billing === 'yearly'}
64+
onChange={(checked) => setBilling(checked ? 'yearly' : 'monthly')}
65+
/>
66+
<span className={billing === 'yearly' ? 'theme-studio__pricing-switch-label theme-studio__pricing-switch-label_active' : 'theme-studio__pricing-switch-label'}>
67+
Yearly
68+
</span>
1769
</Flex>
1870
</Flex>
19-
<Segmented
20-
options={[
21-
{ label: 'Monthly', value: 'monthly' },
22-
{ label: 'Yearly', value: 'yearly' },
23-
]}
24-
value="monthly"
25-
/>
26-
</Flex>
2771

28-
<Grid className="theme-studio__pricing-grid" minColumnWidth={240} gap="sm">
29-
{[
30-
{
31-
name: 'Starter',
32-
price: '$29',
33-
description: 'Perfect for small businesses.',
34-
features: ['1 workspace', 'Basic analytics', 'Community support'],
35-
},
36-
{
37-
name: 'Pro',
38-
price: '$89',
39-
description: 'More features and storage.',
40-
featured: true,
41-
features: ['5 workspaces', 'Advanced analytics', 'Priority support'],
42-
},
43-
{
44-
name: 'Scale',
45-
price: '$199',
46-
description: 'For larger teams and advanced reporting.',
47-
features: ['Unlimited workspaces', 'SSO + audit log', 'Dedicated onboarding'],
48-
},
49-
].map((plan) => (
50-
<Card
51-
key={plan.name}
52-
className={`theme-studio__pricing-card${plan.featured ? ' theme-studio__pricing-card_featured' : ''}`}>
53-
<Card.Content>
54-
<Flex align="center" className="theme-studio__pricing-card-head">
55-
{plan.featured ? <Tag color="success">Popular</Tag> : null}
56-
<Text strong>{plan.name}</Text>
57-
</Flex>
58-
<Flex vertical className="theme-studio__pricing-price">
59-
<Heading level={2}>{plan.price}</Heading>
60-
<Text type="secondary">Per workspace / month</Text>
61-
</Flex>
62-
<Paragraph>{plan.description}</Paragraph>
63-
<Flex vertical className="theme-studio__pricing-feature-list">
64-
{plan.features.map((feature) => (
65-
<Text key={feature}>{feature}</Text>
66-
))}
67-
</Flex>
68-
<Flex className="theme-studio__pricing-card-footer">
69-
<Button variant="solid" color={plan.featured ? 'primary' : 'default'}>
70-
{plan.featured ? 'Upgrade plan' : 'Choose plan'}
71-
</Button>
72-
</Flex>
73-
</Card.Content>
74-
</Card>
75-
))}
76-
</Grid>
72+
<div className="theme-studio__pricing-grid">
73+
{plans.map((plan) => {
74+
const price = billing === 'yearly' ? plan.yearlyPrice : plan.monthlyPrice;
75+
const note = billing === 'yearly' ? plan.yearlyNote : plan.monthlyNote;
7776

78-
<Grid className="theme-studio__preview-grid" minColumnWidth={280} gap="sm">
79-
<Card title="Frequently Asked Questions" className="theme-studio__preview-card">
80-
<Card.Content>
81-
<Flex vertical className="theme-studio__faq-list">
82-
<Flex vertical className="theme-studio__faq-item">
83-
<Text strong>Can I cancel anytime?</Text>
84-
<Text type="secondary">Yes. Plans can be changed or canceled without lock-in.</Text>
85-
</Flex>
86-
<Flex vertical className="theme-studio__faq-item">
87-
<Text strong>Do you offer team migration?</Text>
88-
<Text type="secondary">Pro and Scale include assisted import and onboarding.</Text>
89-
</Flex>
90-
</Flex>
91-
</Card.Content>
92-
</Card>
93-
<Card title="Usage Snapshot" className="theme-studio__preview-card">
94-
<Card.Content>
95-
<Flex vertical className="theme-studio__settings-list">
96-
<Flex vertical>
97-
<Text strong>Seats</Text>
98-
<Progress.Bar percent={68} />
99-
</Flex>
100-
<Flex vertical>
101-
<Text strong>Storage</Text>
102-
<Progress.Bar percent={42} />
103-
</Flex>
104-
</Flex>
105-
</Card.Content>
106-
</Card>
107-
</Grid>
108-
</Flex>
77+
return (
78+
<Card key={plan.name} className="theme-studio__pricing-card">
79+
<Card.Content>
80+
<Flex vertical className="theme-studio__pricing-card-content">
81+
<div>
82+
<h3 className="theme-studio__pricing-plan">{plan.name}</h3>
83+
<Text className="theme-studio__pricing-caption">{plan.caption}</Text>
84+
</div>
85+
86+
<div className="theme-studio__pricing-price-block">
87+
<div className="theme-studio__pricing-price">{price}</div>
88+
<Text className="theme-studio__pricing-note">{note}</Text>
89+
</div>
90+
91+
<div className="theme-studio__pricing-divider" />
92+
93+
<ul className="theme-studio__pricing-features">
94+
{plan.features.map((feature) => (
95+
<li key={feature} className="theme-studio__pricing-feature">
96+
<IconCheckCircle size={16} className="theme-studio__pricing-feature-icon" />
97+
<Text className={feature === 'Everything in Plus, and:' ? 'theme-studio__pricing-feature-text theme-studio__pricing-feature-text_strong' : 'theme-studio__pricing-feature-text'}>
98+
{feature}
99+
</Text>
100+
</li>
101+
))}
102+
</ul>
103+
104+
<Button variant="solid" color="primary" size="lg" className="theme-studio__pricing-action">
105+
Purchase
106+
<IconArrowRight size={16} />
107+
</Button>
108+
</Flex>
109+
</Card.Content>
110+
</Card>
111+
);
112+
})}
113+
</div>
114+
</Flex>
115+
</div>
109116
);
110117
}

0 commit comments

Comments
 (0)