Skip to content
Merged
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
111 changes: 111 additions & 0 deletions packages/swap-widget/src/demo/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,117 @@ body,
justify-content: center;
}

.demo-widget-container.demo-widget-container-modal {
align-self: stretch;
align-items: center;
}

.demo-launch {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 420px;
max-width: 100%;
min-height: 320px;
padding: 24px;
}

.demo-launch-btn {
display: flex;
align-items: center;
gap: 10px;
padding: 16px 32px;
border: none;
border-radius: 14px;
background: var(--demo-accent);
color: #ffffff;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.15s ease;
box-shadow: 0 8px 24px color-mix(in srgb, var(--demo-accent), transparent 65%);
}

.demo-launch-btn:hover {
transform: translateY(-1px);
box-shadow: 0 10px 28px color-mix(in srgb, var(--demo-accent), transparent 55%);
}

.demo-launch-btn:active {
transform: scale(0.98);
}

.demo-modal-overlay {
position: fixed;
inset: 0;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
overflow-y: auto;
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(6px);
animation: demo-modal-fade-in 0.15s ease;
}

.demo-modal-backdrop {
position: absolute;
inset: 0;
border: none;
padding: 0;
background: transparent;
cursor: default;
}

.demo-modal {
position: relative;
margin: auto;
animation: demo-modal-pop-in 0.2s ease;
}

.demo-modal-close {
position: absolute;
top: -40px;
right: 0;
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border: none;
border-radius: 50%;
background: rgba(255, 255, 255, 0.12);
color: #ffffff;
cursor: pointer;
transition: background 0.15s ease;
}

.demo-modal-close:hover {
background: rgba(255, 255, 255, 0.24);
}

@keyframes demo-modal-fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

