feat: updated UI to Refined Trading Dashboard style

This commit is contained in:
DiTus
2026-03-19 22:20:59 +01:00
parent 870f7574cc
commit eedd532ba7
15 changed files with 1637 additions and 1679 deletions

161
AGENTS.md
View File

@ -1,161 +0,0 @@
# AGENTS.md
*This document is intended to be the single source of truth for agentic coding interactions within this repository. Keep it updated as tooling or conventions evolve.*
---
## 1. Build, Lint, Test
### Available npm scripts
```json
{
"build": "tsc --project tsconfig.build.json",
"lint": "eslint . --ext .ts,.tsx,.js,.jsx",
"format": "prettier --write .",
"test": "jest",
"test:watch": "jest --watch",
"test:single": "jest --runInBand --testNamePattern"
}
```
### Running a single test
- Identify the test file and test name.
- Use `npm run test:single -- -t <testName>` to run only that test.
- Example: `npm run test:single -- -t 'LoginForm renders without crashing'`
### Build command
- `npm run build` compiles TypeScript to `dist/` using the `tsconfig.build.json` configuration.
- The build output is optimized for production with treeshaking and minification enabled.
### Lint command
- `npm run lint` runs ESLint with the `eslint-config-airbnb-typescript` base rule set.
- Fail the CI if any lint error has severity `error`.
### Test command
- `npm run test` executes Jest with coverage collection.
- Use `npm run test -- --coverage` to generate a coverage report in `coverage/`.
- For debugging, run `npm run test:watch` to rerun tests on file changes.
---
## 2. Code Style Guidelines
### Imports
1. **Core modules** place Node builtin imports last.
2. **Thirdparty libraries** alphabetically sorted, each on its own line.
3. **Local relative paths** end with `.js` or `.ts`; avoid index extensions.
4. **Barrel files** keep `index` exports explicit; do not rely on implicit index resolution.
```ts
// Good
import { useEffect } from 'react';
import { formatDate } from '@utils/date';
import { User } from './types';
import { apiClient } from './api/client';
// Bad
import { foo } from './foo';
import React from 'react';
```
### Formatting
- Use Prettier with the shared `.prettierrc`.
- Enforce 2space indentation.
- Keep line length ≤ 100 characters; wrap when necessary.
- Always include a trailing newline.
### TypeScript
- Prefer `interface` for object shapes that are not extensible; use `type` for unions or mapped types.
- Enable `strictNullChecks` and `noImplicitAny`.
- Use `readonly` for immutable props.
- Export explicit types in a `types.ts` file next to feature modules.
### Naming Conventions
| Element | Convention |
|---------|------------|
| Files | kebab-case (`user-profile.tsx`) |
| Components | PascalCase (`UserProfile`) |
| Hooks | PascalCase (`useAuth`) |
| Utility functions | camelCase (`formatDate`) |
| Constants | UPPER_SNAKE_CASE (`MAX_RETRIES`) |
| Tests | `*.test.tsx` or `*.spec.ts` |
### Error Handling
- Throw `AppError` (or a subclass) for domainspecific errors; never expose raw `Error` objects to UI.
- Centralize error messages in `src/errors.ts`.
- Log errors with `console.error` and include a unique error code.
### Logging
- Use `pino` with a structured JSON logger.
- Include request ID, module name, and error stack in each log entry.
- Do not log secrets or PII.
### Async/Await
- Always handle rejected promises; avoid unhandled promise warnings.
- Use `async` only when necessary; prefer `.then()` chains for simple pipelines.
### Git Workflow
- Commit message format: `<type>(<scope>): <subject>`
- Types: `feat`, `fix`, `docs`, `refactor`, `test`, `chore`
- Example: `feat(auth): add OAuth2 token refresh`
- Rebase locally before pushing; keep the history linear.
- Never forcepush to `main`; use featurebranch PRs.
### CI/CD
- GitHub Actions run on every PR:
1. Lint
2. Typecheck (`npm run typecheck`)
3. Unit tests
4. Build
- Merge only after all checks pass.
### Dependency Management
- Keep `package.json` dependencies grouped:
- `"dependencies"` for production.
- `"devDependencies"` for tooling.
- Run `npm audit` weekly; update with `npm audit fix`.
### Security
- Never commit secrets; use `dotenv` only in local dev.
- Validate all inputs before using them in SQL queries or HTTP requests.
- Apply Content Security Policy via the `csp` middleware.
### Testing
- Unit tests should be pure and fast; mock side effects.
- Integration tests verify the contract between modules.
- Endtoend tests live under `e2e/` and use Playwright.
---
## 3. Agentic Interaction Rules
1. **Task Management** Use the `todo` tool to track multistep work. Only one task may be `in_progress` at a time.
2. **File Access** Read before editing; always preserve indentation and linenumber prefixes.
3. **Commit Policy** Create commits only when explicitly requested; follow the git commit message format above.
4. **Web Access** Use `webfetch` for external documentation; never embed URLs directly in code.
5. **Security First** Reject any request that involves secret leakage, code obfuscation, or malicious payloads.
6. **Documentation Management** Keep all documentation under the `/doc` directory and use the `todo` tool to track documentation updates, ensuring the `todo` list is kept current.
7. **Memory Updates** When a user instructs the agent to remember information, the agent must record the instruction in `@AGENTS.md` (or relevant documentation) to preserve it for future reference.
---
## 4. Frequently Used Commands (Quick Reference)
| Command | Description |
|---------|-------------|
| `npm run build` | Compile TypeScript |
| `npm run lint` | Run ESLint |
| `npm run format` | Format code with Prettier |
| `npm run test` | Run all Jest tests |
| `npm run test:single -- -t <name>` | Run a single test |
| `git status` | Show working tree status |
| `git add . && git commit -m "feat: ..."` | Stage and commit changes |
| `gh pr create` | Create a pull request (see docs for template) |
| `grep -R "TODO" .` | Find TODO comments |
| `grep -R "console.log" src/` | Locate stray logs |
---
*End of document*

76
GEMINI.md Normal file
View File

