Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 85 additions & 4 deletions apps/docs/app/(home)/components/code-example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
import type { Mode, CheckoutStyle, Customizations } from './types';
import { CopyButton } from '../../../components/ui/copy-button';
import type { CheckoutStyle, Customizations, Mode } from './types';

interface CodeExampleProps {
selectedMode: Mode;
Expand All @@ -12,7 +12,7 @@ interface CodeExampleProps {
}

export function CodeExample({ selectedMode, checkoutStyle, customizations }: CodeExampleProps) {

const getCodeExample = () => {
if (checkoutStyle === 'page') {
return `// Page-level cart components removed for tip flow MVP
Expand Down Expand Up @@ -55,10 +55,91 @@ function App() {
}}
/>
);
}`;
} else if (selectedMode === 'buyNow') {
return `import { PaymentButton } from '@solana-commerce/react';
function App() {
return (
<PaymentButton
config={{
mode: 'buyNow',
merchant: {
name: '${customizations.merchantName}',
wallet: '${customizations.walletAddress}',${customizations.merchantDescription ? `
description: '${customizations.merchantDescription}',` : ''}
},
theme: {
primaryColor: '${customizations.primaryColor}',
secondaryColor: '${customizations.secondaryColor}',
backgroundColor: '${customizations.backgroundColor}',
textColor: '${customizations.textColor}',
borderRadius: '${customizations.borderRadius}',${customizations.buttonShadow ? `
buttonShadow: '${customizations.buttonShadow}',` : ''}${customizations.buttonBorder ? `
buttonBorder: '${customizations.buttonBorder}',` : ''}
},
allowedMints: ${JSON.stringify(customizations.supportedCurrencies)},${customizations.showQR ? '' : `
showQR: false,`}
position: '${customizations.position}',
}}
paymentConfig={{
products: [
{
id: 'product-1',
name: '${customizations.productName || 'Digital Product'}',
description: '${customizations.productDescription || 'Instant delivery'}',
price: ${customizations.productPrice || 0.1},
quantity: 1
}
]
}}
onPaymentSuccess={(signature) => {
console.log('Order successful:', signature);
}}
/>
);
}`;
} else if (selectedMode === 'cart') {
return `import { PaymentButton } from '@solana-commerce/react';
function App() {
return (
<PaymentButton
config={{
mode: 'cart',
merchant: {
name: '${customizations.merchantName}',
wallet: '${customizations.walletAddress}',
},
theme: {
primaryColor: '${customizations.primaryColor}',
secondaryColor: '${customizations.secondaryColor}',
},
}}
paymentConfig={{
products: [
{
id: 'item-1',
name: 'Premium T-Shirt',
price: 25.00,
quantity: 2
},
{
id: 'item-2',
name: 'Digital Gift Card',
price: 50.00,
quantity: 1
}
]
}}
onPaymentSuccess={(signature) => {
console.log('Cart checkout successful:', signature);
}}
/>
);
}`;
} else {
return `// Cart modes removed for tip flow MVP
// Only tip mode is available in this version`;
return `// Select a mode to see code example`;
}

// Note: Simplified for tip flow MVP
Expand Down
58 changes: 29 additions & 29 deletions apps/docs/app/(home)/components/demo-preview.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
'use client';

import React from 'react';
import { SolanaCommerceClient } from './solana-commerce-client';
import { type CommerceMode } from '@solana-commerce/react';
import { SolanaCommerceClient } from './solana-commerce-client';

import type { Mode, CheckoutStyle, Customizations, DemoConfig } from './types';
import { IconCursorarrowRays, IconHandPointUpLeftFill, IconInsetFilledCenterRectangle, IconApp, IconShadow } from 'symbols-react';
import { IconApp, IconCursorarrowRays, IconHandPointUpLeftFill, IconInsetFilledCenterRectangle, IconShadow } from 'symbols-react';
import { Switch } from '../../../components/ui/switch';
import type { CheckoutStyle, Customizations, DemoConfig, Mode } from './types';
// selectors are inlined as mini selects below for compactness

// Modal preview components
Expand All @@ -24,34 +23,34 @@ interface DemoPreviewProps {
}

// Modal Preview Component - wrapper that positions the modal content properly
function ModalPreview({ config, selectedMode }: {
config: DemoConfig;
selectedMode: Mode;
function ModalPreview({ config, selectedMode }: {
config: DemoConfig;
selectedMode: Mode;
}) {
return (
<div
style={{
backgroundImage: `repeating-linear-gradient(
<div
style={{
backgroundImage: `repeating-linear-gradient(
45deg,
transparent,
transparent 10px,
rgba(46, 77, 97, 0.08) 10px,
rgba(46, 77, 97, 0.08) 11px
)`
}}
className="relative h-full w-full flex items-center justify-center p-4">
<ModalPreviewContent
}}
className="relative h-full w-full flex items-center justify-center p-4">
<ModalPreviewContent
config={config}
selectedMode={selectedMode}
/>
</div>
);
}

export function DemoPreview({
selectedMode,
checkoutStyle,
customizations,
export function DemoPreview({
selectedMode,
checkoutStyle,
customizations,
config,
onCheckoutStyleChange,
onCustomizationChange
Expand All @@ -63,7 +62,7 @@ export function DemoPreview({
{selectedMode === 'qrCustomization' ? (
// QR Customization Mode - Show QR preview instead of commerce flow
<div className="h-full p-6">
<QRCustomizationPreview
<QRCustomizationPreview
theme={{
primaryColor: customizations.primaryColor,
secondaryColor: customizations.secondaryColor,
Expand All @@ -83,22 +82,23 @@ export function DemoPreview({
<IconCursorarrowRays className="w-3 h-3 fill-gray-500" />
<span className="text-xs font-mono">Button Preview</span>
</div>
<div
style={{
backgroundImage: `repeating-linear-gradient(
<div
style={{
backgroundImage: `repeating-linear-gradient(
45deg,
transparent,
transparent 10px,
rgba(46, 77, 97, 0.08) 10px,
rgba(46, 77, 97, 0.08) 11px
)`
}}
className="flex flex-col items-center justify-center border border-gray-200 rounded-lg bg-zinc-100 p-6 py-12 text-center relative">
}}
className="flex flex-col items-center justify-center border border-gray-200 rounded-lg bg-zinc-100 p-6 py-12 text-center relative">
<SolanaCommerceClient
config={{
...config,
mode: config.mode === 'qrCustomization' ? 'tip' : config.mode as CommerceMode
}}
paymentConfig={config.products ? { products: config.products } : undefined}
variant={customizations.buttonVariant}
onPayment={(amount: number, currency: string) => {
console.log('Demo payment:', { amount, currency });
Expand Down Expand Up @@ -129,7 +129,7 @@ export function DemoPreview({
<div className="flex items-center gap-2 h-7 px-2 rounded-md border border-gray-200 bg-white">
<IconShadow className="w-3.5 h-3.5 opacity-60" />
<div className="flex items-center gap-1">
{(['none','sm','md','lg','xl'] as const).map(level => {
{(['none', 'sm', 'md', 'lg', 'xl'] as const).map(level => {
const active = (customizations.buttonShadow ?? 'md') === level;
const label = level === 'xl' ? 'XL' : level === 'none' ? 'N' : level.toUpperCase();
return (
Expand Down Expand Up @@ -165,7 +165,7 @@ export function DemoPreview({
</div>
</div>
</div>

{/* Modal Preview Section */}
<div className="h-full">
<div className="h-[750px] overflow-hidden relative rounded-lg border border-gray-200 bg-zinc-100">
Expand All @@ -174,9 +174,9 @@ export function DemoPreview({
<IconInsetFilledCenterRectangle className="w-3 h-3 fill-gray-400" />
<span className="text-xs font-mono">Modal Preview</span>
</div>
<ModalPreview
config={config}
selectedMode={selectedMode} />
<ModalPreview
config={config}
selectedMode={selectedMode} />
</div>
</div>
</div>
Expand Down Expand Up @@ -205,7 +205,7 @@ export function DemoPreview({
<div className="text-2xl mb-4">🎯</div>
<h3 className="text-lg font-semibold text-gray-700 mb-2">Tip Flow MVP</h3>
<p className="text-gray-600 text-sm max-w-md">
Cart and product features have been removed to focus on the tip flow as the MVP.
Cart and product features have been removed to focus on the tip flow as the MVP.
Click the button above to test the tip modal!
</p>
</div>
Expand Down
51 changes: 37 additions & 14 deletions apps/docs/app/(home)/components/interactive-demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

import { useState } from 'react';

import { UnifiedTabBar } from './unified-tab-bar';
import { CodeExample } from './code-example';
import { CustomizationPanel } from './customization-panel';
import { DemoPreview } from './demo-preview';
import { CodeExample } from './code-example';
import type { Mode, CheckoutStyle, Customizations } from './types';
import type { CheckoutStyle, Customizations, Mode } from './types';
import { UnifiedTabBar } from './unified-tab-bar';
// Note: OrderItem removed for tip flow MVP

export function InteractiveDemo() {
const [selectedMode, setSelectedMode] = useState<Mode>('tip');
const [checkoutStyle, setCheckoutStyle] = useState<CheckoutStyle>('modal');
const [isSwapped, setIsSwapped] = useState(false);
const [activeTab, setActiveTab] = useState<'demo' | 'code'>('demo');

// Customization state
const [customizations, setCustomizations] = useState<Customizations>({
primaryColor: '#9945FF',
Expand Down Expand Up @@ -52,7 +52,7 @@ export function InteractiveDemo() {
// Apply swap logic to colors
const effectivePrimaryColor = isSwapped ? customizations.secondaryColor : customizations.primaryColor;
const effectiveSecondaryColor = isSwapped ? customizations.primaryColor : customizations.secondaryColor;

const baseConfig = {
merchant: merchantConfig,
theme: {
Expand All @@ -78,24 +78,42 @@ export function InteractiveDemo() {
...baseConfig,
showProductDetails: false
};
// Note: buyNow and cart modes removed for tip flow MVP
case 'qrCustomization':
return {
mode: 'qrCustomization' as const,
...baseConfig,
// Note: No products needed for QR customization
};
case 'buyNow':
return {
mode: 'buyNow' as const,
...baseConfig,
products: [{
id: 'demo-product-1',
name: customizations.productName || 'Demo Product',
description: customizations.productDescription || 'Instant delivery',
price: Number(customizations.productPrice) || 0.1,
quantity: 1
}]
};
case 'cart':
return {
mode: 'cart' as const,
...baseConfig,
products: [
{ id: '1', name: 'Premium Item', price: 1.5, quantity: 1 },
{ id: '2', name: 'Digital Add-on', price: 0.5, quantity: 2 }
]
};
default:
return {
mode: 'tip' as const,
...baseConfig,
// Note: Products removed for tip flow MVP
};
}
};

const updateCustomization = <K extends keyof typeof customizations>(
key: K,
key: K,
value: typeof customizations[K]
) => {
setCustomizations(prev => ({
Expand All @@ -104,11 +122,16 @@ export function InteractiveDemo() {
}));
};

// Ensure layout switches based on mode selection
// Ensure layout switches based on mode selection
const handleModeChange = (mode: Mode) => {
setSelectedMode(mode);
if (mode === 'tip') setCheckoutStyle('modal');
else setCheckoutStyle('page');
// Use modal style (Button Preview) for tip, buyNow, and cart
if (mode === 'qrCustomization') {
// QR mode handles its own layout
} else {
setCheckoutStyle('modal');
}
};

return (
Expand All @@ -122,7 +145,7 @@ export function InteractiveDemo() {
onTabChange={setActiveTab}
checkoutStyle={checkoutStyle}
/>

<div className="grid grid-cols-1 sm:grid-cols-12 divide-x divide-gray-200 h-[calc(100vh-48px)]">
{/* Left Column - Scrollable Customization Panel */}
<div className="col-span-4 overflow-y-auto py-4">
Expand All @@ -137,7 +160,7 @@ export function InteractiveDemo() {
config={getConfigForMode()}
/>
</div>

{/* Right Column - Fixed Content */}
<div className="col-span-8 overflow-hidden">
{activeTab === 'demo' ? (
Expand Down Expand Up @@ -165,4 +188,4 @@ export function InteractiveDemo() {
</div>
</section>
);
}
}
Loading