@keyframes demo-modal-pop-in {
from {
opacity: 0;
transform: translateY(8px) scale(0.98);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}

.demo-footer {
padding: 20px;
text-align: center;
Expand Down
54 changes: 52 additions & 2 deletions packages/swap-widget/src/demo/DemoCustomizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,14 @@ const DEFAULT_LIGHT: ThemeColors = { bg: '#f8f9fc', card: '#ffffff', accent: '#3

const STORAGE_KEY = 'ssw-demo-config'

export type DisplayMode = 'inline' | 'modal'

type StoredConfig = {
partnerCode?: string
darkColors?: ThemeColors
lightColors?: ThemeColors
selectedPreset?: string | null
displayMode?: DisplayMode
}

const loadConfig = (): StoredConfig => {
Expand All @@ -90,17 +93,18 @@ export const useDemoTheme = (theme: 'light' | 'dark') => {
const [darkColors, setDarkColors] = useState<ThemeColors>(stored.darkColors ?? DEFAULT_DARK)
const [lightColors, setLightColors] = useState<ThemeColors>(stored.lightColors ?? DEFAULT_LIGHT)
const [selectedPreset, setSelectedPreset] = useState<string | null>(stored.selectedPreset ?? null)
const [displayMode, setDisplayMode] = useState<DisplayMode>(stored.displayMode ?? 'inline')

useEffect(() => {
try {
localStorage.setItem(
STORAGE_KEY,
JSON.stringify({ partnerCode, darkColors, lightColors, selectedPreset }),
JSON.stringify({ partnerCode, darkColors, lightColors, selectedPreset, displayMode }),
)
} catch {
// ignore write failures (e.g. storage unavailable)
}
}, [partnerCode, darkColors, lightColors, selectedPreset])
}, [partnerCode, darkColors, lightColors, selectedPreset, displayMode])

const currentColors = theme === 'dark' ? darkColors : lightColors

Expand Down Expand Up @@ -135,6 +139,8 @@ export const useDemoTheme = (theme: 'light' | 'dark') => {
setLightColors,
selectedPreset,
setSelectedPreset,
displayMode,
setDisplayMode,
themeConfig,
demoStyle,
}
Expand All @@ -158,6 +164,8 @@ export const DemoCustomizer = ({ theme, setTheme, state }: DemoCustomizerProps)
setLightColors,
selectedPreset,
setSelectedPreset,
displayMode,
setDisplayMode,
} = state

const currentColors = theme === 'dark' ? darkColors : lightColors
Expand Down Expand Up @@ -310,6 +318,48 @@ ${formatColors(lightColors, 'light')}
</div>
</div>

<div className='demo-customizer-section'>
<span className='demo-customizer-label'>Display</span>
<div className='demo-theme-toggle'>
<button
className={`demo-theme-btn ${displayMode === 'inline' ? 'active' : ''}`}
onClick={() => setDisplayMode('inline')}
type='button'
>
<svg
width='16'
height='16'
viewBox='0 0 24 24'
fill='none'
stroke='currentColor'
strokeWidth='2'
>
<rect x='3' y='3' width='18' height='18' rx='2' />
<rect x='8' y='8' width='8' height='8' rx='1' />
</svg>
Inline
</button>
<button
className={`demo-theme-btn ${displayMode === 'modal' ? 'active' : ''}`}
onClick={() => setDisplayMode('modal')}
type='button'
>
<svg
width='16'
height='16'
viewBox='0 0 24 24'
fill='none'
stroke='currentColor'
strokeWidth='2'
>
<rect x='3' y='3' width='18' height='18' rx='2' opacity='0.4' />
<rect x='7' y='9' width='10' height='8' rx='1' />
</svg>
Modal
</button>
</div>
</div>

<div className='demo-customizer-section'>
<span className='demo-customizer-label'>Background Color</span>
<div className='demo-color-input-row'>
Expand Down
34 changes: 23 additions & 11 deletions packages/swap-widget/src/demo/ExternalWalletApp.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import './App.css'

import { useAppKit, useAppKitAccount } from '@reown/appkit/react'
import { useCallback, useEffect, useState } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'

import { SwapWidget } from '../components/SwapWidget'
import { initializeAppKit } from '../config/appkit'
import { truncateAddress } from '../types'
import { DemoCustomizer, useDemoTheme } from './DemoCustomizer'
import { WidgetModal } from './WidgetModal'

const PROJECT_ID = import.meta.env.VITE_WALLETCONNECT_PROJECT_ID

Expand Down Expand Up @@ -67,7 +68,7 @@ const ExternalDemoBody = ({ theme, setTheme }: ExternalDemoBodyProps) => {
const [showCustomizer, setShowCustomizer] = useState(true)

const themeState = useDemoTheme(theme)
const { themeConfig, partnerCode, demoStyle } = themeState
const { themeConfig, partnerCode, demoStyle, displayMode } = themeState

const handleSwapSuccess = useCallback((txHash: string) => {
console.log('Swap successful:', txHash)
Expand All @@ -77,6 +78,20 @@ const ExternalDemoBody = ({ theme, setTheme }: ExternalDemoBodyProps) => {
console.error('Swap failed:', error)
}, [])

const widget = useMemo(
() => (
<SwapWidget
partnerCode={partnerCode || undefined}
theme={themeConfig}
onSwapSuccess={handleSwapSuccess}
onSwapError={handleSwapError}
showPoweredBy={true}
showConnectButton={false}
/>
),
[partnerCode, themeConfig, handleSwapSuccess, handleSwapError],
)

return (
<div className={`demo-app ${theme}`} style={demoStyle}>
<header className='demo-header'>
Expand Down Expand Up @@ -141,15 +156,12 @@ const ExternalDemoBody = ({ theme, setTheme }: ExternalDemoBodyProps) => {
<DemoCustomizer theme={theme} setTheme={setTheme} state={themeState} />
)}

<div className='demo-widget-container'>
<SwapWidget
partnerCode={partnerCode || undefined}
theme={themeConfig}
onSwapSuccess={handleSwapSuccess}
onSwapError={handleSwapError}
showPoweredBy={true}
showConnectButton={false}
/>
<div
className={`demo-widget-container${
displayMode === 'modal' ? ' demo-widget-container-modal' : ''
}`}
>
{displayMode === 'modal' ? <WidgetModal>{widget}</WidgetModal> : widget}
</div>
</div>
</div>
Expand Down
36 changes: 24 additions & 12 deletions packages/swap-widget/src/demo/InternalWalletApp.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import './App.css'

import { useCallback, useEffect, useState } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'

import { SwapWidget } from '../components/SwapWidget'
import { DemoCustomizer, useDemoTheme } from './DemoCustomizer'
import { WidgetModal } from './WidgetModal'

const PROJECT_ID = import.meta.env.VITE_WALLETCONNECT_PROJECT_ID

Expand All @@ -18,7 +19,7 @@ const InternalDemoBody = ({ theme, setTheme }: InternalDemoBodyProps) => {
const [showCustomizer, setShowCustomizer] = useState(true)

const themeState = useDemoTheme(theme)
const { themeConfig, partnerCode, demoStyle } = themeState
const { themeConfig, partnerCode, demoStyle, displayMode } = themeState

const handleSwapSuccess = useCallback((txHash: string) => {
console.log('Swap successful:', txHash)
Expand All @@ -28,6 +29,21 @@ const InternalDemoBody = ({ theme, setTheme }: InternalDemoBodyProps) => {
console.error('Swap failed:', error)
}, [])

const widget = useMemo(
() => (
<SwapWidget
partnerCode={partnerCode || undefined}
theme={themeConfig}
onSwapSuccess={handleSwapSuccess}
onSwapError={handleSwapError}
showPoweredBy={true}
showConnectButton={true}
walletConnectProjectId={PROJECT_ID}
/>
),
[partnerCode, themeConfig, handleSwapSuccess, handleSwapError],
)

return (
<div className={`demo-app ${theme}`} style={demoStyle}>
<header className='demo-header'>
Expand Down Expand Up @@ -94,16 +110,12 @@ const InternalDemoBody = ({ theme, setTheme }: InternalDemoBodyProps) => {
<DemoCustomizer theme={theme} setTheme={setTheme} state={themeState} />
)}

<div className='demo-widget-container'>
<SwapWidget
partnerCode={partnerCode || undefined}
theme={themeConfig}
onSwapSuccess={handleSwapSuccess}
onSwapError={handleSwapError}
showPoweredBy={true}
showConnectButton={true}
walletConnectProjectId={PROJECT_ID}
/>
<div
className={`demo-widget-container${
displayMode === 'modal' ? ' demo-widget-container-modal' : ''
}`}
>
{displayMode === 'modal' ? <WidgetModal>{widget}</WidgetModal> : widget}
</div>
</div>
</div>
Expand Down
Loading
Loading