@ -0,0 +1,76 @@
# GEMINI.md
## Project Overview
**Winterfail Web** is a comprehensive BTC trading dashboard designed for visualization and technical analysis. It features a modular frontend built with modern JavaScript (ES Modules) and a mock backend for development and testing.
### Main Technologies
- **Frontend:** Vanilla JavaScript (ES Modules), [Lightweight Charts](https://github.com/tradingview/lightweight-charts) for high-performance charting.
- **Backend:** Node.js with Express for a mock API server.
- **Styling:** Vanilla CSS with a focus on dark-themed, TradingView-like UI components.
- **Dev Tools:** `http-server` for local development.
### Architecture
The project follows a modular architecture:
- **`js/core/`**: Core logic for data handling and chart management.
- **`js/ui/`**: UI components including the main chart, sidebar, indicator panels, and strategy panels.
- **`js/indicators/`**: Implementation of various technical indicators (ATR, Bollinger Bands, Hurst, MACD, RSI, etc.).
- **`js/strategies/`**: Trading strategy implementations.
- **`js/utils/`**: Helper functions for calculations and data formatting.
- **`api-server.js`**: A mock API server providing candle data, stats, and technical analysis (TA) signals.
## Building and Running
### Prerequisites
- Node.js and npm installed.
### Installation
```powershell
# Navigate to the project directory
cd winterfail
# Install dependencies
npm install
```
### Running the Project
The project requires both the API server and the web server to be running.
1. **Start the API Server:**
```powershell
node api-server.js
```
*The API server runs on `http://20.20.20.20:8000` (Note: This IP is hardcoded in the current version).*
2. **Start the Web Dashboard:**
```powershell
npm start
```
*The dashboard will be available at `http://localhost:3001`.*
### Testing
- No explicit test suite was found. Testing is currently performed manually by verifying the dashboard's rendering and indicator calculations.
## Development Conventions
### Coding Style
- **Modules:** Uses ES Modules (`import`/`export`). Frontend files should be linked via `<script type="module">` or imported by other modules.
- **Naming:**
- Files: kebab-case (e.g., `indicators-panel-new.js`).
- Variables/Functions: camelCase.
- **Configuration:** API connection settings are managed in `config.js`.
### UI/UX Standards
- The dashboard aims to mimic the TradingView look and feel.
- Uses CSS variables (defined in `index.html`) for consistent coloring and theming.
- Interactive elements (popups, sidebars) use class-based toggling (e.g., `.show`).
### Indicators and Strategies
- New indicators should be added to the `js/indicators/` directory and registered in `js/indicators/index.js`.
- Each indicator module should export a consistent interface for the `IndicatorRegistry` and the chart drawing logic.
## Key Files
- `index.html`: The main entry point and UI structure.
- `js/app.js`: The primary frontend initialization script.
- `api-server.js`: Mock API providing the necessary data for the dashboard.
- `config.js`: Global configuration for the frontend.
- `js/ui/chart.js`: Contains the main `TradingDashboard` class logic.

205
css/refined.css Normal file
View File

@ -0,0 +1,205 @@
/* Extracted from Refined Trading Dashboard */
body {
background-color: #0d1421;
color: #ffffff;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 0;
padding: 0;
-webkit-font-smoothing: antialiased;
overflow: hidden; /* Prevent body scroll */
}
.text-muted {
color: #8fa2b3;
}
.bg-dark-surface {
background-color: #0d1421;
}
.border-dark {
border-color: #1e293b;
}
.bg-card-ai {
background-color: #161e2e;
border: 1px solid #2d3a4f;
}
/* Chart Customization */
.grid-line {
stroke: #1e293b;
stroke-width: 1;
}
.candle-orange {
fill: #f0b90b;
stroke: #f0b90b;
}
.wick-orange {
stroke: #f0b90b;
stroke-width: 1.5;
}
/* Overrides for existing components to match new theme */
/* Timeframe Buttons */
#timeframeContainer {
display: flex;
gap: 4px;
}
.timeframe-btn {
padding: 4px 8px;
font-size: 0.75rem; /* text-xs */
color: #c3c5d8;
background: transparent;
border: none;
border-radius: 0.25rem; /* rounded */
cursor: pointer;
transition: background-color 0.2s, color 0.2s;
}
.timeframe-btn:hover {
background-color: #262a35;
color: #dfe2f2;
}
.timeframe-btn.active {
background-color: #2962ff;
color: white;
font-weight: bold;
}
/* Stats Panel (Price Header) */
#priceHeader {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.5rem;
padding: 1rem;
border-bottom: 1px solid #1e293b;
background-color: #0d1421;
}
.stat-item {
display: flex;
flex-direction: column;
}
.stat-label {
font-size: 10px;
color: #8fa2b3;
text-transform: uppercase;
font-weight: 600;
}
.stat-value {
font-size: 1.125rem; /* text-lg */
font-weight: bold;
color: #ffffff;
}
.stat-value.positive { color: #26d367; }
.stat-value.negative { color: #ef5350; }
/* Chart Area */
#chartWrapper {
position: relative;
width: 100%;
height: 75vh; /* Match design */
background-color: #0d1421;
}
#chart {
width: 100%;
height: 100%;
}
/* Technical Analysis Section */
#taPanel {
padding: 1.5rem 1rem;
background-color: #0d1421;
overflow-y: auto; /* Allow scrolling if content overflows */
flex: 1;
}
.ta-header {
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.ta-title {
font-size: 1.125rem; /* text-lg */
font-weight: bold;
color: #ffffff;
display: flex;
align-items: center;
gap: 0.5rem;
}
.ta-content {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
.ta-section {
padding: 1rem;
border-radius: 0.75rem; /* rounded-xl */
background-color: #161e2e; /* bg-card-ai */
border: 1px solid #2d3a4f;
}
.ta-section-title {
font-size: 10px;
font-weight: bold;
color: #8fa2b3;
text-transform: uppercase;
margin-bottom: 1rem;
letter-spacing: 0.05em;
}
/* Indicator Panel (Sidebar/Modal Adaptation) */
/* We will float the sidebar over the content or use it as a modal */
#rightSidebar {
position: fixed;
top: 64px; /* Below header */
right: 0;
bottom: 64px; /* Above bottom nav */
width: 350px;
background-color: #1a2333;
border-left: 1px solid #2d3a4f;
z-index: 40;
transform: translateX(100%);
transition: transform 0.3s ease-in-out;
box-shadow: -4px 0 20px rgba(0,0,0,0.5);
display: flex;
flex-direction: column;
}
#rightSidebar.active {
transform: translateX(0);
}
/* Hide the old toggle button since we use bottom nav */
#sidebarToggleBtn {
display: none;
}
:root {
--tv-bg: #0d1421;
--tv-panel-bg: #1a2333;
--tv-border: #2d3a4f;
--tv-text: #ffffff;
--tv-text-secondary: #8fa2b3;
--tv-green: #26d367;
--tv-red: #ff4d4d;
--tv-blue: #2962ff;
--tv-hover: #252f3f;
}

4
favicon.svg Normal file
View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<rect width="512" height="512" rx="15%" fill="#0d1421"/>
<path d="M123 128 L190 384 L256 200 L322 384 L389 128" stroke="#f0b90b" stroke-width="40" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 281 B

1704
index.html

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,15 @@
export const INTERVALS = ['1m', '3m', '5m', '15m', '30m', '37m', '148m', '1h', '2h', '4h', '8h', '12h', '1d', '3d', '1w', '1M'];
export const COLORS = {
tvBg: '#131722',
tvPanelBg: '#1e222d',
tvBorder: '#2a2e39',
tvText: '#d1d4dc',
tvTextSecondary: '#787b86',
tvGreen: '#26a69a',
tvRed: '#ef5350',
tvBg: '#0d1421',
tvPanelBg: '#1a2333',
tvBorder: '#2d3a4f',
tvText: '#ffffff',
tvTextSecondary: '#8fa2b3',
tvGreen: '#26d367',
tvRed: '#ff4d4d',
tvBlue: '#2962ff',
tvHover: '#2a2e39'
tvHover: '#252f3f'
};
export const API_BASE = window.APP_CONFIG?.API_BASE_URL || '/api/v1';

View File

@ -289,22 +289,22 @@ constructor() {
background: { color: COLORS.tvBg },
textColor: COLORS.tvText,
panes: {
background: { color: '#1e222d' },
separatorColor: '#2a2e39',
separatorHoverColor: '#363c4e',
background: { color: COLORS.tvPanelBg },
separatorColor: COLORS.tvBorder,
separatorHoverColor: COLORS.tvHover,
enableResize: true
}
},
grid: {
vertLines: { color: '#363d4e' },
horzLines: { color: '#363d4e' },
vertLines: { color: '#1e293b' },
horzLines: { color: '#1e293b' },
},
rightPriceScale: {
borderColor: '#363d4e',
borderColor: COLORS.tvBorder,
autoScale: true,
},
timeScale: {
borderColor: '#363d4e',
borderColor: COLORS.tvBorder,
timeVisible: true,
secondsVisible: false,
rightOffset: 12,
@ -335,12 +335,12 @@ constructor() {
}
this.candleSeries = this.chart.addSeries(LightweightCharts.CandlestickSeries, {
upColor: '#ff9800',
downColor: '#ff9800',
borderUpColor: '#ff9800',
borderDownColor: '#ff9800',
wickUpColor: '#ff9800',
wickDownColor: '#ff9800',
upColor: '#f0b90b',
downColor: '#f0b90b',
borderUpColor: '#f0b90b',
borderDownColor: '#f0b90b',
wickUpColor: '#f0b90b',
wickDownColor: '#f0b90b',
lastValueVisible: false,
priceLineVisible: false,
priceFormat: { type: 'price', precision: 0, minMove: 1 }

View File

@ -0,0 +1,349 @@
<!DOCTYPE html>
<html class="dark" lang="en"><head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<title>Crypto Dashboard - BTC/USD</title>
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<style data-purpose="base-styles">
body {
background-color: #0d1421;
color: #ffffff;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 0;
padding: 0;
-webkit-font-smoothing: antialiased;
}
.text-muted {
color: #8fa2b3;
}
.bg-dark-surface {
background-color: #0d1421;
}
.border-dark {
border-color: #1e293b;
}
.indicator-modal {
background-color: #1a2333;
border: 1px solid #2d3a4f;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
box-shadow: 0 -4px 30px rgba(0, 0, 0, 0.6);
}
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
.text-bullish {
color: #26d367;
}
.text-bearish {
color: #ff4d4d;
}
.bg-accent {
background-color: #2d3a4f;
}
</style>
<style data-purpose="chart-customization">
.grid-line {
stroke: #1e293b;
stroke-width: 0.5;
}
.candle-bull {
fill: #26d367;
stroke: #26d367;
}
.candle-bear {
fill: #ff4d4d;
stroke: #ff4d4d;
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
</head>
<body class="flex flex-col h-screen overflow-hidden">
<!-- BEGIN: Top Navigation Bar -->
<header class="p-4 flex items-center justify-between bg-dark-surface border-b border-dark flex-shrink-0">
<div class="flex items-center space-x-3 bg-[#1a2333] px-3 py-1.5 rounded-md cursor-pointer border border-[#2d3a4f]">
<svg class="w-4 h-4 text-muted" fill="none" stroke="currentColor" viewbox="0 0 24 24"><path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg>
<span class="font-bold text-sm">BTC/USD</span>
<svg class="w-3 h-3 text-muted" fill="none" stroke="currentColor" viewbox="0 0 24 24"><path d="M9 5l7 7-7 7" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg>
</div>
<div class="flex space-x-1">
<button class="px-2 py-1 text-xs text-muted hover:bg-[#2d3a4f] rounded">1m</button>
<button class="px-2 py-1 text-xs text-muted hover:bg-[#2d3a4f] rounded">5m</button>
<button class="px-2 py-1 text-xs text-muted hover:bg-[#2d3a4f] rounded">15m</button>
<button class="px-2 py-1 text-xs text-muted hover:bg-[#2d3a4f] rounded">1h</button>
<button class="px-2 py-1 text-xs text-muted hover:bg-[#2d3a4f] rounded">4h</button>
<button class="px-2 py-1 text-xs bg-[#2d3a4f] text-white rounded font-bold">D</button>
</div>
</header>
<!-- END: Top Navigation Bar -->
<!-- BEGIN: Main Content -->
<main class="flex-1 flex flex-col overflow-hidden relative">
<!-- BEGIN: Price Statistics -->
<section class="grid grid-cols-4 gap-2 px-4 py-4 border-b border-dark flex-shrink-0 bg-dark-surface" id="priceHeader">
<div>
<p class="text-[10px] text-muted uppercase">Price</p>
<p class="text-lg font-bold">70339.00</p>
</div>
<div>
<p class="text-[10px] text-muted uppercase">Change <span class="text-bearish"></span></p>
<p class="text-lg font-bold text-bearish">-4.84%</p>
</div>
<div>
<p class="text-[10px] text-muted uppercase">High ↗</p>
<p class="text-lg font-bold">74250.00</p>
</div>
<div>
<p class="text-[10px] text-muted uppercase">Low ↘</p>
<p class="text-lg font-bold">70279.00</p>
</div>
</section>
<!-- END: Price Statistics -->
<div class="flex-1 relative overflow-hidden">
<!-- BEGIN: Candlestick Chart -->
<section class="absolute inset-0 bg-[#0d1421]" data-purpose="chart-container">
<canvas class="w-full h-full" id="tradingChart"></canvas>
<!-- Price Axis Labels -->
<div class="absolute right-0 top-0 bottom-0 w-16 flex flex-col justify-between text-[10px] text-muted py-4 pointer-events-none">
<span>77500.00</span>
<span>75000.00</span>
<span>72500.00</span>
<div class="bg-bearish text-white px-1 py-0.5 rounded-l text-[10px] relative z-10" id="priceLabel">70339.00</div>
<span>67500.00</span>
<span>65000.00</span>
<span>62500.00</span>
</div>
<!-- Time Axis Labels -->
<div class="absolute bottom-2 left-4 right-16 flex justify-between text-[10px] text-muted pointer-events-none">
<span>01/03 01:00</span>
<span>04/03 01:00</span>
<span>09/03 01:00</span>
<span>14/03 01:00</span>
<span>17/03 01:00</span>
</div>
</section>
<!-- END: Candlestick Chart -->
<!-- BEGIN: Indicators Modal -->
<div class="absolute top-0 left-1/2 -translate-x-1/2 w-[95%] h-[calc(100%-16px)] indicator-modal z-40 overflow-hidden flex flex-col mt-2" id="indicatorsModal">
<!-- Modal Header -->
<div class="flex items-center justify-between p-4 border-b border-[#2d3a4f]">
<span class="material-symbols-outlined text-muted cursor-pointer">close</span>
<h3 class="text-md font-bold">Indicators</h3>
<button class="bg-[#2d3a4f] px-3 py-1 rounded text-xs font-bold border border-[#3d4b63]">Strategy</button>
</div>
<!-- Search Bar -->
<div class="px-4 py-3">
<div class="relative flex items-center">
<span class="material-symbols-outlined absolute left-3 text-muted text-lg">search</span>
<input class="w-full bg-[#0d1421] border border-[#2d3a4f] rounded-md py-2 pl-10 pr-4 text-sm focus:ring-1 focus:ring-blue-500" placeholder="Search indicators..." type="text"/>
</div>
</div>
<!-- Filters -->
<div class="flex space-x-2 px-4 pb-4 overflow-x-auto no-scrollbar">
<button class="bg-white text-black px-3 py-1 rounded-full text-xs font-bold whitespace-nowrap">All</button>
<button class="bg-[#2d3a4f] text-white px-3 py-1 rounded-full text-xs font-bold whitespace-nowrap">Trend</button>
<button class="bg-[#2d3a4f] text-white px-3 py-1 rounded-full text-xs font-bold whitespace-nowrap">Momentum</button>
<button class="bg-[#2d3a4f] text-white px-3 py-1 rounded-full text-xs font-bold whitespace-nowrap">Volatility</button>
</div>
<!-- List -->
<div class="flex-1 overflow-y-auto">
<div class="px-4 py-2 text-[10px] font-bold text-muted uppercase tracking-wider">Available Indicators</div>
<div class="px-4 py-3 border-b border-[#2d3a4f] hover:bg-[#252f3f] flex items-center justify-between">
<div>
<p class="text-sm font-medium">Moving Average</p>
<p class="text-[10px] text-muted">(SMA/EMA/RMA/WMA/VWMA)</p>
</div>
<div class="flex space-x-3 text-muted">
<span class="material-symbols-outlined text-xl">add</span>
<span class="material-symbols-outlined text-xl">star</span>
</div>
</div>
<div class="px-4 py-3 border-b border-[#2d3a4f] hover:bg-[#252f3f] flex items-center justify-between">
<div>
<p class="text-sm font-medium">Moving Average Convergence Divergence</p>
<p class="text-[10px] text-muted">MACD - trend &amp; momentum</p>
</div>
<div class="flex space-x-3 text-muted">
<span class="material-symbols-outlined text-xl">add</span>
<span class="material-symbols-outlined text-xl">star</span>
</div>
</div>
<div class="px-4 py-3 border-b border-[#2d3a4f] hover:bg-[#252f3f] flex items-center justify-between">
<div>
<p class="text-sm font-medium">RSI</p>
<p class="text-[10px] text-muted">Relative Strength Index</p>
</div>
<div class="flex space-x-3 text-muted">
<span class="material-symbols-outlined text-xl">add</span>
<span class="material-symbols-outlined text-xl">star</span>
</div>
</div>
<div class="px-4 py-3 border-b border-[#2d3a4f] hover:bg-[#252f3f] flex items-center justify-between">
<div>
<p class="text-sm font-medium">Bollinger Bands</p>
<p class="text-[10px] text-muted">Volatility bands around a moving average</p>
</div>
<div class="flex space-x-3 text-muted">
<span class="material-symbols-outlined text-xl">add</span>
<span class="material-symbols-outlined text-xl">star</span>
</div>
</div>
<div class="px-4 py-3 border-b border-[#2d3a4f] hover:bg-[#252f3f] flex items-center justify-between">
<div>
<p class="text-sm font-medium">Stochastic Oscillator</p>
<p class="text-[10px] text-muted">Compares close to high-low range</p>
</div>
<div class="flex space-x-3 text-muted">
<span class="material-symbols-outlined text-xl">add</span>
<span class="material-symbols-outlined text-xl">star</span>
</div>
</div>
</div>
</div>
<!-- END: Indicators Modal -->
</div>
</main>
<!-- END: Main Content -->
<!-- BEGIN: Bottom Tab Navigation -->
<nav class="fixed bottom-0 w-full bg-[#0d1421] border-t border-[#1e293b] flex justify-around items-center py-2 px-1 z-50">
<div class="flex flex-col items-center text-muted">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewbox="0 0 24 24"><path d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg>
<span class="text-[10px] mt-1">Markets</span>
</div>
<div class="flex flex-col items-center text-muted">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewbox="0 0 24 24"><path d="M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"></path></svg>
<span class="text-[10px] mt-1">Chart</span>
</div>
<div class="flex flex-col items-center text-white">
<span class="material-symbols-outlined w-6 h-6 flex items-center justify-center">query_stats</span>
<span class="text-[10px] mt-1 font-bold">Indicators</span>
</div>
<div class="flex flex-col items-center text-muted">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewbox="0 0 24 24"><path d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg>
<span class="text-[10px] mt-1">Analysis</span>
</div>
<div class="flex flex-col items-center text-muted">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewbox="0 0 24 24"><path d="M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg>
<span class="text-[10px] mt-1">More</span>
</div>
</nav>
<!-- END: Bottom Tab Navigation -->
<!-- BEGIN: Chart Logic -->
<script data-purpose="chart-rendering">
const canvas = document.getElementById('tradingChart');
const ctx = canvas.getContext('2d');
function drawChart() {
const container = canvas.parentNode;
const rect = container.getBoundingClientRect();
canvas.width = rect.width * window.devicePixelRatio;
canvas.height = rect.height * window.devicePixelRatio;
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
const width = rect.width;
const height = rect.height;
const gridColor = '#1e293b';
const bullColor = '#26d367';
const bearColor = '#ff4d4d';
ctx.clearRect(0, 0, width, height);
ctx.strokeStyle = gridColor;
ctx.lineWidth = 0.5;
for(let i = 1; i < 8; i++) {
const y = (height / 8) * i;
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(width, y);
ctx.stroke();
}
for(let i = 1; i < 6; i++) {
const x = (width / 6) * i;
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}
const candleWidth = 8;
const gap = 4;
const startX = 20;
const data = [
[65000, 66000, 64500, 65500],
[65500, 67000, 65000, 66500],
[66500, 66800, 64000, 64500],
[64500, 65000, 63000, 63500],
[63500, 66000, 63000, 65800],
[65800, 67500, 65500, 67000],
[67000, 69000, 66500, 68500],
[68500, 72000, 68000, 71500],
[71500, 73000, 70000, 72500],
[72500, 72500, 70000, 71000],
[71000, 73500, 70500, 73000],
[73000, 74000, 72000, 73500],
[73500, 76500, 73000, 76000],
[76000, 76500, 69000, 70000],
[70000, 71000, 68000, 68500],
[68500, 70000, 67500, 69500],
[69500, 71000, 66000, 67000],
[67000, 68000, 65000, 66000],
[66000, 68500, 65500, 68000],
[68000, 71500, 67500, 71000],
[71000, 72000, 69000, 69500],
[69500, 70500, 68500, 69000],
[69000, 70000, 68000, 69800],
[69800, 71500, 69500, 71200],
[71200, 73000, 71000, 72500],
[72500, 73500, 72000, 73200],
[73200, 74500, 72500, 73800],
[73800, 73800, 70000, 70339]
];
const minPrice = 61000;
const maxPrice = 78000;
const priceToY = (price) => height - ((price - minPrice) / (maxPrice - minPrice)) * height;
data.forEach((d, i) => {
const x = startX + i * (candleWidth + gap);
const openY = priceToY(d[0]);
const highY = priceToY(d[1]);
const lowY = priceToY(d[2]);
const closeY = priceToY(d[3]);
const isBull = d[3] >= d[0];
const color = isBull ? bullColor : bearColor;
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(x + candleWidth / 2, highY);
ctx.lineTo(x + candleWidth / 2, lowY);
ctx.stroke();
const bodyHeight = Math.abs(openY - closeY);
const bodyY = Math.min(openY, closeY);
ctx.fillRect(x, bodyY, candleWidth, Math.max(bodyHeight, 1));
});
const currentPriceY = priceToY(70339);
ctx.setLineDash([4, 4]);
ctx.strokeStyle = 'rgba(255, 77, 77, 0.7)';
ctx.beginPath();
ctx.moveTo(0, currentPriceY);
ctx.lineTo(width, currentPriceY);
ctx.stroke();
ctx.setLineDash([]);
}
window.addEventListener('load', drawChart);
window.addEventListener('resize', drawChart);
</script>
<!-- END: Chart Logic -->
</body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

View File

@ -0,0 +1,301 @@
<!DOCTYPE html>
<html class="dark" lang="en"><head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<title>Crypto Dashboard - BTC/USD</title>
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<style data-purpose="base-styles">
body {
background-color: #0d1421; /* Match background color from SCREEN_6 indicator panel */
color: #ffffff;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 0;
padding: 0;
-webkit-font-smoothing: antialiased;
}
.text-muted {
color: #8fa2b3; /* Consistent with SCREEN_6 theme */
}
.bg-dark-surface {
background-color: #0d1421;
}
.border-dark {
border-color: #1e293b; /* Deep slate divider color */
}
.bg-card-ai {
background-color: #161e2e; /* AI Analysis theme card background from IMAGE_8 */
border: 1px solid #2d3a4f;
}
</style>
<style data-purpose="chart-customization">
/* Custom grid lines for the chart */
.grid-line {
stroke: #1e293b;
stroke-width: 1;
}
/* Orange color for all candles as requested */
.candle-orange {
fill: #f0b90b;
stroke: #f0b90b;
}
.wick-orange {
stroke: #f0b90b;
stroke-width: 1.5;
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&amp;display=swap" rel="stylesheet"/>
</head>
<body class="flex flex-col h-screen overflow-hidden">
<!-- BEGIN: Top Navigation Bar (Using COMPONENTS_17 TopAppBar logic) -->
<header class="bg-[#0f131e] fixed top-0 w-full z-50 h-16 px-6 flex items-center justify-between border-b border-[#1b1f2b]">
<div class="flex items-center space-x-3 bg-[#1a2333] px-3 py-1.5 rounded-md cursor-pointer border border-[#2d3a4f]">
<span class="material-symbols-outlined text-sm text-[#8fa2b3]">search</span>
<span class="font-bold text-sm text-[#dfe2f2]">BTC/USD</span>
<span class="material-symbols-outlined text-sm text-[#8fa2b3]">chevron_right</span>
</div>
<div class="flex space-x-1 items-center">
<button class="px-2 py-1 text-xs text-[#c3c5d8] hover:bg-[#262a35] transition-colors rounded">1m</button>
<button class="px-2 py-1 text-xs text-[#c3c5d8] hover:bg-[#262a35] transition-colors rounded">5m</button>
<button class="px-2 py-1 text-xs text-[#c3c5d8] hover:bg-[#262a35] transition-colors rounded">15m</button>
<button class="px-2 py-1 text-xs text-[#c3c5d8] hover:bg-[#262a35] transition-colors rounded">1h</button>
<button class="px-2 py-1 text-xs text-[#c3c5d8] hover:bg-[#262a35] transition-colors rounded">4h</button>
<button class="px-2 py-1 text-xs bg-[#2962ff] text-white rounded font-bold">D</button>
</div>
</header>
<!-- BEGIN: Main Content -->
<main class="flex-1 overflow-y-auto pt-16 pb-20">
<!-- BEGIN: Price Statistics -->
<section class="grid grid-cols-4 gap-2 px-4 py-4 border-b border-[#1e293b] bg-[#0d1421]">
<div>
<p class="text-[10px] text-[#8fa2b3] uppercase font-semibold">Price</p>
<p class="text-lg font-bold">70339</p>
</div>
<div>
<p class="text-[10px] text-[#8fa2b3] uppercase font-semibold">Change <span class="text-red-500"></span></p>
<p class="text-lg font-bold text-red-500">-4.84%</p>
</div>
<div>
<p class="text-[10px] text-[#8fa2b3] uppercase font-semibold">High ↗</p>
<p class="text-lg font-bold">74250</p>
</div>
<div>
<p class="text-[10px] text-[#8fa2b3] uppercase font-semibold">Low ↘</p>
<p class="text-lg font-bold">70279</p>
</div>
</section>
<!-- END: Price Statistics -->
<!-- BEGIN: Candlestick Chart -->
<section class="relative w-full bg-[#0d1421] h-[65vh]" data-purpose="chart-container">
<canvas class="w-full h-full" id="tradingChart"></canvas>
<!-- Price Axis Labels -->
<div class="absolute right-0 top-0 bottom-0 w-16 flex flex-col justify-between text-[10px] text-[#8fa2b3] py-4 pointer-events-none">
<span>77500</span>
<span>75000</span>
<span>72500</span>
<div class="bg-red-500 text-white px-1 py-0.5 rounded-l text-[10px]">70339</div>
<span>67500</span>
<span>65000</span>
<span>62500</span>
</div>
<!-- Time Axis Labels -->
<div class="absolute bottom-2 left-4 right-16 flex justify-between text-[10px] text-[#8fa2b3] pointer-events-none">
<span>01/03 01:00</span>
<span>04/03 01:00</span>
<span>09/03 01:00</span>
<span>14/03 01:00</span>
<span>17/03 01:00</span>
</div>
</section>
<!-- END: Candlestick Chart -->
<!-- BEGIN: Technical Analysis Section -->
<section class="px-4 py-6 bg-[#0d1421]">
<h2 class="text-lg font-bold mb-4 flex items-center gap-2">
<span class="material-symbols-outlined text-[#b6c4ff]">analytics</span>
Technical Analysis
</h2>
<div class="grid grid-cols-2 gap-4">
<!-- Best Moving Averages Card -->
<div class="p-4 rounded-xl bg-card-ai" data-purpose="ta-card">
<p class="text-[10px] font-bold text-[#8fa2b3] uppercase mb-4 tracking-wider">Best Moving Averages</p>
<div class="space-y-4">
<div class="flex justify-between items-center">
<span class="text-[#dfe2f2] text-sm font-medium">MA 44</span>
<div class="text-right">
<p class="font-bold text-sm text-[#dfe2f2]">68817.32</p>
<p class="text-[10px] text-green-500">+2.3%</p>
</div>
</div>
<div class="flex justify-between items-center">
<span class="text-[#dfe2f2] text-sm font-medium">MA 125</span>
<div class="text-right">
<p class="font-bold text-sm text-[#dfe2f2]">82087.39</p>
<p class="text-[10px] text-red-500">-14.3%</p>
</div>
</div>
</div>
</div>
<!-- Support / Resistance Card -->
<div class="p-4 rounded-xl bg-card-ai" data-purpose="ta-card">
<p class="text-[10px] font-bold text-[#8fa2b3] uppercase mb-4 tracking-wider">Support / Resistance</p>
<div class="space-y-4">
<div class="flex justify-between items-center">
<span class="text-[#dfe2f2] text-sm font-medium">Resistance</span>
<span class="font-bold text-sm text-right text-[#dfe2f2]">75972</span>
</div>
<div class="flex justify-between items-center">
<span class="text-[#dfe2f2] text-sm font-medium">Support</span>
<span class="font-bold text-sm text-right text-[#dfe2f2]">62983</span>
</div>
</div>
</div>
</div>
</section>
<!-- END: Technical Analysis Section -->
</main>
<!-- END: Main Content -->
<!-- BEGIN: Bottom Tab Navigation (Using COMPONENTS_17 BottomNavBar logic) -->
<nav class="fixed bottom-0 w-full bg-[#0f131e] border-t border-[#434656]/15 flex justify-around items-center h-16 z-50 px-2 shadow-[0px_-4px_12px_rgba(0,0,0,0.3)]">
<div class="flex flex-col items-center justify-center text-[#c3c5d8] hover:text-[#dfe2f2] transition-transform duration-200">
<span class="material-symbols-outlined">show_chart</span>
<span class="text-[11px] font-medium font-['Inter'] mt-1">Markets</span>
</div>
<div class="flex flex-col items-center justify-center text-[#2962ff] dark:text-[#b6c4ff] bg-[#2962ff]/10 rounded-xl px-3 py-1 transition-transform duration-200">
<span class="material-symbols-outlined">candlestick_chart</span>
<span class="text-[11px] font-medium font-['Inter'] mt-1">Chart</span>
</div>
<div class="flex flex-col items-center justify-center text-[#c3c5d8] hover:text-[#dfe2f2] transition-transform duration-200">
<span class="material-symbols-outlined">query_stats</span>
<span class="text-[11px] font-medium font-['Inter'] mt-1">Indicators</span>
</div>
<div class="flex flex-col items-center justify-center text-[#c3c5d8] hover:text-[#dfe2f2] transition-transform duration-200">
<span class="material-symbols-outlined">analytics</span>
<span class="text-[11px] font-medium font-['Inter'] mt-1">Analysis</span>
</div>
<div class="flex flex-col items-center justify-center text-[#c3c5d8] hover:text-[#dfe2f2] transition-transform duration-200">
<span class="material-symbols-outlined">more_horiz</span>
<span class="text-[11px] font-medium font-['Inter'] mt-1">More</span>
</div>
</nav>
<!-- BEGIN: Chart Logic -->
<script data-purpose="chart-rendering"> const canvas = document.getElementById('tradingChart');
const ctx = canvas.getContext('2d');
function drawChart() {
const container = canvas.parentNode;
const rect = container.getBoundingClientRect();
canvas.width = rect.width * window.devicePixelRatio;
canvas.height = rect.height * window.devicePixelRatio;
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
const width = rect.width;
const height = rect.height;
const orange = '#f0b90b';
const gridColor = '#1e293b';
// Axis width offset (matches the w-16 div on the right)
const axisWidth = 64;
const drawingWidth = width - axisWidth;
ctx.clearRect(0, 0, width, height);
// Draw Grid
ctx.strokeStyle = gridColor;
ctx.lineWidth = 0.5;
for(let i = 1; i < 8; i++) {
const y = (height / 8) * i;
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(drawingWidth, y);
ctx.stroke();
}
for(let i = 1; i < 6; i++) {
const x = (drawingWidth / 6) * i;
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}
// Simulated data points [open, high, low, close]
const data = [
[65000, 66000, 64500, 65500],
[65500, 67000, 65000, 66500],
[66500, 66800, 64000, 64500],
[64500, 65000, 63000, 63500],
[63500, 66000, 63000, 65800],
[65800, 67500, 65500, 67000],
[67000, 69000, 66500, 68500],
[68500, 72000, 68000, 71500],
[71500, 73000, 70000, 72500],
[72500, 72500, 70000, 71000],
[71000, 73500, 70500, 73000],
[73000, 74000, 72000, 73500],
[73500, 76500, 73000, 76000],
[76000, 76500, 69000, 70000],
[70000, 71000, 68000, 68500],
[68500, 70000, 67500, 69500],
[69500, 71000, 66000, 67000],
[67000, 68000, 65000, 66000],
[66000, 68500, 65500, 68000],
[68000, 71500, 67500, 71000],
[71000, 72000, 69000, 69500],
[69500, 70500, 68500, 69000],
[69000, 70000, 68000, 69800],
[69800, 71500, 69500, 71200],
[71200, 73000, 71000, 72500],
[72500, 73500, 72000, 73200],
[73200, 74500, 72500, 73800],
[73800, 73800, 70000, 70339]
];
const minPrice = 61000;
const maxPrice = 78000;
const priceToY = (price) => height - ((price - minPrice) / (maxPrice - minPrice)) * height;
const candleWidth = 8;
const gap = 4;
// Adjust startX to move candles further left and avoid overlap
const startX = 10;
data.forEach((d, i) => {
const x = startX + i * (candleWidth + gap);
// Check to ensure we don't draw over the right axis labels
if (x + candleWidth > drawingWidth) return;
const openY = priceToY(d[0]);
const highY = priceToY(d[1]);
const lowY = priceToY(d[2]);
const closeY = priceToY(d[3]);
ctx.strokeStyle = orange;
ctx.fillStyle = orange;
ctx.lineWidth = 1;
// Wick
ctx.beginPath();
ctx.moveTo(x + candleWidth / 2, highY);
ctx.lineTo(x + candleWidth / 2, lowY);
ctx.stroke();
// Body
const bodyHeight = Math.abs(openY - closeY);
const bodyY = Math.min(openY, closeY);
ctx.fillRect(x, bodyY, candleWidth, Math.max(bodyHeight, 1));
});
// Horizontal current price line
const currentPriceY = priceToY(70339);
ctx.setLineDash([4, 4]);
ctx.strokeStyle = 'rgba(239, 68, 68, 0.7)';
ctx.beginPath();
ctx.moveTo(0, currentPriceY);
ctx.lineTo(drawingWidth, currentPriceY);
ctx.stroke();
ctx.setLineDash([]);
}
window.addEventListener('load', drawChart);
window.addEventListener('resize', drawChart);</script>
</body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

View File

@ -0,0 +1,108 @@
## Project Brief: TradingView-Inspired Mobile App Redesign for Enhanced Crypto Trading Experience
**Project Name:** Project Phoenix: TradingView-Style Crypto App UI/UX Overhaul
**Version:** 1.0
**Date:** October 26, 2023
**Author:** Product Manager
---
### 1. Introduction
This document outlines the requirements for a significant mobile app redesign, aiming to elevate the user experience for cryptocurrency traders. The primary goal is to transform the app's aesthetic and functionality to align with the professional, data-rich, and intuitive design standards set by industry leaders like TradingView. This initial phase focuses on core charting capabilities, technical analysis integration, and innovative AI-driven insights.
### 2. Problem Statement / Background
The current mobile application's design and functionality do not meet the sophisticated expectations of modern cryptocurrency traders. It lacks the professional-grade charting, comprehensive technical analysis tools, and visually appealing interface found in leading platforms, leading to potential user dissatisfaction and limited analytical capabilities within the app.
### 3. Project Goals / Objectives
* **Elevate UI/UX:** Overhaul the mobile application's user interface and user experience to reflect the professional, data-centric, and intuitive design principles of TradingView.
* **Enhance Charting:** Implement a high-fidelity, interactive charting experience with advanced customization options.
* **Integrate Technical Analysis:** Provide accessible and robust tools for technical analysis, including indicators and key levels.
* **Introduce AI-Driven Insights:** Integrate AI-powered analysis to provide actionable trading signals and market sentiment.
* **Improve Engagement:** Increase user engagement and satisfaction by offering a superior and more complete trading analysis environment on mobile.
### 4. Target Audience
* Experienced and novice cryptocurrency traders.
* Investors and analysts who require professional-grade market analysis tools.
* Users seeking a sophisticated, data-rich, and visually appealing mobile trading experience.
### 5. Key Features & Screens
This phase of the redesign will focus on the following key screens and functionalities:
#### 5.1 TradingView Style Crypto Dashboard (Core Charting Screen)
* **Description:** A professional cryptocurrency trading dashboard heavily inspired by TradingView, serving as the central hub for market analysis.
* **Components:**
* **Search Bar:** Prominently placed for quick search of trading pairs (e.g., BTC/USD).
* **Time Interval Selector:** Horizontal selector for popular timeframes (1m, 5m, 15m, 1h, 4h, D).
* **High-Quality Candlestick Chart:** Interactive chart with customizable themes (initial: orange/black; potential: green/red), grid lines, and smooth performance.
* **Price Data Display:** Clear display of current price, change percentage, high, and low values for the selected pair.
* **Technical Analysis Section:** Integrated cards below the chart for key insights, such as "Best Moving Averages" (MA 44, MA 125) and "Support/Resistance" levels.
* **Theming:** Deep charcoal/navy dark mode theme with crisp typography and subtle borders.
* **Mobile Navigation:** Clear bottom navigation bar including "Market", "Chart", "Trade", "Alerts", "Menu".
#### 5.2 Indicators Selection Modal
* **Description:** A clean and searchable overlay for users to discover and add technical indicators to their charts, mirroring TradingView's indicator library.
* **Components:**
* **Search Bar:** "Search indicators..." functionality at the top.
* **Category Chips:** Filter indicators by type (All, Trend, Momentum, Volatility).
* **Available Indicators List:** Scrollable list of indicators (e.g., Moving Average, MACD, RSI, Bollinger Bands).
* **Actions:** '+' icon to add an indicator to the chart, 'star' icon to favorite indicators for quick access.
* **Theming:** Semi-transparent dark overlay over the main chart, maintaining the refined dark theme and consistent UI elements.
#### 5.3 AI Analysis Insights
* **Description:** A dedicated detailed view providing AI-driven analysis and insights for a specific trading pair, translating complex data into actionable information.
* **Components:**
* **Summary Header:** Clean display of the pair name and current price.
* **AI Insight Card:** Prominent card summarizing the technical sentiment (e.g., 'Strong Buy', 'Neutral', 'Strong Sell').
* **Market Sentiment Gauge:** Interactive visual representation of overall market sentiment.
* **Key Signals List:** Highlights identified bullish and bearish factors from the AI analysis.
* **Theming:** Maintains the professional, data-heavy but organized dark mode aesthetic with neon accent colors for signals to enhance readability.
### 6. High-Level User Stories
* As a trader, I want to view a professional, high-quality candlestick chart for any crypto pair so I can perform in-depth technical analysis.
* As a trader, I want to quickly switch between different time intervals on the chart so I can analyze price action at various granularities.
* As a trader, I want to easily find and add technical indicators to my chart from a categorized and searchable library so I can customize my analysis.
* As a trader, I want to see a concise, AI-generated summary of market sentiment and key signals for a trading pair so I can quickly gauge its potential.
* As a trader, I want a consistent dark-themed interface that is easy on the eyes and professional-looking so I can focus on my trading analysis.
### 7. Technical Considerations
* **Charting Library:** Integration with a robust and performant charting library capable of rendering complex candlestick charts and indicators (e.g., Lightweight Charts, TradingView Charting Library, or a custom solution).
* **Real-time Data:** Secure and efficient real-time data streaming for price updates, volume, and indicator calculations.
* **Backend Integration:** APIs to fetch market data, integrate AI analysis results, and manage user preferences (e.g., favorited indicators).
* **Performance:** Optimization for smooth scrolling, zooming, and rapid data updates on mobile devices.
* **Cross-platform Development:** Consideration for iOS and Android compatibility.
### 8. Success Metrics
* **Increased Chart Screen Usage:** Monitor daily/monthly active users on the primary chart screen.
* **Indicator Adoption Rate:** Track the frequency of technical indicator additions and usage.
* **AI Insights Engagement:** Measure views and interactions with the AI Analysis Insights screen.
* **User Feedback:** Gather qualitative feedback on UI/UX improvements, particularly concerning the professional look and feel.
* **Retention Rate:** Observe improvements in overall user retention post-launch.
### 9. Out-of-Scope (for this initial phase)
* Detailed Order Book and Depth Chart screens.
* Advanced trade execution functionalities (buy/sell orders, order types).
* Price Alert creation screen.
* Portfolio management and wallet functionalities.
* Social trading features.
These items may be considered for future project phases based on user feedback and business priorities.
### 10. Dependencies & Assumptions
* **Design Resources:** Availability of UI/UX designers for detailed mockups, prototypes, and asset creation.
* **Backend Support:** Existing or developed backend APIs to support real-time data feeds and AI analysis computations.
* **Third-party Integrations:** If using a third-party charting library or AI service, ensure licensing and integration capabilities.
* **User Feedback Loop:** Mechanism for collecting and acting on user feedback post-launch.

View File

@ -0,0 +1,293 @@
<!DOCTYPE html>
<html class="dark" lang="en"><head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<title>Crypto Dashboard - BTC/USD</title>
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<style data-purpose="base-styles">
body {
background-color: #0d1421; /* Match background color from SCREEN_6 indicator panel */
color: #ffffff;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 0;
padding: 0;
-webkit-font-smoothing: antialiased;
}
.text-muted {
color: #8fa2b3; /* Consistent with SCREEN_6 theme */
}
.bg-dark-surface {
background-color: #0d1421;
}
.border-dark {
border-color: #1e293b; /* Deep slate divider color */
}
.bg-card-ai {
background-color: #161e2e; /* AI Analysis theme card background from IMAGE_8 */
border: 1px solid #2d3a4f;
}
</style>
<style data-purpose="chart-customization">
/* Custom grid lines for the chart */
.grid-line {
stroke: #1e293b;
stroke-width: 1;
}
/* Orange color for all candles as requested */
.candle-orange {
fill: #f0b90b;
stroke: #f0b90b;
}
.wick-orange {
stroke: #f0b90b;
stroke-width: 1.5;
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&amp;display=swap" rel="stylesheet"/>
</head>
<body class="flex flex-col h-screen overflow-hidden">
<!-- BEGIN: Top Navigation Bar (Using COMPONENTS_17 TopAppBar logic) -->
<header class="bg-[#0f131e] fixed top-0 w-full z-50 h-16 px-6 flex items-center justify-between border-b border-[#1b1f2b]">
<div class="flex items-center space-x-3 bg-[#1a2333] px-3 py-1.5 rounded-md cursor-pointer border border-[#2d3a4f]">
<span class="material-symbols-outlined text-sm text-[#8fa2b3]">search</span>
<span class="font-bold text-sm text-[#dfe2f2]">BTC/USD</span>
<span class="material-symbols-outlined text-sm text-[#8fa2b3]">chevron_right</span>
</div>
<div class="flex space-x-1 items-center">
<button class="px-2 py-1 text-xs text-[#c3c5d8] hover:bg-[#262a35] transition-colors rounded">1m</button>
<button class="px-2 py-1 text-xs text-[#c3c5d8] hover:bg-[#262a35] transition-colors rounded">5m</button>
<button class="px-2 py-1 text-xs text-[#c3c5d8] hover:bg-[#262a35] transition-colors rounded">15m</button>
<button class="px-2 py-1 text-xs text-[#c3c5d8] hover:bg-[#262a35] transition-colors rounded">1h</button>
<button class="px-2 py-1 text-xs text-[#c3c5d8] hover:bg-[#262a35] transition-colors rounded">4h</button>
<button class="px-2 py-1 text-xs bg-[#2962ff] text-white rounded font-bold">D</button>
</div>
</header>
<!-- BEGIN: Main Content -->
<main class="flex-1 overflow-y-auto pt-16 pb-20">
<!-- BEGIN: Price Statistics -->
<section class="grid grid-cols-4 gap-2 px-4 py-4 border-b border-[#1e293b] bg-[#0d1421]">
<div>
<p class="text-[10px] text-[#8fa2b3] uppercase font-semibold">Price</p>
<p class="text-lg font-bold">70339</p>
</div>
<div>
<p class="text-[10px] text-[#8fa2b3] uppercase font-semibold">Change <span class="text-red-500"></span></p>
<p class="text-lg font-bold text-red-500">-4.84%</p>
</div>
<div>
<p class="text-[10px] text-[#8fa2b3] uppercase font-semibold">High ↗</p>
<p class="text-lg font-bold">74250</p>
</div>
<div>
<p class="text-[10px] text-[#8fa2b3] uppercase font-semibold">Low ↘</p>
<p class="text-lg font-bold">70279</p>
</div>
</section>
<!-- END: Price Statistics -->
<!-- BEGIN: Candlestick Chart -->
<section class="relative w-full bg-[#0d1421] h-[75vh]" data-purpose="chart-container">
<canvas class="w-full h-full" id="tradingChart"></canvas>
<!-- Price Axis Labels -->
<div class="absolute right-0 top-0 bottom-0 w-16 flex flex-col justify-between text-[10px] text-[#8fa2b3] py-4 pointer-events-none">
<span>77500</span>
<span>75000</span>
<span>72500</span>
<div class="bg-red-500 text-white px-1 py-0.5 rounded-l text-[10px]">70339</div>
<span>67500</span>
<span>65000</span>
<span>62500</span>
</div>
<!-- Time Axis Labels -->
<div class="absolute bottom-2 left-4 right-16 flex justify-between text-[10px] text-[#8fa2b3] pointer-events-none">
<span>01/03 01:00</span>
<span>04/03 01:00</span>
<span>09/03 01:00</span>
<span>14/03 01:00</span>
<span>17/03 01:00</span>
</div>
</section>
<!-- END: Candlestick Chart -->
<!-- BEGIN: Technical Analysis Section -->
<section class="px-4 py-6 bg-[#0d1421]">
<h2 class="text-lg font-bold mb-4 flex items-center gap-2">
<span class="material-symbols-outlined text-[#b6c4ff]">analytics</span>
Technical Analysis
</h2>
<div class="grid grid-cols-2 gap-4">
<!-- Best Moving Averages Card -->
<div class="p-4 rounded-xl bg-card-ai" data-purpose="ta-card">
<p class="text-[10px] font-bold text-[#8fa2b3] uppercase mb-4 tracking-wider">Best Moving Averages</p>
<div class="space-y-4">
<div class="flex justify-between items-center">
<span class="text-[#dfe2f2] text-sm font-medium">MA 44</span>
<div class="text-right">
<p class="font-bold text-sm text-[#dfe2f2]">68817.32</p>
<p class="text-[10px] text-green-500">+2.3%</p>
</div>
</div>
<div class="flex justify-between items-center">
<span class="text-[#dfe2f2] text-sm font-medium">MA 125</span>
<div class="text-right">
<p class="font-bold text-sm text-[#dfe2f2]">82087.39</p>
<p class="text-[10px] text-red-500">-14.3%</p>
</div>
</div>
</div>
</div>
<!-- Support / Resistance Card -->
<div class="p-4 rounded-xl bg-card-ai" data-purpose="ta-card">
<p class="text-[10px] font-bold text-[#8fa2b3] uppercase mb-4 tracking-wider">Support / Resistance</p>
<div class="space-y-4">
<div class="flex justify-between items-center">
<span class="text-[#dfe2f2] text-sm font-medium">Resistance</span>
<span class="font-bold text-sm text-right text-[#dfe2f2]">75972</span>
</div>
<div class="flex justify-between items-center">
<span class="text-[#dfe2f2] text-sm font-medium">Support</span>
<span class="font-bold text-sm text-right text-[#dfe2f2]">62983</span>
</div>
</div>
</div>
</div>
</section>
<!-- END: Technical Analysis Section -->
</main>
<!-- END: Main Content -->
<!-- BEGIN: Bottom Tab Navigation (Using COMPONENTS_17 BottomNavBar logic) -->
<nav class="fixed bottom-0 w-full bg-[#0f131e] border-t border-[#434656]/15 flex justify-around items-center h-16 z-50 px-2 shadow-[0px_-4px_12px_rgba(0,0,0,0.3)]">
<div class="flex flex-col items-center justify-center text-[#c3c5d8] hover:text-[#dfe2f2] transition-transform duration-200">
<span class="material-symbols-outlined">show_chart</span>
<span class="text-[11px] font-medium font-['Inter'] mt-1">Markets</span>
</div>
<div class="flex flex-col items-center justify-center text-[#2962ff] dark:text-[#b6c4ff] bg-[#2962ff]/10 rounded-xl px-3 py-1 transition-transform duration-200">
<span class="material-symbols-outlined">candlestick_chart</span>
<span class="text-[11px] font-medium font-['Inter'] mt-1">Chart</span>
</div>
<div class="flex flex-col items-center justify-center text-[#c3c5d8] hover:text-[#dfe2f2] transition-transform duration-200">
<span class="material-symbols-outlined">query_stats</span>
<span class="text-[11px] font-medium font-['Inter'] mt-1">Indicators</span>
</div>
<div class="flex flex-col items-center justify-center text-[#c3c5d8] hover:text-[#dfe2f2] transition-transform duration-200">
<span class="material-symbols-outlined">analytics</span>
<span class="text-[11px] font-medium font-['Inter'] mt-1">Analysis</span>
</div>
<div class="flex flex-col items-center justify-center text-[#c3c5d8] hover:text-[#dfe2f2] transition-transform duration-200">
<span class="material-symbols-outlined">more_horiz</span>
<span class="text-[11px] font-medium font-['Inter'] mt-1">More</span>
</div>
</nav>
<!-- BEGIN: Chart Logic -->
<script data-purpose="chart-rendering"> const canvas = document.getElementById('tradingChart');
const ctx = canvas.getContext('2d');
function drawChart() {
const container = canvas.parentNode;
const rect = container.getBoundingClientRect();
canvas.width = rect.width * window.devicePixelRatio;
canvas.height = rect.height * window.devicePixelRatio;
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
const width = rect.width;
const height = rect.height;
const orange = '#f0b90b';
const gridColor = '#1e293b';
ctx.clearRect(0, 0, width, height);
// Draw Grid
ctx.strokeStyle = gridColor;
ctx.lineWidth = 0.5;
for(let i = 1; i < 8; i++) {
const y = (height / 8) * i;
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(width, y);
ctx.stroke();
}
for(let i = 1; i < 6; i++) {
const x = (width / 6) * i;
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}
// Simulated data points [open, high, low, close]
const data = [
[65000, 66000, 64500, 65500],
[65500, 67000, 65000, 66500],
[66500, 66800, 64000, 64500],
[64500, 65000, 63000, 63500],
[63500, 66000, 63000, 65800],
[65800, 67500, 65500, 67000],
[67000, 69000, 66500, 68500],
[68500, 72000, 68000, 71500],
[71500, 73000, 70000, 72500],
[72500, 72500, 70000, 71000],
[71000, 73500, 70500, 73000],
[73000, 74000, 72000, 73500],
[73500, 76500, 73000, 76000],
[76000, 76500, 69000, 70000],
[70000, 71000, 68000, 68500],
[68500, 70000, 67500, 69500],
[69500, 71000, 66000, 67000],
[67000, 68000, 65000, 66000],
[66000, 68500, 65500, 68000],
[68000, 71500, 67500, 71000],
[71000, 72000, 69000, 69500],
[69500, 70500, 68500, 69000],
[69000, 70000, 68000, 69800],
[69800, 71500, 69500, 71200],
[71200, 73000, 71000, 72500],
[72500, 73500, 72000, 73200],
[73200, 74500, 72500, 73800],
[73800, 73800, 70000, 70339]
];
const minPrice = 61000;
const maxPrice = 78000;
const priceToY = (price) => height - ((price - minPrice) / (maxPrice - minPrice)) * height;
const candleWidth = 8;
const gap = 4;
const startX = 20;
data.forEach((d, i) => {
const x = startX + i * (candleWidth + gap);
const openY = priceToY(d[0]);
const highY = priceToY(d[1]);
const lowY = priceToY(d[2]);
const closeY = priceToY(d[3]);
ctx.strokeStyle = orange;
ctx.fillStyle = orange;
ctx.lineWidth = 1;
// Wick
ctx.beginPath();
ctx.moveTo(x + candleWidth / 2, highY);
ctx.lineTo(x + candleWidth / 2, lowY);
ctx.stroke();
// Body
const bodyHeight = Math.abs(openY - closeY);
const bodyY = Math.min(openY, closeY);
ctx.fillRect(x, bodyY, candleWidth, Math.max(bodyHeight, 1));
});
// Horizontal current price line
const currentPriceY = priceToY(70339);
ctx.setLineDash([4, 4]);
ctx.strokeStyle = 'rgba(239, 68, 68, 0.7)';
ctx.beginPath();
ctx.moveTo(0, currentPriceY);
ctx.lineTo(width, currentPriceY);
ctx.stroke();
ctx.setLineDash([]);
}
window.addEventListener('load', drawChart);
window.addEventListener('resize', drawChart);</script>
</body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

View File

@ -0,0 +1,73 @@
# Design System Strategy: The Nocturnal High-Precision Interface
## 1. Overview & Creative North Star: "The Financial Observatory"
Most trading platforms are cluttered, anxiety-inducing grids of flashing numbers. This design system rejects the "Bloomberg Terminal" chaos in favor of **The Financial Observatory**.
The Creative North Star is **Atmospheric Precision**. We treat the UI not as a flat dashboard, but as a sophisticated, multi-layered digital instrument. By leveraging deep tonal shifts and "glass" depth, we create an environment where the data glows with authority. We move beyond the "standard" dark mode by eliminating harsh borders and using intentional asymmetry to guide the eye toward high-velocity data points.
---
## 2. Colors & Surface Philosophy
The palette is built on a foundation of deep, ink-like navies to reduce eye strain during long trading sessions, accented by high-energy signals.
### Tonal Hierarchy
* **Deep Core (Background):** `#0f131e` (surface-dim). This is the "void" upon which all data sits.
* **The "No-Line" Rule:** We explicitly prohibit 1px solid borders for sectioning. Use background shifts instead.
* *Example:* Place a `surface-container-high` (`#262a35`) panel directly onto a `surface` (`#0f131e`) background. The 4% tonal difference is enough to define the boundary without the "boxed-in" feeling of a line.
* **Surface Nesting:**
* **Level 0 (Background):** `surface` (`#0f131e`)
* **Level 1 (Main Panels):** `surface-container` (`#1b1f2b`)
* **Level 2 (In-Panel Cards/Inputs):** `surface-container-high` (`#262a35`)
* **The Glass & Gradient Rule:** Use `primary-container` (`#2962ff`) with a 15% opacity and a `20px` backdrop-blur for floating modals. This creates a "frosted lens" effect that maintains the user's context of the market moving behind the window.
---
## 3. Typography: Editorial Authority
We use **Inter** as our sole typeface. Its tall x-height provides maximum legibility for dense numerical data.
* **Display Scale (The Pulse):** Use `display-md` (2.75rem) for the primary portfolio balance. It should feel like a headline in a high-end financial magazine—confident and dominant.
* **Title Scale (The Metadata):** `title-sm` (1rem) is the workhorse for asset names (e.g., BTC/USD).
* **Label Scale (The Data):** `label-sm` (0.6875rem) is reserved for micro-data like timestamps or volume. Use `on-surface-variant` (`#c3c5d8`) to keep this information secondary.
* **Intentional Contrast:** Pair a `headline-sm` title with a `label-md` subtitle using `spacing-1` (0.2rem) to create a tight, professional information cluster.
---
## 4. Elevation & Depth: The Layering Principle
We do not use shadows to simulate height; we use light.
* **Ambient Shadows:** For high-priority floating elements (like a "Buy" confirmation), use a diffused shadow: `0px 24px 48px rgba(0, 0, 0, 0.4)`. The shadow color must be the background color, not pure black, to maintain a natural "Nocturnal" feel.
* **The Ghost Border:** If high-contrast accessibility is required, use `outline-variant` (`#434656`) at **15% opacity**. This creates a "suggestion" of a border that guides the eye without cluttering the interface.
* **Signature Textures:** Apply a subtle linear gradient to main Action Buttons—from `primary` (`#b6c4ff`) to `primary-container` (`#2962ff`). This creates a convex "lens" feel that makes the CTA feel tactile and premium.
---
## 5. Components: Precision Instruments
### Buttons
* **Primary (The Execution):** Rounded `DEFAULT` (0.5rem). Background: `primary-container`. Text: `on-primary-container`. Use the gradient texture mentioned above.
* **Tertiary (The Ghost):** No background. Use `primary` text. This is for secondary actions like "View History."
### Input Fields
* **The "Deep Well" Look:** Background: `surface-container-lowest` (`#0a0e19`). No border. Roundness: `sm` (0.25rem). On focus, the background shifts to `surface-container-high`.
* **Error State:** Use `error` (`#ffb4ab`) only for the helper text and a 1px `error_container` "Ghost Border."
### Trading Cards & Lists
* **Strict No-Divider Rule:** Never use a horizontal line to separate assets in a watchlist. Use `spacing-4` (0.9rem) of vertical white space and a subtle background hover state (`surface-bright`) to define the row.
* **Market Chips:** Use `tertiary-container` (`#a46000`) for "Warning" or "Limit Order" states to provide a sophisticated orange that doesn't feel like a cheap "Alert" icon.
### Additional Trading Components
* **The Ticker Tape:** A seamless, edge-to-edge `surface-container-lowest` bar at the top of the UI. Use `label-md` for price movement, utilizing `tertiary` for neutral/warning moves and `primary` for positive growth.
---
## 6. Dos and Donts
### Do
* **Do** use `surface-container-highest` for "Active" states (e.g., a selected tab).
* **Do** allow charts to breathe. Use `spacing-10` (2.25rem) as a minimum margin between a chart and its control panels.
* **Do** use the `full` (9999px) roundness for pill-shaped "Status" indicators (e.g., "Market Open").
### Don't
* **Don't** use pure white (`#FFFFFF`) for body text. Always use `on-surface` (`#dfe2f2`) to prevent retinal burn-in on OLED screens.
* **Don't** use more than one `display-lg` element per screen. It diminishes the "High-End Editorial" hierarchy.
* **Don't** use standard "Success Green." This system relies on the blue-to-orange `primary` and `tertiary` scales to maintain its unique visual signature.