feat: Add sleek mobile-first design and Astro landing site
- Update design tokens with dark gaming theme (OLED-friendly) - Pure black backgrounds (#000000) - Cyan primary (#00d9ff) and neon green accent (#00ff88) - Glassmorphism effects and mobile-specific tokens - Build complete React Native mobile app screens - HomeScreen: Chat list with dark cards and status indicators - MessagesScreen: Chat view with gradient bubbles and typing indicators - FriendsScreen: Friend list with online/offline sections and game presence - GamesScreen: GameForge projects with team channels - ProfileScreen: User profile with .aethex domain display - AppNavigator: Bottom tab navigation with glow effects - Create Astro marketing landing site - Hero section with animated gradients and phone mockup - Features showcase (6 cards) - Pricing tiers (Free/Premium/Enterprise) - Download section for all platforms - Fully responsive dark theme Design inspiration: BitChat, Root, Discord Dark, Telegram Mobile-first approach with 48px touch targets and safe areas
This commit is contained in:
parent
5abfbb60f8
commit
651cba733d
17 changed files with 2762 additions and 68 deletions
67
astro-site/README.md
Normal file
67
astro-site/README.md
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# AeThex Connect - Astro Landing Site
|
||||
|
||||
Modern, sleek landing page for AeThex Connect built with Astro and Tailwind CSS.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Start development server
|
||||
npm run dev
|
||||
|
||||
# Build for production
|
||||
npm run build
|
||||
|
||||
# Preview production build
|
||||
npm run preview
|
||||
```
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
astro-site/
|
||||
├── src/
|
||||
│ ├── pages/
|
||||
│ │ └── index.astro # Homepage
|
||||
│ ├── components/
|
||||
│ │ ├── Hero.astro # Hero section with phone mockup
|
||||
│ │ ├── Features.astro # Feature cards
|
||||
│ │ └── Pricing.astro # Pricing tiers
|
||||
│ └── layouts/
|
||||
│ └── Layout.astro # Base layout
|
||||
├── public/ # Static assets
|
||||
├── astro.config.mjs
|
||||
├── tailwind.config.mjs
|
||||
└── package.json
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- ⚡ Lightning-fast static site generation
|
||||
- 🎨 Sleek dark gaming theme
|
||||
- 📱 Mobile-first responsive design
|
||||
- ✨ Animated gradients and smooth transitions
|
||||
- 🎯 SEO optimized
|
||||
- 🚀 Ready to deploy (Vercel, Netlify, Cloudflare Pages)
|
||||
|
||||
## Deploy
|
||||
|
||||
### Vercel
|
||||
```bash
|
||||
npm i -g vercel
|
||||
vercel
|
||||
```
|
||||
|
||||
### Netlify
|
||||
```bash
|
||||
npm i -g netlify-cli
|
||||
netlify deploy
|
||||
```
|
||||
|
||||
### Cloudflare Pages
|
||||
Connect your GitHub repo to Cloudflare Pages dashboard.
|
||||
|
||||
Build command: `npm run build`
|
||||
Output directory: `dist`
|
||||
7
astro-site/astro.config.mjs
Normal file
7
astro-site/astro.config.mjs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
import tailwind from '@astrojs/tailwind';
|
||||
|
||||
export default defineConfig({
|
||||
integrations: [tailwind()],
|
||||
site: 'https://aethex-connect.com',
|
||||
});
|
||||
17
astro-site/package.json
Normal file
17
astro-site/package.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "aethex-connect-site",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/tailwind": "^5.0.0",
|
||||
"tailwindcss": "^3.4.0"
|
||||
}
|
||||
}
|
||||
136
astro-site/src/components/Features.astro
Normal file
136
astro-site/src/components/Features.astro
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
---
|
||||
// Features showcase
|
||||
const features = [
|
||||
{
|
||||
icon: '🔐',
|
||||
title: 'Own Your Identity',
|
||||
description: 'Your .aethex domain is an NFT. It\'s yours forever. No company can take it away.',
|
||||
},
|
||||
{
|
||||
icon: '💬',
|
||||
title: 'Cross-Game Chat',
|
||||
description: 'Voice and text that follows you across every game. Start in Valorant, join in Fortnite.',
|
||||
},
|
||||
{
|
||||
icon: '🎮',
|
||||
title: 'GameForge Integration',
|
||||
description: 'Building a game? Auto-created team channels with role-based access for your dev team.',
|
||||
},
|
||||
{
|
||||
icon: '📞',
|
||||
title: 'Crystal Clear Calls',
|
||||
description: 'Low-latency voice optimized for competitive gaming. HD video with screen sharing.',
|
||||
},
|
||||
{
|
||||
icon: '👥',
|
||||
title: 'Persistent Friends',
|
||||
description: 'See which games your friends are playing. Join their lobbies with one click.',
|
||||
},
|
||||
{
|
||||
icon: '💎',
|
||||
title: 'Premium Tiers',
|
||||
description: 'Free tier to get started. Premium for serious gamers. Enterprise for game studios.',
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<section id="features" class="features">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<h2>Built for <span class="gradient-text">Gamers</span></h2>
|
||||
<p>Everything you need to stay connected with your squad across all games.</p>
|
||||
</div>
|
||||
|
||||
<div class="features-grid">
|
||||
{features.map(feature => (
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">{feature.icon}</div>
|
||||
<h3>{feature.title}</h3>
|
||||
<p>{feature.description}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.features {
|
||||
padding: 6rem 2rem;
|
||||
background: #0a0a0f;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
text-align: center;
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
.section-header h2 {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.gradient-text {
|
||||
background: linear-gradient(135deg, #00d9ff 0%, #00ff88 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.section-header p {
|
||||
font-size: 1.25rem;
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
.features-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border: 1px solid rgba(0, 217, 255, 0.1);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-4px);
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-color: rgba(0, 217, 255, 0.3);
|
||||
box-shadow: 0 8px 24px rgba(0, 217, 255, 0.2);
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.feature-card h3 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.75rem;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.feature-card p {
|
||||
color: #b0b0b0;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.section-header h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
.features-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
250
astro-site/src/components/Hero.astro
Normal file
250
astro-site/src/components/Hero.astro
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
---
|
||||
// Hero component with animated gradient
|
||||
---
|
||||
|
||||
<section class="hero">
|
||||
<div class="container">
|
||||
<div class="hero-content">
|
||||
<h1 class="hero-title">
|
||||
Chat Across <span class="gradient-text">All Games</span>
|
||||
</h1>
|
||||
<p class="hero-subtitle">
|
||||
Your gaming identity and friends follow you everywhere.
|
||||
Own your <span class="highlight">.aethex</span> domain, connect with your squad across every game.
|
||||
</p>
|
||||
<div class="cta-buttons">
|
||||
<a href="#download" class="btn-primary">
|
||||
📱 Download App
|
||||
</a>
|
||||
<a href="#features" class="btn-secondary">
|
||||
Learn More →
|
||||
</a>
|
||||
</div>
|
||||
<p class="hero-caption">
|
||||
Available on iOS, Android, Windows, macOS & Linux
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="hero-visual">
|
||||
<div class="phone-mockup">
|
||||
<div class="phone-screen">
|
||||
<div class="chat-preview">
|
||||
<div class="chat-item">
|
||||
<span class="avatar">🎮</span>
|
||||
<div>
|
||||
<div class="chat-name">Squad Goals</div>
|
||||
<div class="chat-msg">Let's run Valorant</div>
|
||||
</div>
|
||||
<span class="chat-badge">3</span>
|
||||
</div>
|
||||
<div class="chat-item">
|
||||
<span class="avatar">👤</span>
|
||||
<div>
|
||||
<div class="chat-name">john.aethex</div>
|
||||
<div class="chat-msg">yo wanna play?</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.hero {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: linear-gradient(180deg, #000000 0%, #0a0a0f 100%);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: radial-gradient(circle, rgba(0,217,255,0.1) 0%, transparent 70%);
|
||||
animation: pulse 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { transform: scale(1); opacity: 0.5; }
|
||||
50% { transform: scale(1.1); opacity: 0.3; }
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 4rem;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 3.5rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.1;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero-title {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.gradient-text {
|
||||
background: linear-gradient(135deg, #00d9ff 0%, #00ff88 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: 1.25rem;
|
||||
color: #b0b0b0;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
color: #00d9ff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.btn-primary, .btn-secondary {
|
||||
padding: 1rem 2rem;
|
||||
border-radius: 12px;
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #00d9ff 0%, #00b8d9 100%);
|
||||
color: #000;
|
||||
box-shadow: 0 8px 24px rgba(0,217,255,0.3);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 12px 32px rgba(0,217,255,0.4);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: rgba(255,255,255,0.05);
|
||||
color: #fff;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.hero-caption {
|
||||
font-size: 0.875rem;
|
||||
color: #707070;
|
||||
}
|
||||
|
||||
.hero-visual {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.phone-mockup {
|
||||
width: 300px;
|
||||
height: 600px;
|
||||
background: linear-gradient(135deg, #1a1a1a 0%, #0f0f0f 100%);
|
||||
border-radius: 40px;
|
||||
padding: 12px;
|
||||
box-shadow: 0 20px 60px rgba(0,0,0,0.8);
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.phone-screen {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #000;
|
||||
border-radius: 32px;
|
||||
overflow: hidden;
|
||||
padding: 1.5rem 1rem;
|
||||
}
|
||||
|
||||
.chat-preview {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.chat-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
background: rgba(255,255,255,0.05);
|
||||
padding: 1rem;
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(255,255,255,0.05);
|
||||
}
|
||||
|
||||
.avatar {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.chat-name {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.chat-msg {
|
||||
font-size: 0.8rem;
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
.chat-badge {
|
||||
margin-left: auto;
|
||||
background: #00d9ff;
|
||||
color: #000;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 999px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.phone-mockup {
|
||||
width: 250px;
|
||||
height: 500px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
225
astro-site/src/components/Pricing.astro
Normal file
225
astro-site/src/components/Pricing.astro
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
---
|
||||
// Pricing section
|
||||
const tiers = [
|
||||
{
|
||||
name: 'Free',
|
||||
price: '$0',
|
||||
period: 'forever',
|
||||
features: [
|
||||
'5 friends maximum',
|
||||
'Basic text messaging',
|
||||
'Subdomain identity',
|
||||
'100 MB storage',
|
||||
'Community support',
|
||||
],
|
||||
cta: 'Get Started',
|
||||
highlight: false,
|
||||
},
|
||||
{
|
||||
name: 'Premium',
|
||||
price: '$100',
|
||||
period: 'per year',
|
||||
features: [
|
||||
'Blockchain .aethex domain (NFT)',
|
||||
'Unlimited friends',
|
||||
'HD voice & video (1080p)',
|
||||
'10 GB storage',
|
||||
'Priority support',
|
||||
'Custom profile branding',
|
||||
],
|
||||
cta: 'Go Premium',
|
||||
highlight: true,
|
||||
},
|
||||
{
|
||||
name: 'Enterprise',
|
||||
price: 'Custom',
|
||||
period: 'contact us',
|
||||
features: [
|
||||
'Everything in Premium',
|
||||
'White-label platform',
|
||||
'Custom domain',
|
||||
'Unlimited storage',
|
||||
'99.9% SLA guarantee',
|
||||
'Dedicated account manager',
|
||||
],
|
||||
cta: 'Contact Sales',
|
||||
highlight: false,
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<section id="pricing" class="pricing">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<h2>Choose Your <span class="gradient-text">Tier</span></h2>
|
||||
<p>Start free, upgrade when you're ready.</p>
|
||||
</div>
|
||||
|
||||
<div class="pricing-grid">
|
||||
{tiers.map(tier => (
|
||||
<div class:list={['pricing-card', { highlight: tier.highlight }]}>
|
||||
{tier.highlight && <div class="popular-badge">Most Popular</div>}
|
||||
<div class="tier-name">{tier.name}</div>
|
||||
<div class="tier-price">
|
||||
{tier.price}
|
||||
<span class="tier-period">/{tier.period}</span>
|
||||
</div>
|
||||
<ul class="tier-features">
|
||||
{tier.features.map(feature => (
|
||||
<li>✓ {feature}</li>
|
||||
))}
|
||||
</ul>
|
||||
<a href="#download" class:list={['tier-cta', { primary: tier.highlight }]}>
|
||||
{tier.cta}
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.pricing {
|
||||
padding: 6rem 2rem;
|
||||
background: linear-gradient(180deg, #0a0a0f 0%, #000000 100%);
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
text-align: center;
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
.section-header h2 {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.gradient-text {
|
||||
background: linear-gradient(135deg, #00d9ff 0%, #a855f7 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.section-header p {
|
||||
font-size: 1.25rem;
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
.pricing-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 2rem;
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.pricing-card {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
position: relative;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.pricing-card.highlight {
|
||||
border-color: #00d9ff;
|
||||
background: rgba(0, 217, 255, 0.05);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.pricing-card:hover {
|
||||
transform: translateY(-8px) scale(1.02);
|
||||
}
|
||||
|
||||
.pricing-card.highlight:hover {
|
||||
transform: translateY(-8px) scale(1.07);
|
||||
}
|
||||
|
||||
.popular-badge {
|
||||
position: absolute;
|
||||
top: -12px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: linear-gradient(135deg, #00d9ff 0%, #00b8d9 100%);
|
||||
color: #000;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 999px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.tier-name {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.tier-price {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 2rem;
|
||||
color: #00d9ff;
|
||||
}
|
||||
|
||||
.tier-period {
|
||||
font-size: 1rem;
|
||||
color: #707070;
|
||||
}
|
||||
|
||||
.tier-features {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.tier-features li {
|
||||
padding: 0.5rem 0;
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
.tier-cta {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
transition: all 0.2s;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
color: #fff;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.tier-cta:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.tier-cta.primary {
|
||||
background: linear-gradient(135deg, #00d9ff 0%, #00b8d9 100%);
|
||||
color: #000;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.tier-cta.primary:hover {
|
||||
box-shadow: 0 8px 24px rgba(0, 217, 255, 0.4);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.section-header h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
.pricing-card.highlight {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
35
astro-site/src/layouts/Layout.astro
Normal file
35
astro-site/src/layouts/Layout.astro
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
const { title = 'AeThex Connect - Gaming Communication Platform' } = Astro.props;
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{title}</title>
|
||||
<meta name="description" content="Next-generation communication platform for gamers. Own your identity with blockchain domains, connect across all games." />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
</head>
|
||||
<body class="bg-dark-bg text-white antialiased">
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style is:global>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
</style>
|
||||
275
astro-site/src/pages/index.astro
Normal file
275
astro-site/src/pages/index.astro
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import Hero from '../components/Hero.astro';
|
||||
import Features from '../components/Features.astro';
|
||||
import Pricing from '../components/Pricing.astro';
|
||||
---
|
||||
|
||||
<Layout title="AeThex Connect - Gaming Communication Platform">
|
||||
<main>
|
||||
<Hero />
|
||||
<Features />
|
||||
<Pricing />
|
||||
|
||||
<!-- Download Section -->
|
||||
<section id="download" class="download">
|
||||
<div class="container">
|
||||
<h2>Download <span class="gradient-text">AeThex Connect</span></h2>
|
||||
<p>Available on all platforms</p>
|
||||
|
||||
<div class="download-buttons">
|
||||
<a href="#" class="download-btn">
|
||||
<span class="icon">🍎</span>
|
||||
<div>
|
||||
<div class="label">Download on the</div>
|
||||
<div class="platform">App Store</div>
|
||||
</div>
|
||||
</a>
|
||||
<a href="#" class="download-btn">
|
||||
<span class="icon">🤖</span>
|
||||
<div>
|
||||
<div class="label">Get it on</div>
|
||||
<div class="platform">Google Play</div>
|
||||
</div>
|
||||
</a>
|
||||
<a href="#" class="download-btn">
|
||||
<span class="icon">💻</span>
|
||||
<div>
|
||||
<div class="label">Desktop for</div>
|
||||
<div class="platform">Windows/Mac/Linux</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<div class="footer-brand">
|
||||
<h3>AeThex Connect</h3>
|
||||
<p>Next-generation communication for gamers</p>
|
||||
</div>
|
||||
<div class="footer-links">
|
||||
<div>
|
||||
<h4>Product</h4>
|
||||
<ul>
|
||||
<li><a href="#features">Features</a></li>
|
||||
<li><a href="#pricing">Pricing</a></li>
|
||||
<li><a href="#download">Download</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Company</h4>
|
||||
<ul>
|
||||
<li><a href="/about">About</a></li>
|
||||
<li><a href="/blog">Blog</a></li>
|
||||
<li><a href="/careers">Careers</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Support</h4>
|
||||
<ul>
|
||||
<li><a href="/docs">Documentation</a></li>
|
||||
<li><a href="/help">Help Center</a></li>
|
||||
<li><a href="/contact">Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<p>© 2026 AeThex Corporation. All rights reserved.</p>
|
||||
<div class="footer-legal">
|
||||
<a href="/privacy">Privacy</a>
|
||||
<a href="/terms">Terms</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</main>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
main {
|
||||
background: #000;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.download {
|
||||
padding: 6rem 2rem;
|
||||
text-align: center;
|
||||
background: linear-gradient(180deg, #000000 0%, #0a0a0f 100%);
|
||||
}
|
||||
|
||||
.download .container {
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.download h2 {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.gradient-text {
|
||||
background: linear-gradient(135deg, #00d9ff 0%, #00ff88 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.download p {
|
||||
font-size: 1.25rem;
|
||||
color: #b0b0b0;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.download-buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 1.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.download-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
padding: 1rem 2rem;
|
||||
border-radius: 12px;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.download-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.download-btn .icon {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.download-btn .label {
|
||||
font-size: 0.75rem;
|
||||
color: #b0b0b0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.download-btn .platform {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.footer {
|
||||
background: #000;
|
||||
padding: 4rem 2rem 2rem;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.footer .container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 3fr;
|
||||
gap: 4rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.footer-content {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-brand h3 {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.footer-brand p {
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.footer-links {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-links h4 {
|
||||
font-size: 0.875rem;
|
||||
text-transform: uppercase;
|
||||
color: #707070;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.footer-links ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.footer-links li {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.footer-links a {
|
||||
color: #b0b0b0;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.footer-links a:hover {
|
||||
color: #00d9ff;
|
||||
}
|
||||
|
||||
.footer-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-top: 2rem;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
||||
color: #707070;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.footer-bottom {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-legal {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.footer-legal a {
|
||||
color: #707070;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer-legal a:hover {
|
||||
color: #00d9ff;
|
||||
}
|
||||
</style>
|
||||
22
astro-site/tailwind.config.mjs
Normal file
22
astro-site/tailwind.config.mjs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#00d9ff',
|
||||
accent: '#00ff88',
|
||||
secondary: '#a855f7',
|
||||
dark: {
|
||||
bg: '#000000',
|
||||
card: '#0f0f0f',
|
||||
elevated: '#1a1a1a',
|
||||
},
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
120
packages/mobile/src/navigation/AppNavigator.tsx
Normal file
120
packages/mobile/src/navigation/AppNavigator.tsx
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/**
|
||||
* App Navigator
|
||||
* Bottom tab navigation with sleek design
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||
import { NavigationContainer } from '@react-navigation/native';
|
||||
import { StyleSheet, View, Text } from 'react-native';
|
||||
import { theme } from '../theme';
|
||||
|
||||
// Screens
|
||||
import HomeScreen from '../screens/HomeScreen';
|
||||
import MessagesScreen from '../screens/MessagesScreen';
|
||||
import GamesScreen from '../screens/GamesScreen';
|
||||
import FriendsScreen from '../screens/FriendsScreen';
|
||||
import ProfileScreen from '../screens/ProfileScreen';
|
||||
|
||||
const Tab = createBottomTabNavigator();
|
||||
|
||||
const TabIcon = ({ focused, emoji }: { focused: boolean; emoji: string }) => (
|
||||
<View style={[styles.tabIcon, focused && styles.tabIconActive]}>
|
||||
<Text style={styles.tabEmoji}>{emoji}</Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
export default function AppNavigator() {
|
||||
return (
|
||||
<NavigationContainer
|
||||
theme={{
|
||||
dark: true,
|
||||
colors: {
|
||||
primary: theme.colors.primary,
|
||||
background: theme.colors.background,
|
||||
card: theme.colors.background,
|
||||
text: theme.colors.text,
|
||||
border: theme.colors.gray800,
|
||||
notification: theme.colors.primary,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Tab.Navigator
|
||||
screenOptions={{
|
||||
headerShown: false,
|
||||
tabBarStyle: styles.tabBar,
|
||||
tabBarActiveTintColor: theme.colors.primary,
|
||||
tabBarInactiveTintColor: theme.colors.gray600,
|
||||
tabBarLabelStyle: styles.tabLabel,
|
||||
}}
|
||||
>
|
||||
<Tab.Screen
|
||||
name="Home"
|
||||
component={HomeScreen}
|
||||
options={{
|
||||
tabBarIcon: ({ focused }) => <TabIcon focused={focused} emoji="🏠" />,
|
||||
}}
|
||||
/>
|
||||
<Tab.Screen
|
||||
name="Messages"
|
||||
component={MessagesScreen}
|
||||
options={{
|
||||
tabBarIcon: ({ focused }) => <TabIcon focused={focused} emoji="💬" />,
|
||||
tabBarBadge: 3, // Unread count
|
||||
}}
|
||||
/>
|
||||
<Tab.Screen
|
||||
name="Games"
|
||||
component={GamesScreen}
|
||||
options={{
|
||||
tabBarIcon: ({ focused }) => <TabIcon focused={focused} emoji="🎮" />,
|
||||
}}
|
||||
/>
|
||||
<Tab.Screen
|
||||
name="Friends"
|
||||
component={FriendsScreen}
|
||||
options={{
|
||||
tabBarIcon: ({ focused }) => <TabIcon focused={focused} emoji="👥" />,
|
||||
}}
|
||||
/>
|
||||
<Tab.Screen
|
||||
name="Profile"
|
||||
component={ProfileScreen}
|
||||
options={{
|
||||
tabBarIcon: ({ focused }) => <TabIcon focused={focused} emoji="👤" />,
|
||||
}}
|
||||
/>
|
||||
</Tab.Navigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
tabBar: {
|
||||
backgroundColor: theme.colors.background,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: theme.colors.gray900,
|
||||
height: theme.layout.tabBarHeight,
|
||||
paddingBottom: 8,
|
||||
paddingTop: 8,
|
||||
},
|
||||
tabLabel: {
|
||||
fontSize: theme.typography.fontSize.xs,
|
||||
fontWeight: theme.typography.fontWeight.medium,
|
||||
},
|
||||
tabIcon: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: theme.borderRadius.md,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
tabIconActive: {
|
||||
backgroundColor: theme.colors.backgroundTertiary,
|
||||
...theme.shadows.glow,
|
||||
},
|
||||
tabEmoji: {
|
||||
fontSize: 24,
|
||||
},
|
||||
});
|
||||
222
packages/mobile/src/screens/FriendsScreen.tsx
Normal file
222
packages/mobile/src/screens/FriendsScreen.tsx
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
/**
|
||||
* Friends Screen
|
||||
* Cross-game friends list with status
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
FlatList,
|
||||
TouchableOpacity,
|
||||
SafeAreaView,
|
||||
SectionList,
|
||||
} from 'react-native';
|
||||
import { theme } from '../theme';
|
||||
|
||||
interface Friend {
|
||||
id: string;
|
||||
username: string;
|
||||
status: 'online' | 'offline' | 'idle' | 'dnd';
|
||||
game?: string;
|
||||
avatar: string;
|
||||
}
|
||||
|
||||
export default function FriendsScreen({ navigation }: any) {
|
||||
const [friends] = useState<Friend[]>([
|
||||
{ id: '1', username: 'john.aethex', status: 'online', game: 'Valorant', avatar: 'J' },
|
||||
{ id: '2', username: 'sarah.aethex', status: 'online', game: 'Fortnite', avatar: 'S' },
|
||||
{ id: '3', username: 'mike.aethex', status: 'idle', avatar: 'M' },
|
||||
{ id: '4', username: 'alex.aethex', status: 'offline', avatar: 'A' },
|
||||
]);
|
||||
|
||||
const onlineFriends = friends.filter(f => f.status === 'online');
|
||||
const offlineFriends = friends.filter(f => f.status !== 'online');
|
||||
|
||||
const sections = [
|
||||
{ title: `ONLINE (${onlineFriends.length})`, data: onlineFriends },
|
||||
{ title: `OFFLINE (${offlineFriends.length})`, data: offlineFriends },
|
||||
];
|
||||
|
||||
const getStatusColor = (status: Friend['status']) => {
|
||||
switch (status) {
|
||||
case 'online': return theme.colors.online;
|
||||
case 'idle': return theme.colors.idle;
|
||||
case 'dnd': return theme.colors.dnd;
|
||||
default: return theme.colors.offline;
|
||||
}
|
||||
};
|
||||
|
||||
const renderFriend = ({ item }: { item: Friend }) => (
|
||||
<TouchableOpacity style={styles.friendCard} activeOpacity={0.7}>
|
||||
<View style={styles.avatarContainer}>
|
||||
<View style={styles.avatar}>
|
||||
<Text style={styles.avatarText}>{item.avatar}</Text>
|
||||
</View>
|
||||
<View style={[styles.statusDot, { backgroundColor: getStatusColor(item.status) }]} />
|
||||
</View>
|
||||
<View style={styles.friendInfo}>
|
||||
<Text style={styles.username}>{item.username}</Text>
|
||||
{item.game && (
|
||||
<View style={styles.gameRow}>
|
||||
<Text style={styles.gameIcon}>🎮</Text>
|
||||
<Text style={styles.gameText}>Playing {item.game}</Text>
|
||||
</View>
|
||||
)}
|
||||
{!item.game && item.status === 'offline' && (
|
||||
<Text style={styles.lastSeen}>Last seen 2h ago</Text>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.actions}>
|
||||
<TouchableOpacity style={styles.actionButton}>
|
||||
<Text style={styles.actionIcon}>💬</Text>
|
||||
</TouchableOpacity>
|
||||
{item.status === 'online' && (
|
||||
<TouchableOpacity style={styles.actionButton}>
|
||||
<Text style={styles.actionIcon}>📞</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.headerTitle}>Friends</Text>
|
||||
<TouchableOpacity style={styles.addButton}>
|
||||
<Text style={styles.addIcon}>➕</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<SectionList
|
||||
sections={sections}
|
||||
renderItem={renderFriend}
|
||||
renderSectionHeader={({ section }) => (
|
||||
<View style={styles.sectionHeader}>
|
||||
<Text style={styles.sectionTitle}>{section.title}</Text>
|
||||
</View>
|
||||
)}
|
||||
keyExtractor={(item) => item.id}
|
||||
contentContainerStyle={styles.listContent}
|
||||
stickySectionHeadersEnabled={false}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.colors.background,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: theme.spacing.md,
|
||||
paddingVertical: theme.spacing.md,
|
||||
},
|
||||
headerTitle: {
|
||||
fontSize: theme.typography.fontSize.xxl,
|
||||
fontWeight: theme.typography.fontWeight.bold,
|
||||
color: theme.colors.text,
|
||||
},
|
||||
addButton: {
|
||||
width: theme.layout.touchTarget,
|
||||
height: theme.layout.touchTarget,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
addIcon: {
|
||||
fontSize: 24,
|
||||
},
|
||||
listContent: {
|
||||
paddingHorizontal: theme.spacing.md,
|
||||
},
|
||||
sectionHeader: {
|
||||
paddingVertical: theme.spacing.md,
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
fontWeight: theme.typography.fontWeight.semibold,
|
||||
color: theme.colors.textTertiary,
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
friendCard: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.colors.card,
|
||||
borderRadius: theme.borderRadius.lg,
|
||||
padding: theme.spacing.md,
|
||||
marginBottom: theme.spacing.md,
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(255, 255, 255, 0.05)',
|
||||
},
|
||||
avatarContainer: {
|
||||
position: 'relative',
|
||||
marginRight: theme.spacing.md,
|
||||
},
|
||||
avatar: {
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: theme.borderRadius.full,
|
||||
backgroundColor: theme.colors.primary,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
avatarText: {
|
||||
fontSize: 20,
|
||||
fontWeight: theme.typography.fontWeight.bold,
|
||||
color: '#000',
|
||||
},
|
||||
statusDot: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
width: 14,
|
||||
height: 14,
|
||||
borderRadius: 7,
|
||||
borderWidth: 2,
|
||||
borderColor: theme.colors.card,
|
||||
},
|
||||
friendInfo: {
|
||||
flex: 1,
|
||||
},
|
||||
username: {
|
||||
fontSize: theme.typography.fontSize.base,
|
||||
fontWeight: theme.typography.fontWeight.semibold,
|
||||
color: theme.colors.text,
|
||||
marginBottom: 4,
|
||||
},
|
||||
gameRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
gameIcon: {
|
||||
fontSize: 14,
|
||||
marginRight: 4,
|
||||
},
|
||||
gameText: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
color: theme.colors.textSecondary,
|
||||
},
|
||||
lastSeen: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
color: theme.colors.textTertiary,
|
||||
},
|
||||
actions: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
actionButton: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginLeft: theme.spacing.sm,
|
||||
},
|
||||
actionIcon: {
|
||||
fontSize: 20,
|
||||
},
|
||||
});
|
||||
221
packages/mobile/src/screens/GamesScreen.tsx
Normal file
221
packages/mobile/src/screens/GamesScreen.tsx
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
/**
|
||||
* Games Screen (GameForge)
|
||||
* Game development projects and team channels
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
ScrollView,
|
||||
TouchableOpacity,
|
||||
SafeAreaView,
|
||||
} from 'react-native';
|
||||
import { theme } from '../theme';
|
||||
|
||||
export default function GamesScreen() {
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.headerTitle}>GameForge Projects</Text>
|
||||
<TouchableOpacity style={styles.addButton}>
|
||||
<Text style={styles.addIcon}>➕</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<ScrollView contentContainerStyle={styles.content}>
|
||||
{/* Project Card */}
|
||||
<View style={styles.projectCard}>
|
||||
<View style={styles.projectHeader}>
|
||||
<Text style={styles.projectIcon}>🎮</Text>
|
||||
<View style={styles.projectInfo}>
|
||||
<Text style={styles.projectName}>Project Phoenix</Text>
|
||||
<Text style={styles.projectMeta}>5 members • 3 online</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.channels}>
|
||||
{['#general', '#dev', '#art', '#test'].map(channel => (
|
||||
<TouchableOpacity key={channel} style={styles.channelButton}>
|
||||
<Text style={styles.channelText}>{channel}</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
|
||||
<View style={styles.notification}>
|
||||
<Text style={styles.notificationDot}>🔴</Text>
|
||||
<Text style={styles.notificationText}>Build failed 2m ago</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Another Project */}
|
||||
<View style={styles.projectCard}>
|
||||
<View style={styles.projectHeader}>
|
||||
<Text style={styles.projectIcon}>🎮</Text>
|
||||
<View style={styles.projectInfo}>
|
||||
<Text style={styles.projectName}>Indie Shooter</Text>
|
||||
<Text style={styles.projectMeta}>2 members • 1 online</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.channels}>
|
||||
{['#general', '#dev'].map(channel => (
|
||||
<TouchableOpacity key={channel} style={styles.channelButton}>
|
||||
<Text style={styles.channelText}>{channel}</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Team Status */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>TEAM STATUS</Text>
|
||||
<View style={styles.teamList}>
|
||||
{[
|
||||
{ name: 'sarah.aethex', role: 'Developer', online: true },
|
||||
{ name: 'mike.aethex', role: 'Artist', online: true },
|
||||
{ name: 'alex.aethex', role: 'Designer', online: false },
|
||||
].map(member => (
|
||||
<View key={member.name} style={styles.teamMember}>
|
||||
<View style={[styles.memberDot, { backgroundColor: member.online ? theme.colors.online : theme.colors.offline }]} />
|
||||
<Text style={styles.memberName}>{member.name}</Text>
|
||||
<Text style={styles.memberRole}>({member.role})</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.colors.background,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: theme.spacing.md,
|
||||
paddingVertical: theme.spacing.md,
|
||||
},
|
||||
headerTitle: {
|
||||
fontSize: theme.typography.fontSize.xxl,
|
||||
fontWeight: theme.typography.fontWeight.bold,
|
||||
color: theme.colors.text,
|
||||
},
|
||||
addButton: {
|
||||
width: theme.layout.touchTarget,
|
||||
height: theme.layout.touchTarget,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
addIcon: {
|
||||
fontSize: 24,
|
||||
},
|
||||
content: {
|
||||
padding: theme.spacing.md,
|
||||
},
|
||||
projectCard: {
|
||||
backgroundColor: theme.colors.card,
|
||||
borderRadius: theme.borderRadius.lg,
|
||||
padding: theme.spacing.lg,
|
||||
marginBottom: theme.spacing.md,
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(255, 255, 255, 0.05)',
|
||||
},
|
||||
projectHeader: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: theme.spacing.md,
|
||||
},
|
||||
projectIcon: {
|
||||
fontSize: 32,
|
||||
marginRight: theme.spacing.md,
|
||||
},
|
||||
projectInfo: {
|
||||
flex: 1,
|
||||
},
|
||||
projectName: {
|
||||
fontSize: theme.typography.fontSize.lg,
|
||||
fontWeight: theme.typography.fontWeight.semibold,
|
||||
color: theme.colors.text,
|
||||
marginBottom: 4,
|
||||
},
|
||||
projectMeta: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
color: theme.colors.textSecondary,
|
||||
},
|
||||
channels: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
marginBottom: theme.spacing.md,
|
||||
},
|
||||
channelButton: {
|
||||
backgroundColor: theme.colors.backgroundSecondary,
|
||||
paddingHorizontal: theme.spacing.md,
|
||||
paddingVertical: theme.spacing.sm,
|
||||
borderRadius: theme.borderRadius.base,
|
||||
marginRight: theme.spacing.sm,
|
||||
marginBottom: theme.spacing.sm,
|
||||
},
|
||||
channelText: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
color: theme.colors.textSecondary,
|
||||
},
|
||||
notification: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'rgba(239, 68, 68, 0.1)',
|
||||
padding: theme.spacing.sm,
|
||||
borderRadius: theme.borderRadius.base,
|
||||
},
|
||||
notificationDot: {
|
||||
fontSize: 12,
|
||||
marginRight: theme.spacing.sm,
|
||||
},
|
||||
notificationText: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
color: theme.colors.error,
|
||||
},
|
||||
section: {
|
||||
marginTop: theme.spacing.lg,
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
fontWeight: theme.typography.fontWeight.semibold,
|
||||
color: theme.colors.textTertiary,
|
||||
marginBottom: theme.spacing.md,
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
teamList: {
|
||||
backgroundColor: theme.colors.card,
|
||||
borderRadius: theme.borderRadius.lg,
|
||||
padding: theme.spacing.md,
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(255, 255, 255, 0.05)',
|
||||
},
|
||||
teamMember: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingVertical: theme.spacing.sm,
|
||||
},
|
||||
memberDot: {
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: 4,
|
||||
marginRight: theme.spacing.sm,
|
||||
},
|
||||
memberName: {
|
||||
fontSize: theme.typography.fontSize.base,
|
||||
color: theme.colors.text,
|
||||
marginRight: theme.spacing.sm,
|
||||
},
|
||||
memberRole: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
color: theme.colors.textSecondary,
|
||||
},
|
||||
});
|
||||
267
packages/mobile/src/screens/HomeScreen.tsx
Normal file
267
packages/mobile/src/screens/HomeScreen.tsx
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
/**
|
||||
* Home Screen (Chat List)
|
||||
* Main conversation list with sleek dark design
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
FlatList,
|
||||
TouchableOpacity,
|
||||
TextInput,
|
||||
SafeAreaView,
|
||||
StatusBar,
|
||||
} from 'react-native';
|
||||
import { theme } from '../theme';
|
||||
|
||||
interface Conversation {
|
||||
id: string;
|
||||
name: string;
|
||||
lastMessage: string;
|
||||
timestamp: string;
|
||||
unread: number;
|
||||
isOnline: boolean;
|
||||
isGroup: boolean;
|
||||
avatar: string;
|
||||
}
|
||||
|
||||
export default function HomeScreen({ navigation }: any) {
|
||||
const [conversations, setConversations] = useState<Conversation[]>([
|
||||
{
|
||||
id: '1',
|
||||
name: 'john.aethex',
|
||||
lastMessage: 'yo wanna play valorant',
|
||||
timestamp: '2:30 PM',
|
||||
unread: 0,
|
||||
isOnline: true,
|
||||
isGroup: false,
|
||||
avatar: '👤',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Squad Goals',
|
||||
lastMessage: "Sarah: let's go",
|
||||
timestamp: '1:15 PM',
|
||||
unread: 3,
|
||||
isOnline: true,
|
||||
isGroup: true,
|
||||
avatar: '🎮',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: 'mike.aethex',
|
||||
lastMessage: 'gg bro',
|
||||
timestamp: 'Yesterday',
|
||||
unread: 0,
|
||||
isOnline: false,
|
||||
isGroup: false,
|
||||
avatar: '👤',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
name: 'Project Phoenix',
|
||||
lastMessage: 'Dev team meeting 3pm',
|
||||
timestamp: 'Yesterday',
|
||||
unread: 0,
|
||||
isOnline: true,
|
||||
isGroup: true,
|
||||
avatar: '🎮',
|
||||
},
|
||||
]);
|
||||
|
||||
const renderConversation = ({ item }: { item: Conversation }) => (
|
||||
<TouchableOpacity
|
||||
style={styles.conversationCard}
|
||||
onPress={() => navigation.navigate('Chat', { conversation: item })}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<View style={styles.conversationContent}>
|
||||
{/* Avatar with status */}
|
||||
<View style={styles.avatarContainer}>
|
||||
<View style={styles.avatar}>
|
||||
<Text style={styles.avatarEmoji}>{item.avatar}</Text>
|
||||
</View>
|
||||
{item.isOnline && <View style={styles.statusDot} />}
|
||||
</View>
|
||||
|
||||
{/* Message preview */}
|
||||
<View style={styles.messagePreview}>
|
||||
<View style={styles.headerRow}>
|
||||
<Text style={styles.conversationName} numberOfLines={1}>
|
||||
{item.name}
|
||||
</Text>
|
||||
<Text style={styles.timestamp}>{item.timestamp}</Text>
|
||||
</View>
|
||||
<View style={styles.lastMessageRow}>
|
||||
<Text style={styles.lastMessage} numberOfLines={1}>
|
||||
{item.lastMessage}
|
||||
</Text>
|
||||
{item.unread > 0 && (
|
||||
<View style={styles.unreadBadge}>
|
||||
<Text style={styles.unreadText}>{item.unread}</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<StatusBar barStyle="light-content" backgroundColor={theme.colors.background} />
|
||||
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<TouchableOpacity style={styles.menuButton}>
|
||||
<Text style={styles.menuIcon}>☰</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={styles.headerTitle}>AeThex Connect</Text>
|
||||
<TouchableOpacity style={styles.searchButton}>
|
||||
<Text style={styles.searchIcon}>🔍</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Conversation List */}
|
||||
<FlatList
|
||||
data={conversations}
|
||||
renderItem={renderConversation}
|
||||
keyExtractor={(item) => item.id}
|
||||
contentContainerStyle={styles.listContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.colors.background,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: theme.spacing.md,
|
||||
paddingVertical: theme.spacing.md,
|
||||
backgroundColor: theme.colors.background,
|
||||
},
|
||||
headerTitle: {
|
||||
fontSize: theme.typography.fontSize.xl,
|
||||
fontWeight: theme.typography.fontWeight.semibold,
|
||||
color: theme.colors.text,
|
||||
flex: 1,
|
||||
marginLeft: theme.spacing.md,
|
||||
},
|
||||
menuButton: {
|
||||
width: theme.layout.touchTarget,
|
||||
height: theme.layout.touchTarget,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
menuIcon: {
|
||||
fontSize: 24,
|
||||
color: theme.colors.text,
|
||||
},
|
||||
searchButton: {
|
||||
width: theme.layout.touchTarget,
|
||||
height: theme.layout.touchTarget,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
searchIcon: {
|
||||
fontSize: 20,
|
||||
},
|
||||
listContent: {
|
||||
paddingHorizontal: theme.spacing.md,
|
||||
paddingBottom: theme.spacing.xl,
|
||||
},
|
||||
conversationCard: {
|
||||
backgroundColor: theme.colors.card,
|
||||
borderRadius: theme.borderRadius.lg,
|
||||
marginBottom: theme.spacing.md,
|
||||
padding: theme.spacing.md,
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(255, 255, 255, 0.05)',
|
||||
},
|
||||
conversationContent: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
avatarContainer: {
|
||||
position: 'relative',
|
||||
marginRight: theme.spacing.md,
|
||||
},
|
||||
avatar: {
|
||||
width: 56,
|
||||
height: 56,
|
||||
borderRadius: theme.borderRadius.full,
|
||||
backgroundColor: theme.colors.backgroundSecondary,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
borderWidth: 2,
|
||||
borderColor: theme.colors.gray800,
|
||||
},
|
||||
avatarEmoji: {
|
||||
fontSize: 28,
|
||||
},
|
||||
statusDot: {
|
||||
position: 'absolute',
|
||||
bottom: 2,
|
||||
right: 2,
|
||||
width: 14,
|
||||
height: 14,
|
||||
borderRadius: 7,
|
||||
backgroundColor: theme.colors.online,
|
||||
borderWidth: 2,
|
||||
borderColor: theme.colors.card,
|
||||
},
|
||||
messagePreview: {
|
||||
flex: 1,
|
||||
},
|
||||
headerRow: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 4,
|
||||
},
|
||||
conversationName: {
|
||||
fontSize: theme.typography.fontSize.base,
|
||||
fontWeight: theme.typography.fontWeight.semibold,
|
||||
color: theme.colors.text,
|
||||
flex: 1,
|
||||
},
|
||||
timestamp: {
|
||||
fontSize: theme.typography.fontSize.xs,
|
||||
color: theme.colors.textTertiary,
|
||||
marginLeft: theme.spacing.sm,
|
||||
},
|
||||
lastMessageRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
lastMessage: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
color: theme.colors.textSecondary,
|
||||
flex: 1,
|
||||
},
|
||||
unreadBadge: {
|
||||
backgroundColor: theme.colors.primary,
|
||||
borderRadius: theme.borderRadius.full,
|
||||
paddingHorizontal: 8,
|
||||
paddingVertical: 2,
|
||||
marginLeft: theme.spacing.sm,
|
||||
minWidth: 24,
|
||||
alignItems: 'center',
|
||||
...theme.shadows.glow,
|
||||
},
|
||||
unreadText: {
|
||||
fontSize: theme.typography.fontSize.xs,
|
||||
fontWeight: theme.typography.fontWeight.bold,
|
||||
color: '#000',
|
||||
},
|
||||
});
|
||||
347
packages/mobile/src/screens/MessagesScreen.tsx
Normal file
347
packages/mobile/src/screens/MessagesScreen.tsx
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
/**
|
||||
* Messages Screen (Chat View)
|
||||
* Individual chat conversation with message bubbles
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
FlatList,
|
||||
TextInput,
|
||||
TouchableOpacity,
|
||||
SafeAreaView,
|
||||
KeyboardAvoidingView,
|
||||
Platform,
|
||||
} from 'react-native';
|
||||
import { theme } from '../theme';
|
||||
|
||||
interface Message {
|
||||
id: string;
|
||||
text: string;
|
||||
timestamp: string;
|
||||
isOwn: boolean;
|
||||
status?: 'sent' | 'delivered' | 'read';
|
||||
}
|
||||
|
||||
export default function MessagesScreen({ route, navigation }: any) {
|
||||
const { conversation } = route?.params || { conversation: { name: 'john.aethex' } };
|
||||
|
||||
const [messages, setMessages] = useState<Message[]>([
|
||||
{
|
||||
id: '1',
|
||||
text: "hey what's up? 🎮",
|
||||
timestamp: '2:28 PM',
|
||||
isOwn: true,
|
||||
status: 'read',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
text: 'yo wanna run some valorant?',
|
||||
timestamp: '2:30 PM',
|
||||
isOwn: false,
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
text: 'bet, im in 🔥',
|
||||
timestamp: '2:31 PM',
|
||||
isOwn: true,
|
||||
status: 'delivered',
|
||||
},
|
||||
]);
|
||||
|
||||
const [inputText, setInputText] = useState('');
|
||||
const [isTyping] = useState(true);
|
||||
|
||||
const renderMessage = ({ item }: { item: Message }) => (
|
||||
<View style={[styles.messageContainer, item.isOwn && styles.messageContainerOwn]}>
|
||||
<View style={[styles.messageBubble, item.isOwn && styles.messageBubbleOwn]}>
|
||||
<Text style={[styles.messageText, item.isOwn && styles.messageTextOwn]}>
|
||||
{item.text}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={[styles.messageFooter, item.isOwn && styles.messageFooterOwn]}>
|
||||
<Text style={styles.messageTimestamp}>{item.timestamp}</Text>
|
||||
{item.isOwn && (
|
||||
<Text style={styles.messageStatus}>
|
||||
{item.status === 'read' && '✓✓'}
|
||||
{item.status === 'delivered' && '✓'}
|
||||
{item.status === 'sent' && '•'}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
const handleSend = () => {
|
||||
if (inputText.trim()) {
|
||||
const newMessage: Message = {
|
||||
id: Date.now().toString(),
|
||||
text: inputText.trim(),
|
||||
timestamp: new Date().toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' }),
|
||||
isOwn: true,
|
||||
status: 'sent',
|
||||
};
|
||||
setMessages([...messages, newMessage]);
|
||||
setInputText('');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<KeyboardAvoidingView
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||
style={styles.keyboardView}
|
||||
keyboardVerticalOffset={0}
|
||||
>
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<TouchableOpacity onPress={() => navigation.goBack()} style={styles.backButton}>
|
||||
<Text style={styles.backIcon}>←</Text>
|
||||
</TouchableOpacity>
|
||||
<View style={styles.headerInfo}>
|
||||
<Text style={styles.headerTitle}>{conversation.name}</Text>
|
||||
<View style={styles.statusRow}>
|
||||
<View style={styles.onlineDot} />
|
||||
<Text style={styles.statusText}>Online • Playing Valorant</Text>
|
||||
</View>
|
||||
</View>
|
||||
<TouchableOpacity style={styles.iconButton}>
|
||||
<Text style={styles.callIcon}>📞</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.iconButton}>
|
||||
<Text style={styles.videoIcon}>📹</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Messages List */}
|
||||
<FlatList
|
||||
data={messages}
|
||||
renderItem={renderMessage}
|
||||
keyExtractor={(item) => item.id}
|
||||
contentContainerStyle={styles.messagesList}
|
||||
showsVerticalScrollIndicator={false}
|
||||
inverted={false}
|
||||
/>
|
||||
|
||||
{/* Typing Indicator */}
|
||||
{isTyping && (
|
||||
<View style={styles.typingContainer}>
|
||||
<Text style={styles.typingText}>{conversation.name} is typing...</Text>
|
||||
<View style={styles.typingDots}>
|
||||
<View style={[styles.dot, styles.dot1]} />
|
||||
<View style={[styles.dot, styles.dot2]} />
|
||||
<View style={[styles.dot, styles.dot3]} />
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Input Bar */}
|
||||
<View style={styles.inputContainer}>
|
||||
<TouchableOpacity style={styles.attachButton}>
|
||||
<Text style={styles.attachIcon}>+</Text>
|
||||
</TouchableOpacity>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Message..."
|
||||
placeholderTextColor={theme.colors.textMuted}
|
||||
value={inputText}
|
||||
onChangeText={setInputText}
|
||||
multiline
|
||||
maxLength={2000}
|
||||
/>
|
||||
<TouchableOpacity style={styles.sendButton} onPress={handleSend}>
|
||||
<Text style={styles.sendIcon}>🎤</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.colors.background,
|
||||
},
|
||||
keyboardView: {
|
||||
flex: 1,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: theme.spacing.md,
|
||||
paddingVertical: theme.spacing.sm,
|
||||
backgroundColor: theme.colors.backgroundSecondary,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: theme.colors.gray900,
|
||||
},
|
||||
backButton: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginRight: theme.spacing.sm,
|
||||
},
|
||||
backIcon: {
|
||||
fontSize: 24,
|
||||
color: theme.colors.primary,
|
||||
},
|
||||
headerInfo: {
|
||||
flex: 1,
|
||||
},
|
||||
headerTitle: {
|
||||
fontSize: theme.typography.fontSize.base,
|
||||
fontWeight: theme.typography.fontWeight.semibold,
|
||||
color: theme.colors.text,
|
||||
},
|
||||
statusRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginTop: 2,
|
||||
},
|
||||
onlineDot: {
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: 4,
|
||||
backgroundColor: theme.colors.online,
|
||||
marginRight: 6,
|
||||
},
|
||||
statusText: {
|
||||
fontSize: theme.typography.fontSize.xs,
|
||||
color: theme.colors.textSecondary,
|
||||
},
|
||||
iconButton: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginLeft: theme.spacing.sm,
|
||||
},
|
||||
callIcon: {
|
||||
fontSize: 20,
|
||||
},
|
||||
videoIcon: {
|
||||
fontSize: 20,
|
||||
},
|
||||
messagesList: {
|
||||
paddingHorizontal: theme.spacing.md,
|
||||
paddingVertical: theme.spacing.lg,
|
||||
},
|
||||
messageContainer: {
|
||||
marginBottom: theme.spacing.md,
|
||||
alignItems: 'flex-start',
|
||||
maxWidth: '80%',
|
||||
},
|
||||
messageContainerOwn: {
|
||||
alignSelf: 'flex-end',
|
||||
alignItems: 'flex-end',
|
||||
},
|
||||
messageBubble: {
|
||||
backgroundColor: theme.colors.card,
|
||||
borderRadius: theme.borderRadius.xl,
|
||||
padding: theme.spacing.md,
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(255, 255, 255, 0.05)',
|
||||
},
|
||||
messageBubbleOwn: {
|
||||
backgroundColor: 'transparent',
|
||||
borderWidth: 0,
|
||||
backgroundImage: `linear-gradient(135deg, ${theme.colors.primary}, ${theme.colors.secondary})`,
|
||||
},
|
||||
messageText: {
|
||||
fontSize: theme.typography.fontSize.base,
|
||||
color: theme.colors.text,
|
||||
lineHeight: 22,
|
||||
},
|
||||
messageTextOwn: {
|
||||
color: '#ffffff',
|
||||
},
|
||||
messageFooter: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginTop: 4,
|
||||
paddingHorizontal: theme.spacing.sm,
|
||||
},
|
||||
messageFooterOwn: {
|
||||
flexDirection: 'row-reverse',
|
||||
},
|
||||
messageTimestamp: {
|
||||
fontSize: theme.typography.fontSize.xs,
|
||||
color: theme.colors.textTertiary,
|
||||
},
|
||||
messageStatus: {
|
||||
fontSize: theme.typography.fontSize.xs,
|
||||
color: theme.colors.primary,
|
||||
marginLeft: 4,
|
||||
},
|
||||
typingContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: theme.spacing.lg,
|
||||
paddingVertical: theme.spacing.sm,
|
||||
},
|
||||
typingText: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
color: theme.colors.textSecondary,
|
||||
marginRight: theme.spacing.sm,
|
||||
},
|
||||
typingDots: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
dot: {
|
||||
width: 6,
|
||||
height: 6,
|
||||
borderRadius: 3,
|
||||
backgroundColor: theme.colors.textSecondary,
|
||||
marginHorizontal: 2,
|
||||
},
|
||||
dot1: {},
|
||||
dot2: {},
|
||||
dot3: {},
|
||||
inputContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: theme.spacing.md,
|
||||
paddingVertical: theme.spacing.md,
|
||||
backgroundColor: theme.colors.backgroundSecondary,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: theme.colors.gray900,
|
||||
},
|
||||
attachButton: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: theme.borderRadius.full,
|
||||
backgroundColor: theme.colors.card,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginRight: theme.spacing.sm,
|
||||
},
|
||||
attachIcon: {
|
||||
fontSize: 24,
|
||||
color: theme.colors.primary,
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.colors.card,
|
||||
borderRadius: theme.borderRadius.lg,
|
||||
paddingHorizontal: theme.spacing.md,
|
||||
paddingVertical: theme.spacing.sm,
|
||||
fontSize: theme.typography.fontSize.base,
|
||||
color: theme.colors.text,
|
||||
maxHeight: 100,
|
||||
},
|
||||
sendButton: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: theme.borderRadius.full,
|
||||
backgroundColor: theme.colors.card,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginLeft: theme.spacing.sm,
|
||||
},
|
||||
sendIcon: {
|
||||
fontSize: 20,
|
||||
},
|
||||
});
|
||||
226
packages/mobile/src/screens/ProfileScreen.tsx
Normal file
226
packages/mobile/src/screens/ProfileScreen.tsx
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
/**
|
||||
* Profile Screen
|
||||
* User profile with .aethex domain and settings
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
ScrollView,
|
||||
TouchableOpacity,
|
||||
SafeAreaView,
|
||||
} from 'react-native';
|
||||
import { theme } from '../theme';
|
||||
|
||||
export default function ProfileScreen() {
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.headerTitle}>Settings</Text>
|
||||
</View>
|
||||
|
||||
<ScrollView contentContainerStyle={styles.content}>
|
||||
{/* Profile Section */}
|
||||
<View style={styles.profileSection}>
|
||||
<View style={styles.avatarLarge}>
|
||||
<Text style={styles.avatarText}>A</Text>
|
||||
</View>
|
||||
<Text style={styles.username}>alice.aethex ✓</Text>
|
||||
<Text style={styles.membershipBadge}>Premium Member</Text>
|
||||
</View>
|
||||
|
||||
{/* Domain Card */}
|
||||
<View style={styles.domainCard}>
|
||||
<Text style={styles.domainIcon}>🌐</Text>
|
||||
<View style={styles.domainInfo}>
|
||||
<Text style={styles.domainName}>alice.aethex</Text>
|
||||
<Text style={styles.domainDetail}>NFT Token: 0x742f...</Text>
|
||||
<Text style={styles.domainDetail}>Owned since: Jan 2026</Text>
|
||||
</View>
|
||||
<TouchableOpacity style={styles.domainButton}>
|
||||
<Text style={styles.domainButtonText}>View on Polygon →</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Settings Sections */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>ACCOUNT</Text>
|
||||
|
||||
<TouchableOpacity style={styles.settingItem}>
|
||||
<Text style={styles.settingIcon}>⭐</Text>
|
||||
<Text style={styles.settingLabel}>Premium</Text>
|
||||
<Text style={styles.settingArrow}>→</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={styles.settingItem}>
|
||||
<Text style={styles.settingIcon}>🔔</Text>
|
||||
<Text style={styles.settingLabel}>Notifications</Text>
|
||||
<Text style={styles.settingArrow}>→</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={styles.settingItem}>
|
||||
<Text style={styles.settingIcon}>🔒</Text>
|
||||
<Text style={styles.settingLabel}>Privacy</Text>
|
||||
<Text style={styles.settingArrow}>→</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={styles.settingItem}>
|
||||
<Text style={styles.settingIcon}>🎮</Text>
|
||||
<Text style={styles.settingLabel}>Connected Games</Text>
|
||||
<Text style={styles.settingArrow}>→</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* About Section */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>ABOUT</Text>
|
||||
|
||||
<TouchableOpacity style={styles.settingItem}>
|
||||
<Text style={styles.settingIcon}>❓</Text>
|
||||
<Text style={styles.settingLabel}>Help & Support</Text>
|
||||
<Text style={styles.settingArrow}>→</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={styles.settingItem}>
|
||||
<Text style={styles.settingIcon}>📄</Text>
|
||||
<Text style={styles.settingLabel}>Terms & Privacy</Text>
|
||||
<Text style={styles.settingArrow}>→</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Version */}
|
||||
<Text style={styles.version}>Version 1.0.0</Text>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.colors.background,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: theme.spacing.md,
|
||||
paddingVertical: theme.spacing.md,
|
||||
},
|
||||
headerTitle: {
|
||||
fontSize: theme.typography.fontSize.xxl,
|
||||
fontWeight: theme.typography.fontWeight.bold,
|
||||
color: theme.colors.text,
|
||||
},
|
||||
content: {
|
||||
padding: theme.spacing.md,
|
||||
},
|
||||
profileSection: {
|
||||
alignItems: 'center',
|
||||
paddingVertical: theme.spacing.xl,
|
||||
},
|
||||
avatarLarge: {
|
||||
width: 100,
|
||||
height: 100,
|
||||
borderRadius: 50,
|
||||
backgroundColor: theme.colors.primary,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginBottom: theme.spacing.md,
|
||||
...theme.shadows.glow,
|
||||
},
|
||||
avatarText: {
|
||||
fontSize: 48,
|
||||
fontWeight: theme.typography.fontWeight.bold,
|
||||
color: '#000',
|
||||
},
|
||||
username: {
|
||||
fontSize: theme.typography.fontSize.xxl,
|
||||
fontWeight: theme.typography.fontWeight.bold,
|
||||
color: theme.colors.text,
|
||||
marginBottom: 4,
|
||||
},
|
||||
membershipBadge: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
color: theme.colors.secondary,
|
||||
},
|
||||
domainCard: {
|
||||
backgroundColor: theme.colors.card,
|
||||
borderRadius: theme.borderRadius.lg,
|
||||
padding: theme.spacing.lg,
|
||||
marginBottom: theme.spacing.xl,
|
||||
borderWidth: 1,
|
||||
borderColor: theme.colors.primary + '30',
|
||||
},
|
||||
domainIcon: {
|
||||
fontSize: 32,
|
||||
marginBottom: theme.spacing.md,
|
||||
},
|
||||
domainInfo: {
|
||||
marginBottom: theme.spacing.md,
|
||||
},
|
||||
domainName: {
|
||||
fontSize: theme.typography.fontSize.lg,
|
||||
fontWeight: theme.typography.fontWeight.semibold,
|
||||
color: theme.colors.text,
|
||||
marginBottom: theme.spacing.sm,
|
||||
},
|
||||
domainDetail: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
color: theme.colors.textSecondary,
|
||||
marginBottom: 4,
|
||||
},
|
||||
domainButton: {
|
||||
backgroundColor: theme.colors.backgroundSecondary,
|
||||
padding: theme.spacing.md,
|
||||
borderRadius: theme.borderRadius.base,
|
||||
alignItems: 'center',
|
||||
},
|
||||
domainButtonText: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
color: theme.colors.primary,
|
||||
fontWeight: theme.typography.fontWeight.medium,
|
||||
},
|
||||
section: {
|
||||
marginBottom: theme.spacing.xl,
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
fontWeight: theme.typography.fontWeight.semibold,
|
||||
color: theme.colors.textTertiary,
|
||||
marginBottom: theme.spacing.md,
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
settingItem: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.colors.card,
|
||||
padding: theme.spacing.lg,
|
||||
borderRadius: theme.borderRadius.lg,
|
||||
marginBottom: theme.spacing.sm,
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(255, 255, 255, 0.05)',
|
||||
},
|
||||
settingIcon: {
|
||||
fontSize: 20,
|
||||
marginRight: theme.spacing.md,
|
||||
width: 24,
|
||||
},
|
||||
settingLabel: {
|
||||
flex: 1,
|
||||
fontSize: theme.typography.fontSize.base,
|
||||
color: theme.colors.text,
|
||||
},
|
||||
settingArrow: {
|
||||
fontSize: 20,
|
||||
color: theme.colors.textTertiary,
|
||||
},
|
||||
version: {
|
||||
textAlign: 'center',
|
||||
fontSize: theme.typography.fontSize.sm,
|
||||
color: theme.colors.textMuted,
|
||||
marginTop: theme.spacing.xl,
|
||||
marginBottom: theme.spacing.xxl,
|
||||
},
|
||||
});
|
||||
150
packages/mobile/src/theme/index.ts
Normal file
150
packages/mobile/src/theme/index.ts
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/**
|
||||
* Mobile Theme
|
||||
* Imports design tokens and adapts for React Native
|
||||
*/
|
||||
|
||||
// Import design tokens from UI package
|
||||
import { colors, spacing, typography, borderRadius, shadows } from '@aethex/ui';
|
||||
|
||||
export const theme = {
|
||||
colors: {
|
||||
// Background
|
||||
background: colors.background.primary,
|
||||
backgroundSecondary: colors.background.secondary,
|
||||
backgroundTertiary: colors.background.tertiary,
|
||||
|
||||
// Card
|
||||
card: colors.background.tertiary,
|
||||
cardElevated: colors.background.elevated,
|
||||
|
||||
// Text
|
||||
text: colors.text.primary,
|
||||
textSecondary: colors.text.secondary,
|
||||
textTertiary: colors.text.tertiary,
|
||||
textMuted: colors.text.muted,
|
||||
|
||||
// Brand
|
||||
primary: colors.primary[500],
|
||||
primaryLight: colors.primary[400],
|
||||
primaryDark: colors.primary[600],
|
||||
|
||||
accent: colors.accent[500],
|
||||
accentLight: colors.accent[400],
|
||||
accentDark: colors.accent[600],
|
||||
|
||||
secondary: colors.secondary[500],
|
||||
|
||||
// Semantic
|
||||
success: colors.success,
|
||||
warning: colors.warning,
|
||||
error: colors.error,
|
||||
info: colors.info,
|
||||
|
||||
// Status
|
||||
online: colors.status.online,
|
||||
idle: colors.status.idle,
|
||||
dnd: colors.status.dnd,
|
||||
offline: colors.status.offline,
|
||||
|
||||
// Effects
|
||||
glass: colors.effects.glass,
|
||||
glassBorder: colors.effects.glassBorder,
|
||||
overlay: colors.effects.overlay,
|
||||
|
||||
// Gray scale
|
||||
gray50: colors.gray[50],
|
||||
gray100: colors.gray[100],
|
||||
gray200: colors.gray[200],
|
||||
gray300: colors.gray[300],
|
||||
gray400: colors.gray[400],
|
||||
gray500: colors.gray[500],
|
||||
gray600: colors.gray[600],
|
||||
gray700: colors.gray[700],
|
||||
gray800: colors.gray[800],
|
||||
gray900: colors.gray[900],
|
||||
gray950: colors.gray[950],
|
||||
},
|
||||
|
||||
spacing: {
|
||||
xs: 4,
|
||||
sm: 8,
|
||||
md: 16,
|
||||
lg: 24,
|
||||
xl: 32,
|
||||
xxl: 48,
|
||||
xxxl: 64,
|
||||
},
|
||||
|
||||
typography: {
|
||||
fontFamily: typography.fontFamily.sans,
|
||||
|
||||
fontSize: {
|
||||
xs: 12,
|
||||
sm: 14,
|
||||
base: 16,
|
||||
lg: 18,
|
||||
xl: 20,
|
||||
xxl: 24,
|
||||
xxxl: 28,
|
||||
huge: 32,
|
||||
},
|
||||
|
||||
fontWeight: {
|
||||
light: '300' as const,
|
||||
normal: '400' as const,
|
||||
medium: '500' as const,
|
||||
semibold: '600' as const,
|
||||
bold: '700' as const,
|
||||
},
|
||||
},
|
||||
|
||||
borderRadius: {
|
||||
sm: 6,
|
||||
base: 8,
|
||||
md: 12,
|
||||
lg: 16,
|
||||
xl: 18,
|
||||
xxl: 24,
|
||||
full: 9999,
|
||||
},
|
||||
|
||||
shadows: {
|
||||
sm: {
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 1 },
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 2,
|
||||
elevation: 2,
|
||||
},
|
||||
md: {
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowOpacity: 0.4,
|
||||
shadowRadius: 8,
|
||||
elevation: 4,
|
||||
},
|
||||
lg: {
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 8 },
|
||||
shadowOpacity: 0.5,
|
||||
shadowRadius: 16,
|
||||
elevation: 8,
|
||||
},
|
||||
glow: {
|
||||
shadowColor: colors.primary[500],
|
||||
shadowOffset: { width: 0, height: 0 },
|
||||
shadowOpacity: 0.4,
|
||||
shadowRadius: 20,
|
||||
elevation: 10,
|
||||
},
|
||||
},
|
||||
|
||||
layout: {
|
||||
headerHeight: 56,
|
||||
tabBarHeight: 56,
|
||||
touchTarget: 48,
|
||||
messageBubbleMaxWidth: '80%',
|
||||
},
|
||||
};
|
||||
|
||||
export type Theme = typeof theme;
|
||||
|
|
@ -1,71 +1,109 @@
|
|||
/**
|
||||
* Design System Tokens
|
||||
* Shared design tokens across all platforms
|
||||
*
|
||||
* SLEEK DARK GAMING THEME
|
||||
* Inspired by: BitChat, Root, Discord Dark, Telegram
|
||||
*/
|
||||
|
||||
export const colors = {
|
||||
// Brand colors
|
||||
// Brand colors (Cyan primary - modern gaming)
|
||||
primary: {
|
||||
50: '#ecfeff',
|
||||
100: '#cffafe',
|
||||
200: '#a5f3fc',
|
||||
300: '#67e8f9',
|
||||
400: '#22d3ee',
|
||||
500: '#00d9ff', // Primary cyan
|
||||
600: '#00b8d9',
|
||||
700: '#0097b3',
|
||||
800: '#007a8f',
|
||||
900: '#006073',
|
||||
},
|
||||
|
||||
// Accent colors (Neon green gaming)
|
||||
accent: {
|
||||
50: '#f0fdf4',
|
||||
100: '#dcfce7',
|
||||
200: '#bbf7d0',
|
||||
300: '#86efac',
|
||||
400: '#4ade80',
|
||||
500: '#00ff88', // Neon green
|
||||
600: '#00e070',
|
||||
700: '#00c05d',
|
||||
800: '#009f4a',
|
||||
900: '#00803b',
|
||||
},
|
||||
|
||||
// Secondary accent (Purple for premium)
|
||||
secondary: {
|
||||
50: '#faf5ff',
|
||||
100: '#f3e8ff',
|
||||
200: '#e9d5ff',
|
||||
300: '#d8b4fe',
|
||||
400: '#c084fc',
|
||||
500: '#a855f7',
|
||||
500: '#a855f7', // Premium purple
|
||||
600: '#9333ea',
|
||||
700: '#7e22ce',
|
||||
800: '#6b21a8',
|
||||
900: '#581c87',
|
||||
},
|
||||
|
||||
// Accent colors
|
||||
accent: {
|
||||
50: '#fdf4ff',
|
||||
100: '#fae8ff',
|
||||
200: '#f5d0fe',
|
||||
300: '#f0abfc',
|
||||
400: '#e879f9',
|
||||
500: '#d946ef',
|
||||
600: '#c026d3',
|
||||
700: '#a21caf',
|
||||
800: '#86198f',
|
||||
900: '#701a75',
|
||||
},
|
||||
|
||||
// Neutral colors (dark theme)
|
||||
// Neutral colors (OLED-friendly blacks)
|
||||
gray: {
|
||||
50: '#fafafa',
|
||||
100: '#f4f4f5',
|
||||
200: '#e4e4e7',
|
||||
300: '#d4d4d8',
|
||||
400: '#a1a1aa',
|
||||
500: '#71717a',
|
||||
600: '#52525b',
|
||||
700: '#3f3f46',
|
||||
800: '#27272a',
|
||||
900: '#18181b',
|
||||
950: '#09090b',
|
||||
100: '#f5f5f5',
|
||||
200: '#e5e5e5',
|
||||
300: '#d4d4d4',
|
||||
400: '#a3a3a3',
|
||||
500: '#737373',
|
||||
600: '#525252',
|
||||
700: '#404040',
|
||||
800: '#262626',
|
||||
900: '#171717',
|
||||
950: '#0a0a0a', // Pure black for OLED
|
||||
},
|
||||
|
||||
// Semantic colors
|
||||
success: '#22c55e',
|
||||
warning: '#f59e0b',
|
||||
error: '#ef4444',
|
||||
info: '#3b82f6',
|
||||
success: '#10b981', // Green
|
||||
warning: '#f59e0b', // Orange
|
||||
error: '#ef4444', // Red
|
||||
info: '#00d9ff', // Cyan (matches primary)
|
||||
|
||||
// Background
|
||||
// Background (OLED-optimized)
|
||||
background: {
|
||||
primary: '#0a0a0f',
|
||||
secondary: '#18181b',
|
||||
tertiary: '#27272a',
|
||||
primary: '#000000', // Pure black for OLED battery saving
|
||||
secondary: '#0f0f0f', // Slightly elevated
|
||||
tertiary: '#1a1a1a', // Cards
|
||||
elevated: '#262626', // Modals/overlays
|
||||
},
|
||||
|
||||
// Text
|
||||
// Text (High contrast for readability)
|
||||
text: {
|
||||
primary: '#e4e4e7',
|
||||
secondary: '#a1a1aa',
|
||||
tertiary: '#71717a',
|
||||
muted: '#52525b',
|
||||
primary: '#ffffff', // White
|
||||
secondary: '#b0b0b0', // Light gray
|
||||
tertiary: '#707070', // Medium gray
|
||||
muted: '#505050', // Dark gray
|
||||
disabled: '#3a3a3a', // Very dark gray
|
||||
},
|
||||
|
||||
// Special effects
|
||||
effects: {
|
||||
glass: 'rgba(20, 20, 20, 0.7)', // Glassmorphism background
|
||||
glassBorder: 'rgba(255, 255, 255, 0.1)', // Glass border
|
||||
glow: 'rgba(0, 217, 255, 0.3)', // Cyan glow
|
||||
glowGreen: 'rgba(0, 255, 136, 0.3)', // Green glow
|
||||
glowPurple: 'rgba(168, 85, 247, 0.3)', // Purple glow
|
||||
overlay: 'rgba(0, 0, 0, 0.8)', // Dark overlay
|
||||
overlayLight: 'rgba(0, 0, 0, 0.5)', // Lighter overlay
|
||||
},
|
||||
|
||||
// Status indicators
|
||||
status: {
|
||||
online: '#3ba55c', // Discord green
|
||||
idle: '#faa61a', // Yellow
|
||||
dnd: '#ed4245', // Red
|
||||
offline: '#747f8d', // Gray
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -79,7 +117,8 @@ export const spacing = {
|
|||
6: '1.5rem', // 24px
|
||||
8: '2rem', // 32px
|
||||
10: '2.5rem', // 40px
|
||||
12: '3rem', // 48px
|
||||
12: '3rem', // 48px - Touch target minimum
|
||||
14: '3.5rem', // 56px - Bottom nav height
|
||||
16: '4rem', // 64px
|
||||
20: '5rem', // 80px
|
||||
24: '6rem', // 96px
|
||||
|
|
@ -87,23 +126,25 @@ export const spacing = {
|
|||
|
||||
export const typography = {
|
||||
fontFamily: {
|
||||
// Use native system fonts for best mobile performance
|
||||
sans: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
||||
mono: '"Fira Code", Consolas, Monaco, "Courier New", monospace',
|
||||
mono: 'ui-monospace, "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", Consolas, monospace',
|
||||
},
|
||||
|
||||
fontSize: {
|
||||
xs: '0.75rem', // 12px
|
||||
sm: '0.875rem', // 14px
|
||||
base: '1rem', // 16px
|
||||
lg: '1.125rem', // 18px
|
||||
xl: '1.25rem', // 20px
|
||||
'2xl': '1.5rem', // 24px
|
||||
'3xl': '1.875rem', // 30px
|
||||
'4xl': '2.25rem', // 36px
|
||||
'5xl': '3rem', // 48px
|
||||
xs: '0.75rem', // 12px - Captions, timestamps
|
||||
sm: '0.875rem', // 14px - Labels, secondary text
|
||||
base: '1rem', // 16px - Body text (mobile readable)
|
||||
lg: '1.125rem', // 18px - Emphasized text
|
||||
xl: '1.25rem', // 20px - Subheadings
|
||||
'2xl': '1.5rem', // 24px - Section headers
|
||||
'3xl': '1.75rem', // 28px - Screen titles
|
||||
'4xl': '2rem', // 32px - Hero text
|
||||
'5xl': '2.5rem', // 40px - Large hero
|
||||
},
|
||||
|
||||
fontWeight: {
|
||||
light: 300,
|
||||
normal: 400,
|
||||
medium: 500,
|
||||
semibold: 600,
|
||||
|
|
@ -114,7 +155,7 @@ export const typography = {
|
|||
none: 1,
|
||||
tight: 1.25,
|
||||
snug: 1.375,
|
||||
normal: 1.5,
|
||||
normal: 1.5, // Default for readability
|
||||
relaxed: 1.625,
|
||||
loose: 2,
|
||||
},
|
||||
|
|
@ -122,33 +163,44 @@ export const typography = {
|
|||
|
||||
export const borderRadius = {
|
||||
none: '0',
|
||||
sm: '0.25rem', // 4px
|
||||
sm: '0.375rem', // 6px
|
||||
base: '0.5rem', // 8px
|
||||
md: '0.75rem', // 12px
|
||||
lg: '1rem', // 16px
|
||||
xl: '1.5rem', // 24px
|
||||
full: '9999px',
|
||||
lg: '1rem', // 16px - Message bubbles
|
||||
xl: '1.125rem', // 18px - Message bubbles rounded
|
||||
'2xl': '1.5rem', // 24px - Cards
|
||||
full: '9999px', // Pills
|
||||
};
|
||||
|
||||
export const shadows = {
|
||||
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
||||
base: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
|
||||
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
||||
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
||||
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
|
||||
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
|
||||
glow: '0 0 20px rgba(139, 92, 246, 0.4)',
|
||||
// Subtle shadows for dark theme
|
||||
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.3)',
|
||||
base: '0 2px 4px 0 rgba(0, 0, 0, 0.4)',
|
||||
md: '0 4px 8px -2px rgba(0, 0, 0, 0.5)',
|
||||
lg: '0 8px 16px -4px rgba(0, 0, 0, 0.6)',
|
||||
xl: '0 16px 32px -8px rgba(0, 0, 0, 0.7)',
|
||||
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.8)',
|
||||
|
||||
// Glow effects for gaming aesthetic
|
||||
glowCyan: '0 0 20px rgba(0, 217, 255, 0.4)',
|
||||
glowCyanStrong: '0 0 30px rgba(0, 217, 255, 0.6)',
|
||||
glowGreen: '0 0 20px rgba(0, 255, 136, 0.4)',
|
||||
glowPurple: '0 0 20px rgba(168, 85, 247, 0.4)',
|
||||
glowSubtle: '0 0 10px rgba(255, 255, 255, 0.1)',
|
||||
};
|
||||
|
||||
export const breakpoints = {
|
||||
sm: '640px',
|
||||
md: '768px',
|
||||
lg: '1024px',
|
||||
xl: '1280px',
|
||||
'2xl': '1536px',
|
||||
// Mobile-first breakpoints
|
||||
xs: '375px', // Small phones
|
||||
sm: '640px', // Large phones
|
||||
md: '768px', // Tablets
|
||||
lg: '1024px', // Small laptops
|
||||
xl: '1280px', // Desktop
|
||||
'2xl': '1536px', // Large desktop
|
||||
};
|
||||
|
||||
export const zIndex = {
|
||||
base: 0,
|
||||
dropdown: 1000,
|
||||
sticky: 1100,
|
||||
fixed: 1200,
|
||||
|
|
@ -156,6 +208,7 @@ export const zIndex = {
|
|||
modal: 1400,
|
||||
popover: 1500,
|
||||
tooltip: 1600,
|
||||
toast: 1700,
|
||||
};
|
||||
|
||||
export const transitions = {
|
||||
|
|
@ -163,4 +216,58 @@ export const transitions = {
|
|||
base: '200ms cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
slow: '300ms cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
slower: '500ms cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
|
||||
// Easing functions
|
||||
easeInOut: 'cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
easeOut: 'cubic-bezier(0, 0, 0.2, 1)',
|
||||
easeIn: 'cubic-bezier(0.4, 0, 1, 1)',
|
||||
spring: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
|
||||
};
|
||||
|
||||
// Mobile-specific tokens
|
||||
export const mobile = {
|
||||
touchTarget: {
|
||||
minimum: '44px', // iOS HIG minimum
|
||||
comfortable: '48px', // Material Design
|
||||
large: '56px', // Bottom nav, FABs
|
||||
},
|
||||
|
||||
safeArea: {
|
||||
top: 'env(safe-area-inset-top)',
|
||||
bottom: 'env(safe-area-inset-bottom)',
|
||||
left: 'env(safe-area-inset-left)',
|
||||
right: 'env(safe-area-inset-right)',
|
||||
},
|
||||
|
||||
statusBar: {
|
||||
height: '44px', // iOS status bar
|
||||
heightAndroid: '24px',
|
||||
},
|
||||
|
||||
navbar: {
|
||||
height: '56px', // Standard mobile nav
|
||||
heightLarge: '64px', // Large title nav
|
||||
},
|
||||
|
||||
tabBar: {
|
||||
height: '56px', // Bottom tab bar
|
||||
heightSafe: 'calc(56px + env(safe-area-inset-bottom))',
|
||||
},
|
||||
};
|
||||
|
||||
// Glassmorphism effect tokens
|
||||
export const glass = {
|
||||
blur: '20px',
|
||||
blurStrong: '30px',
|
||||
blurSubtle: '10px',
|
||||
|
||||
background: {
|
||||
light: 'rgba(255, 255, 255, 0.05)',
|
||||
medium: 'rgba(255, 255, 255, 0.1)',
|
||||
dark: 'rgba(0, 0, 0, 0.3)',
|
||||
darker: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
|
||||
border: 'rgba(255, 255, 255, 0.1)',
|
||||
borderBright: 'rgba(255, 255, 255, 0.2)',
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue