From 5c9a32fc4dfb956a6eb01900907202e232f18781 Mon Sep 17 00:00:00 2001 From: HoseinBaseri Date: Thu, 16 Jan 2025 16:15:19 +0330 Subject: [PATCH 01/12] add color utility functions and Tailwind CSS configuration --- lib/global.css | 18 +++ lib/store/options.store.ts | 6 + lib/utils/color/constants.ts | 46 ++++++ lib/utils/color/createSwatches.ts | 79 +++++++++++ lib/utils/color/helpers.ts | 229 ++++++++++++++++++++++++++++++ lib/utils/color/scales.ts | 90 ++++++++++++ lib/utils/color/setupColors.ts | 40 ++++++ lib/utils/color/types.ts | 25 ++++ package.json | 3 + pnpm-lock.yaml | 64 +++++++++ tailwind.config.js | 22 ++- 11 files changed, 619 insertions(+), 3 deletions(-) create mode 100644 lib/utils/color/constants.ts create mode 100644 lib/utils/color/createSwatches.ts create mode 100644 lib/utils/color/helpers.ts create mode 100644 lib/utils/color/scales.ts create mode 100644 lib/utils/color/setupColors.ts create mode 100644 lib/utils/color/types.ts diff --git a/lib/global.css b/lib/global.css index f8b272e..ff58868 100644 --- a/lib/global.css +++ b/lib/global.css @@ -1,5 +1,23 @@ @import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap'); +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --mts-primary-50: 233 251 240; + --mts-primary-100: 207 247 222; + --mts-primary-200: 159 239 188; + --mts-primary-300: 111 230 155; + --mts-primary-400: 64 222 122; + --mts-primary-500: 34 197 94; + --mts-primary-600: 27 157 75; + --mts-primary-700: 20 117 56; + --mts-primary-800: 13 78 37; + --mts-primary-900: 7 39 19; + --mts-primary-950: 4 22 10; +} + .mts-default { --border-color: #f4f4f5; --primary-color: #22c55e; diff --git a/lib/store/options.store.ts b/lib/store/options.store.ts index 0b46ef9..a206b2f 100644 --- a/lib/store/options.store.ts +++ b/lib/store/options.store.ts @@ -5,6 +5,7 @@ import { useSwapStore } from './swap.store'; import { MyTonSwapClient } from '@mytonswap/sdk'; import { WIDGET_VERSION } from '../constants'; import { useWalletStore } from './wallet.store'; +import { setupColors } from '../utils/color/setupColors'; export type SwapOptions = { default_pay_token?: string; @@ -24,6 +25,7 @@ export type SwapOptions = { | 'omniston'; layout_direction?: 'ltr' | 'rtl'; ui_preferences?: { + primary_color?: string; disable_provided_text?: boolean; show_swap_details?: boolean; show_settings_wallet?: boolean; @@ -52,6 +54,7 @@ export const useOptionsStore = create( options: { liquidity_provider: 'mytonswap', ui_preferences: { + primary_color: '#22C55E', disable_provided_text: false, disable_token_select_pay: false, disable_token_select_receive: false, @@ -68,6 +71,9 @@ export const useOptionsStore = create( setOptions: (option) => { const { options, userOptions } = get(); if (JSON.stringify(option) === JSON.stringify(userOptions)) return; + if (option.ui_preferences?.primary_color) { + setupColors(option.ui_preferences.primary_color); + } const newSchema = defaultsDeep( option, options diff --git a/lib/utils/color/constants.ts b/lib/utils/color/constants.ts new file mode 100644 index 0000000..5d5cc3f --- /dev/null +++ b/lib/utils/color/constants.ts @@ -0,0 +1,46 @@ +import type { Mode, PaletteConfig } from './types'; + +export const DEFAULT_STOP = 500; +export const DEFAULT_STOPS = [ + 0, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950, 1000, +]; + +export const MODES: Mode[] = [`hex`, `p-3`, 'oklch']; +export const DEFAULT_MODE = MODES[0]; + +export const DEFAULT_PALETTE_CONFIG: PaletteConfig = { + id: ``, + name: ``, + value: ``, + valueStop: DEFAULT_STOP, + swatches: [], + h: 0, + s: 0, + lMin: 0, + lMax: 100, + useLightness: true, + mode: MODES[0], +}; + +export const RANDOM_PALETTES = [ + { + name: `blue`, + value: `3B82F6`, + }, + { + name: `red`, + value: `EF4444`, + }, + { + name: `green`, + value: `22C55E`, + }, + { + name: `purple`, + value: `A855F7`, + }, + { + name: `brand`, + value: `2522FC`, + }, +]; diff --git a/lib/utils/color/createSwatches.ts b/lib/utils/color/createSwatches.ts new file mode 100644 index 0000000..30e07e3 --- /dev/null +++ b/lib/utils/color/createSwatches.ts @@ -0,0 +1,79 @@ +import { DEFAULT_PALETTE_CONFIG } from './constants'; +import { + clamp, + hexToHSL, + HSLToHex, + lightnessFromHSLum, + luminanceFromHex, + unsignedModulo, +} from './helpers'; +import { + createDistributionValues, + createHueScale, + createSaturationScale, +} from './scales'; +import type { PaletteConfig } from './types'; + +export function createSwatches(palette: PaletteConfig) { + const { value, valueStop } = palette; + + // Tweaks may be passed in, otherwise use defaults + const useLightness = + palette.useLightness ?? DEFAULT_PALETTE_CONFIG.useLightness; + const h = palette.h ?? DEFAULT_PALETTE_CONFIG.h; + const s = palette.s ?? DEFAULT_PALETTE_CONFIG.s; + const lMin = palette.lMin ?? DEFAULT_PALETTE_CONFIG.lMin; + const lMax = palette.lMax ?? DEFAULT_PALETTE_CONFIG.lMax; + + // Create hue and saturation scales based on tweaks + const hueScale = createHueScale(h, valueStop); + const saturationScale = createSaturationScale(s, valueStop); + + // Get the base hex's H/S/L values + const { h: valueH, s: valueS, l: valueL } = hexToHSL(value); + + // Create lightness scales based on tweak + lightness/luminance of current value + const lightnessValue = useLightness ? valueL : luminanceFromHex(value); + const distributionScale = createDistributionValues( + lMin, + lMax, + lightnessValue, + valueStop + ); + + const swatches = hueScale.map(({ stop }, stopIndex) => { + const newH = unsignedModulo(valueH + hueScale[stopIndex].tweak, 360); + const newS = clamp(valueS + saturationScale[stopIndex].tweak, 0, 100); + let newL = useLightness + ? distributionScale[stopIndex].tweak + : lightnessFromHSLum( + newH, + newS, + distributionScale[stopIndex].tweak + ); + newL = clamp(newL, 0, 100); + + const newHex = HSLToHex(newH, newS, newL); + + return { + stop, + // Sometimes the initial value is changed slightly during conversion, + // overriding that with the original value + hex: + stop === valueStop + ? `#${value.toUpperCase()}` + : newHex.toUpperCase(), + // Used in graphs + h: newH, + hScale: + ((unsignedModulo(hueScale[stopIndex].tweak + 180, 360) - 180) / + 180) * + 50, + s: newS, + sScale: newS - 50, + l: newL, + }; + }); + + return swatches; +} diff --git a/lib/utils/color/helpers.ts b/lib/utils/color/helpers.ts new file mode 100644 index 0000000..9ab4a2e --- /dev/null +++ b/lib/utils/color/helpers.ts @@ -0,0 +1,229 @@ +import { DEFAULT_PALETTE_CONFIG } from './constants'; + +export function luminanceFromRGB(r: number, g: number, b: number) { + // Formula from WCAG 2.0 + const [R, G, B] = [r, g, b].map(function (c) { + c /= 255; // to 0-1 range + return c < 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); + }); + return 21.26 * R + 71.52 * G + 7.22 * B; +} + +export function luminanceFromHex(H: string) { + const values: [number, number, number] = Object.values(hexToRGB(H)).map( + (item) => Number(item) + ) as [number, number, number]; + return round(luminanceFromRGB(...values), 2); +} + +// TODO: Even out this function, luminance values aren't linear/good +export function lightnessFromHSLum(H: number, S: number, Lum: number) { + const vals: { [key: number]: number } = {}; + for (let L = 99; L >= 0; L--) { + const values: [number, number, number] = Object.values( + HSLtoRGB(H, S, L) + ) as [number, number, number]; + vals[L] = Math.abs(Lum - luminanceFromRGB(...values)); + } + + // Run through all these and find the closest to 0 + let lowestDiff = 100; + let newL = 100; + for (let i = Object.keys(vals).length - 1; i >= 0; i--) { + if (vals[i] < lowestDiff) { + newL = i; + lowestDiff = vals[i]; + } + } + + return newL; +} + +export function hexToRGB(H: string) { + if (H.length === 6 && !H.startsWith(`#`)) { + H = `#${H}`; + } + + let r = `0`; + let g = `0`; + let b = `0`; + if (H.length === 4) { + r = `0x${H[1]}${H[1]}`; + g = `0x${H[2]}${H[2]}`; + b = `0x${H[3]}${H[3]}`; + } else if (H.length === 7) { + r = `0x${H[1]}${H[2]}`; + g = `0x${H[3]}${H[4]}`; + b = `0x${H[5]}${H[6]}`; + } + + return { r, g, b }; +} + +export function hexToHSL(H: string) { + if (H.length === 6 && !H.startsWith(`#`)) { + H = `#${H}`; + } + + // Convert hex to RGB first + const rgbValues = hexToRGB(H); + let { r, g, b } = { + r: parseInt(rgbValues.r), + g: parseInt(rgbValues.g), + b: parseInt(rgbValues.b), + }; + // Then to HSL + r /= 255; + g /= 255; + b /= 255; + const cmin = Math.min(r, g, b); + const cmax = Math.max(r, g, b); + const delta = cmax - cmin; + let h = 0; + let s = 0; + let l = 0; + + if (delta === 0) h = 0; + else if (cmax === r) h = ((g - b) / delta) % 6; + else if (cmax === g) h = (b - r) / delta + 2; + else h = (r - g) / delta + 4; + + h = Math.round(h * 60); + + if (h < 0) h += 360; + + l = (cmax + cmin) / 2; + s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1)); + s = +(s * 100).toFixed(1); + l = +(l * 100).toFixed(1); + + // return `hsl(${h},${s}%,${l}%)`; + return { h, s, l }; +} + +export function HSLtoRGB(h: number, s: number, l: number) { + s = clamp(s, 0, 100) / 100; + l = clamp(l, 0, 100) / 100; + + const c = (1 - Math.abs(2 * l - 1)) * s; + const x = c * (1 - Math.abs(((h / 60) % 2) - 1)); + const m = l - c / 2; + let r = 0; + let g = 0; + let b = 0; + + if (h >= 0 && h < 60) { + r = c; + g = x; + b = 0; + } else if (h >= 60 && h < 120) { + r = x; + g = c; + b = 0; + } else if (h >= 120 && h < 180) { + r = 0; + g = c; + b = x; + } else if (h >= 180 && h < 240) { + r = 0; + g = x; + b = c; + } else if (h >= 240 && h < 300) { + r = x; + g = 0; + b = c; + } else if (h >= 300 && h < 360) { + r = c; + g = 0; + b = x; + } + + return { + r: Math.round((r + m) * 255), + g: Math.round((g + m) * 255), + b: Math.round((b + m) * 255), + }; +} + +export function HSLToHex(h: number, s: number, l: number) { + const rgbValues = HSLtoRGB(h, s, l); + let { r, g, b } = { + r: '', + g: '', + b: '', + }; + + // Having obtained RGB, convert channels to hex + r = rgbValues.r.toString(16); + g = rgbValues.g.toString(16); + b = rgbValues.b.toString(16); + + // Prepend 0s, if necessary + if (r.length === 1) r = `0${r}`; + if (g.length === 1) g = `0${g}`; + if (b.length === 1) b = `0${b}`; + + return `#${r}${g}${b}`; +} + +export function isHex(value: string) { + const valueHex = + value.length === 6 && !value.startsWith(`#`) ? `#${value}` : value; + + const re = new RegExp(/^#[0-9A-F]{6}$/i); + + return re.test(valueHex.toUpperCase()); +} + +export function isValidName(name: string) { + const re = new RegExp(/^[A-Za-z]{3,24}$/i); + + return re.test(name); +} + +export function round(value: number, precision: number = 0) { + const multiplier = Math.pow(10, precision); + return Math.round(value * multiplier) / multiplier; +} + +export function removeTrailingSlash(s: string) { + return s.endsWith('/') ? s.slice(0, -1) : s; +} + +export function titleCase(s: string) { + return s.charAt(0).toUpperCase() + s.slice(1); +} + +export function arrayObjectDiff( + before: { [key: string]: string | number | boolean }[], + current: { [key: string]: string | number | boolean }[] +) { + const defaultKeys = Object.keys(DEFAULT_PALETTE_CONFIG); + + // TODO: Fix this TS string-key-nonsense + const changedKeys: (string | null)[] = defaultKeys + .map((key) => { + const beforeValues = before + .map((p) => p[key]) + .sort() + .join(); + + const currentValues = current + .map((p) => p[key]) + .sort() + .join(); + + return beforeValues === currentValues ? null : key; + }) + .filter(Boolean); + + return changedKeys; +} + +export function unsignedModulo(x: number, n: number) { + return ((x % n) + n) % n; +} + +export function clamp(x: number, min: number, max: number) { + return Math.min(Math.max(x, min), max); +} diff --git a/lib/utils/color/scales.ts b/lib/utils/color/scales.ts new file mode 100644 index 0000000..809759c --- /dev/null +++ b/lib/utils/color/scales.ts @@ -0,0 +1,90 @@ +import { DEFAULT_STOP, DEFAULT_STOPS } from './constants'; + +export function createSaturationScale( + tweak: number = 0, + stop: number = DEFAULT_STOP +) { + const stops = DEFAULT_STOPS; + const index = stops.indexOf(stop); + + if (index === -1) { + throw new Error(`Invalid key value: ${stop}`); + } + + return stops.map((stop) => { + const diff = Math.abs(stops.indexOf(stop) - index); + const tweakValue = tweak + ? Math.round((diff + 1) * tweak * (1 + diff / 10)) + : 0; + + if (tweakValue > 100) { + return { stop, tweak: 100 }; + } + + return { stop, tweak: tweakValue }; + }); +} + +export function createHueScale(tweak: number = 0, stop: number = DEFAULT_STOP) { + const stops = DEFAULT_STOPS; + const index = stops.indexOf(stop); + + if (index === -1) { + throw new Error(`Invalid parameter value: ${stop}`); + } + + return stops.map((stop) => { + const diff = Math.abs(stops.indexOf(stop) - index); + const tweakValue = tweak ? diff * tweak : 0; + + return { stop, tweak: tweakValue }; + }); +} + +export function createDistributionValues( + min: number = 0, + max: number = 100, + lightness: number, + stop: number = DEFAULT_STOP +) { + const stops = DEFAULT_STOPS; + + // Create known stops + const newValues = [ + { stop: 0, tweak: max }, + { stop, tweak: lightness }, + { stop: 1000, tweak: min }, + ]; + + // Create missing stops + for (let i = 0; i < stops.length; i++) { + const stopValue = stops[i]; + + if (stopValue === 0 || stopValue === 1000 || stopValue === stop) { + continue; + } + + const diff = Math.abs((stopValue - stop) / 100); + const totalDiff = + stopValue < stop + ? Math.abs( + stops.indexOf(stop) - stops.indexOf(DEFAULT_STOPS[0]) + ) - 1 + : Math.abs( + stops.indexOf(stop) - + stops.indexOf(DEFAULT_STOPS[DEFAULT_STOPS.length - 1]) + ) - 1; + const increment = stopValue < stop ? max - lightness : lightness - min; + + const tweak = + stopValue < stop + ? (increment / totalDiff) * diff + lightness + : lightness - (increment / totalDiff) * diff; + + newValues.push({ stop: stopValue, tweak: Math.round(tweak) }); + } + + newValues.sort((a, b) => a.stop - b.stop); + + return newValues; +} diff --git a/lib/utils/color/setupColors.ts b/lib/utils/color/setupColors.ts new file mode 100644 index 0000000..0b6a5df --- /dev/null +++ b/lib/utils/color/setupColors.ts @@ -0,0 +1,40 @@ +import { DEFAULT_PALETTE_CONFIG } from './constants'; +import { nanoid } from 'nanoid'; +import { createSwatches } from './createSwatches'; +import Color from 'color'; +export const setupColors = (color_raw: string) => { + try { + const color = Color(color_raw).hex(); + const pallet = createSwatches({ + ...DEFAULT_PALETTE_CONFIG, + id: nanoid(), + + value: color.replace('#', '').toUpperCase(), + swatches: [], + }).map((item) => item.hex); + + // Remove the first and last item + const modifiedPallet = pallet.slice(1, -1); + const cssVariableKeys = [ + '--mts-primary-50', + '--mts-primary-100', + '--mts-primary-200', + '--mts-primary-300', + '--mts-primary-400', + '--mts-primary-500', + '--mts-primary-600', + '--mts-primary-700', + '--mts-primary-800', + '--mts-primary-900', + '--mts-primary-950', + ]; + modifiedPallet.map((item, idx) => { + document.documentElement.style.setProperty( + cssVariableKeys[idx], + Color(item).rgb().array().join(' ') + ); + }); + } catch (error) { + console.log(error); + } +}; diff --git a/lib/utils/color/types.ts b/lib/utils/color/types.ts new file mode 100644 index 0000000..6ebc06d --- /dev/null +++ b/lib/utils/color/types.ts @@ -0,0 +1,25 @@ +export interface SwatchValue { + hex: string; + stop: number; + h: number; + hScale: number; + s: number; + sScale: number; + l: number; +} + +export type Mode = `hex` | `p-3` | `oklch`; + +export interface PaletteConfig { + id: string; + name: string; + value: string; + valueStop: number; + swatches: SwatchValue[]; + useLightness: boolean; + h: number; + s: number; + lMin: number; + lMax: number; + mode: Mode; +} diff --git a/package.json b/package.json index 1ce1a79..a1ac10c 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "@storybook/react": "^8.3.6", "@storybook/react-vite": "^8.3.6", "@storybook/test": "^8.3.6", + "@types/color": "^4.2.0", "@types/lodash": "^4.17.10", "@types/node": "^22.7.4", "@types/react": "^18.3.10", @@ -124,10 +125,12 @@ "@uidotdev/usehooks": "^2.4.1", "axios": "^1.7.7", "axios-retry": "^4.5.0", + "color": "^4.2.3", "framer-motion": "^11.11.2", "i18next": "^23.16.4", "i18next-browser-languagedetector": "^8.0.0", "lodash": "^4.17.21", + "nanoid": "^5.0.9", "react-error-boundary": "^4.1.2", "react-hot-toast": "^2.4.1", "react-i18next": "^15.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f00ca4f..b0e6b15 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: clsx: specifier: ^2.1.1 version: 2.1.1 + color: + specifier: ^4.2.3 + version: 4.2.3 framer-motion: specifier: ^11.11.2 version: 11.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -50,6 +53,9 @@ importers: lodash: specifier: ^4.17.21 version: 4.17.21 + nanoid: + specifier: ^5.0.9 + version: 5.0.9 react: specifier: ^18.3.1 version: 18.3.1 @@ -123,6 +129,9 @@ importers: '@storybook/test': specifier: ^8.3.6 version: 8.3.6(storybook@8.3.6) + '@types/color': + specifier: ^4.2.0 + version: 4.2.0 '@types/lodash': specifier: ^4.17.10 version: 4.17.10 @@ -1392,6 +1401,15 @@ packages: '@types/body-parser@1.19.5': resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + '@types/color-convert@2.0.4': + resolution: {integrity: sha512-Ub1MmDdyZ7mX//g25uBAoH/mWGd9swVbt8BseymnaE18SU4po/PjmCrHxqIIRjBo3hV/vh1KGr0eMxUhp+t+dQ==} + + '@types/color-name@1.1.5': + resolution: {integrity: sha512-j2K5UJqGTxeesj6oQuGpMgifpT5k9HprgQd8D1Y0lOFqKHl3PJu5GMeS4Y5EgjS55AE6OQxf8mPED9uaGbf4Cg==} + + '@types/color@4.2.0': + resolution: {integrity: sha512-6+xrIRImMtGAL2X3qYkd02Mgs+gFGs+WsK0b7VVMaO4mYRISwyTjcqNrO0mNSmYEoq++rSLDB2F5HDNmqfOe+A==} + '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} @@ -2017,6 +2035,13 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} @@ -2818,6 +2843,9 @@ packages: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -3214,6 +3242,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@5.0.9: + resolution: {integrity: sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==} + engines: {node: ^18 || >=20} + hasBin: true + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -3831,6 +3864,9 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + slice-ansi@3.0.0: resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} engines: {node: '>=8'} @@ -5655,6 +5691,16 @@ snapshots: '@types/connect': 3.4.38 '@types/node': 22.7.4 + '@types/color-convert@2.0.4': + dependencies: + '@types/color-name': 1.1.5 + + '@types/color-name@1.1.5': {} + + '@types/color@4.2.0': + dependencies: + '@types/color-convert': 2.0.4 + '@types/connect@3.4.38': dependencies: '@types/node': 22.7.4 @@ -6366,6 +6412,16 @@ snapshots: color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + colorette@2.0.20: {} combined-stream@1.0.8: @@ -7277,6 +7333,8 @@ snapshots: call-bind: 1.0.7 has-tostringtag: 1.0.2 + is-arrayish@0.3.2: {} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 @@ -7612,6 +7670,8 @@ snapshots: nanoid@3.3.7: {} + nanoid@5.0.9: {} + natural-compare@1.4.0: {} negotiator@0.6.3: {} @@ -8266,6 +8326,10 @@ snapshots: signal-exit@4.1.0: {} + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + slice-ansi@3.0.0: dependencies: ansi-styles: 4.3.0 diff --git a/tailwind.config.js b/tailwind.config.js index e962d13..a8d1d6d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -2,15 +2,31 @@ export default { content: [ // refrence the library only - "./lib/**/**/*.{js,ts,jsx,tsx}", + './lib/**/**/*.{js,ts,jsx,tsx}', ], theme: { extend: { gridTemplateColumns: { - swapcard: "1fr auto", + swapcard: '1fr auto', + }, + colors: { + 'mts-primary': { + 50: 'rgb(var(--mts-primary-50) / )', + 100: 'rgb(var(--mts-primary-100) / )', + 200: 'rgb(var(--mts-primary-200) / )', + 300: 'rgb(var(--mts-primary-300) / )', + 400: 'rgb(var(--mts-primary-400) / )', + 500: 'rgb(var(--mts-primary-500) / )', + 600: 'rgb(var(--mts-primary-600) / )', + 700: 'rgb(var(--mts-primary-700) / )', + 800: 'rgb(var(--mts-primary-800) / )', + 900: 'rgb(var(--mts-primary-900) / )', + 950: 'rgb(var(--mts-primary-950) / )', + }, }, }, }, plugins: [], - darkMode: "class", + darkMode: 'class', + prefix: 'mts-', }; From cae5b1a73db4f2bd2c64ff62fd7f4bc8a0389010 Mon Sep 17 00:00:00 2001 From: HoseinBaseri Date: Sat, 18 Jan 2025 16:50:55 +0330 Subject: [PATCH 02/12] refactor: update Tailwind CSS configuration and utility functions for improved styling --- lib/components/Header/Header.tsx | 24 +-- lib/components/Header/SettingPopover.tsx | 48 +++--- lib/components/Header/SlippageSetting.tsx | 48 +++--- lib/components/Header/TokensSettings.tsx | 28 ++-- lib/components/Header/Wallet.tsx | 48 +++--- lib/components/Swap/Swap.scss | 14 +- lib/components/Swap/Swap.stories.tsx | 7 + .../SwapButton/ConfirmationModal.tsx | 100 ++++++------ lib/components/SwapButton/Inprogress.tsx | 30 ++-- lib/components/SwapButton/SwapButton.tsx | 13 +- .../SwapButton/WaitingForWallet.tsx | 32 ++-- lib/components/SwapCard/Card.tsx | 142 ++++++++++-------- lib/components/SwapCard/CardButton.tsx | 25 ++- lib/components/SwapCard/CardDialog.tsx | 70 +++++---- lib/components/SwapCard/FavList.tsx | 30 ++-- lib/components/SwapCard/SwapCard.tsx | 15 +- lib/components/SwapCard/Token.tsx | 36 +++-- lib/components/SwapDetails/SwapDetails.tsx | 35 +++-- lib/components/SwapDetails/SwapKeyValue.tsx | 9 +- lib/global.css | 4 +- lib/utils/cn.ts | 8 +- tailwind.config.js | 2 +- 22 files changed, 404 insertions(+), 364 deletions(-) diff --git a/lib/components/Header/Header.tsx b/lib/components/Header/Header.tsx index fd63665..bfe5ada 100644 --- a/lib/components/Header/Header.tsx +++ b/lib/components/Header/Header.tsx @@ -1,10 +1,10 @@ -import SettingPopover from "./SettingPopover"; -import "./Header.scss"; -import { useOptionsStore } from "../../store/options.store"; -import Refresh from "../Common/Refresh"; -import { useSwapStore } from "../../store/swap.store"; -import { useTranslation } from "react-i18next"; -import Setting from "../icons/Setting"; +import SettingPopover from './SettingPopover'; +import './Header.scss'; +import { useOptionsStore } from '../../store/options.store'; +import Refresh from '../Common/Refresh'; +import { useSwapStore } from '../../store/swap.store'; +import { useTranslation } from 'react-i18next'; +import Setting from '../icons/Setting'; const Header = () => { const { t } = useTranslation(); const { options } = useOptionsStore(); @@ -12,12 +12,12 @@ const Header = () => { useSwapStore(); return ( -
-
{t("swap")}
-
+
+
{t('swap')}
+
{options.ui_preferences?.show_refresh && (
{ )} {options.ui_preferences?.show_settings && ( - + )}
diff --git a/lib/components/Header/SettingPopover.tsx b/lib/components/Header/SettingPopover.tsx index f818ec4..ab20b6d 100644 --- a/lib/components/Header/SettingPopover.tsx +++ b/lib/components/Header/SettingPopover.tsx @@ -1,16 +1,16 @@ -import { FC, PropsWithChildren, useRef, useState } from "react"; -import SlippageSetting from "./SlippageSetting"; -import { useOnClickOutside } from "usehooks-ts"; -import TokensSettings from "./TokensSettings"; -import { AnimatePresence, motion } from "framer-motion"; +import { FC, PropsWithChildren, useRef, useState } from 'react'; +import SlippageSetting from './SlippageSetting'; +import { useOnClickOutside } from 'usehooks-ts'; +import TokensSettings from './TokensSettings'; +import { AnimatePresence, motion } from 'framer-motion'; -import "./SettingPopover.scss"; -import Wallet from "./Wallet"; -import { useOptionsStore } from "../../store/options.store"; -import { useTranslation } from "react-i18next"; -import { useMediaQuery } from "@uidotdev/usehooks"; -import { modalAnimationDesktop, modalAnimationMobile } from "../../constants"; -import { IoClose } from "react-icons/io5"; +import './SettingPopover.scss'; +import Wallet from './Wallet'; +import { useOptionsStore } from '../../store/options.store'; +import { useTranslation } from 'react-i18next'; +import { useMediaQuery } from '@uidotdev/usehooks'; +import { modalAnimationDesktop, modalAnimationMobile } from '../../constants'; +import { IoClose } from 'react-icons/io5'; export type SettingPopoverProps = PropsWithChildren & {}; @@ -36,14 +36,18 @@ const SettingPopover: FC = ({ children }) => { const handleCloseSetting = () => { setIsOpen(false); }; - const isDesktop = useMediaQuery("(min-width: 768px)"); + const isDesktop = useMediaQuery('(min-width: 768px)'); const modalAnimation = isDesktop ? modalAnimationDesktop : modalAnimationMobile; return ( -
- @@ -52,23 +56,23 @@ const SettingPopover: FC = ({ children }) => { initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} - transition={{ ease: "easeOut", duration: 0.15 }} - className="modal-backdrop" + transition={{ ease: 'easeOut', duration: 0.15 }} + className="mts-fixed mts-top-0 mts-left-0 mts-bg-black/50 mts-w-full mts-h-full" > -
-
{t("setting")}
+
+
{t('setting')}
diff --git a/lib/components/Header/SlippageSetting.tsx b/lib/components/Header/SlippageSetting.tsx index 4750e1a..1587324 100644 --- a/lib/components/Header/SlippageSetting.tsx +++ b/lib/components/Header/SlippageSetting.tsx @@ -3,6 +3,7 @@ import { AnimatePresence, motion } from 'framer-motion'; import { useSwapStore } from '../../store/swap.store'; import './SlippageSetting.scss'; import { useTranslation } from 'react-i18next'; +import { cn } from '../../utils/cn'; const SlippageSetting = () => { const { t } = useTranslation(); @@ -50,13 +51,13 @@ const SlippageSetting = () => { return (
- diff --git a/lib/components/Header/Wallet.tsx b/lib/components/Header/Wallet.tsx index 7e37044..ef18d0a 100644 --- a/lib/components/Header/Wallet.tsx +++ b/lib/components/Header/Wallet.tsx @@ -1,14 +1,14 @@ -import { fromNano } from "@mytonswap/sdk"; -import { TON_ADDR } from "../../constants"; -import { useWalletStore } from "../../store/wallet.store"; -import "./Wallet.scss"; -import formatNumber from "../../utils/formatNum"; -import shortAddress from "../../utils/shortAddress"; -import { FaCheck, FaCopy } from "react-icons/fa6"; -import { useState } from "react"; -import { MdArrowOutward } from "react-icons/md"; -import { useOptionsStore } from "../../store/options.store"; -import { useTranslation } from "react-i18next"; +import { fromNano } from '@mytonswap/sdk'; +import { TON_ADDR } from '../../constants'; +import { useWalletStore } from '../../store/wallet.store'; +import './Wallet.scss'; +import formatNumber from '../../utils/formatNum'; +import shortAddress from '../../utils/shortAddress'; +import { FaCheck, FaCopy } from 'react-icons/fa6'; +import { useState } from 'react'; +import { MdArrowOutward } from 'react-icons/md'; +import { useOptionsStore } from '../../store/options.store'; +import { useTranslation } from 'react-i18next'; // import { useTonConnectUI } from "@tonconnect/ui-react"; const Wallet = () => { @@ -45,24 +45,24 @@ const Wallet = () => { return ( <> {wallet && ( -
-

{t("account")}

-
-

{t("balance")}

-
+
+

{t('account')}

+
+

{t('balance')}

+
{TON_BALANCE} - {t("ton")} + {t('ton')}
-
-
+
+
{shortAddress( wallet.account.address, - "mainnet", + 'mainnet', 4 )}
@@ -79,10 +79,10 @@ const Wallet = () => {
diff --git a/lib/components/Swap/Swap.scss b/lib/components/Swap/Swap.scss index 75aa7b2..1ada41c 100644 --- a/lib/components/Swap/Swap.scss +++ b/lib/components/Swap/Swap.scss @@ -22,23 +22,13 @@ font-family: 'Plus Jakarta Sans', sans-serif !important; -webkit-tap-highlight-color: transparent; } - button { - cursor: pointer; - border: none; - background: transparent; - font-family: Inter, sans-serif; - } + input { outline: none; border: none; background: none; width: 100%; } - * { - box-sizing: border-box; - margin: 0; - padding: 0; - } .animate-spin { animation: spin 1s linear infinite; @@ -69,7 +59,7 @@ border-style: solid; border-color: var(--swap-container-border-color); border-radius: 1rem; - background: var(--swap-container-background-color); + // background: var(--swap-container-background-color); padding: 0.5rem; max-width: 21.875rem; overflow: hidden; diff --git a/lib/components/Swap/Swap.stories.tsx b/lib/components/Swap/Swap.stories.tsx index 695c47e..2175557 100644 --- a/lib/components/Swap/Swap.stories.tsx +++ b/lib/components/Swap/Swap.stories.tsx @@ -29,6 +29,13 @@ export default meta; type Story = StoryObj; export const Default: Story = { + args: { + options: { + ui_preferences: { + primary_color: '#1971ff', + }, + }, + }, decorators: [ (Story) => (
diff --git a/lib/components/SwapButton/ConfirmationModal.tsx b/lib/components/SwapButton/ConfirmationModal.tsx index d40b151..8dcfef4 100644 --- a/lib/components/SwapButton/ConfirmationModal.tsx +++ b/lib/components/SwapButton/ConfirmationModal.tsx @@ -1,14 +1,13 @@ -import { IoMdClose } from "react-icons/io"; -import { ModalState, useSwapStore } from "../../store/swap.store"; -import { fromNano } from "@mytonswap/sdk"; -import { FaArrowRightArrowLeft } from "react-icons/fa6"; -import SwapKeyValue from "../SwapDetails/SwapKeyValue"; -import formatNumber from "../../utils/formatNum"; -import swap from "../../utils/swap"; -import { FC, useEffect } from "react"; -import "./ConfirmationModal.scss"; -import { useOptionsStore } from "../../store/options.store"; -import { useTranslation } from "react-i18next"; +import { IoMdClose } from 'react-icons/io'; +import { ModalState, useSwapStore } from '../../store/swap.store'; +import { fromNano } from '@mytonswap/sdk'; +import { FaArrowRightArrowLeft } from 'react-icons/fa6'; +import SwapKeyValue from '../SwapDetails/SwapKeyValue'; +import formatNumber from '../../utils/formatNum'; +import swap from '../../utils/swap'; +import { FC, useEffect } from 'react'; +import { useOptionsStore } from '../../store/options.store'; +import { useTranslation } from 'react-i18next'; type ConfirmationModalProps = { setConfirmModal: (state: ModalState) => void; }; @@ -16,7 +15,7 @@ type ConfirmationModalProps = { const ConfirmationModal: FC = ({ setConfirmModal }) => { const { t } = useTranslation(); const handleConfirmClose = () => { - setConfirmModal(ModalState.NONE); + setConfirmModal(ModalState.IN_PROGRESS); }; const { tonConnectInstance } = useOptionsStore(); useEffect(() => { @@ -44,38 +43,43 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => { } }; return ( -
-
- {t("confirm.confirm_title")}{" "} - +
+
+ + {t('confirm.confirm_title')} + {' '} +
-
+
-
+
- {fromNano(pay_amount, pay_token?.decimal)}{" "} + {fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol}
- +
{bestRoute!.pool_data.receive_show!} {receive_token?.symbol}
-
- ≈{" "} +
+ ≈{' '} {formatNumber( Number(bestRoute!.pool_data.receive_show) * receive_rate!.USD, @@ -84,15 +88,15 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => { $
-
+
+
{formatNumber( bestRoute!.pool_data.minimumReceive_show, 4 @@ -102,44 +106,28 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => { } /> - {/* -
- {bestRoute.selected_pool - .dex === "dedust" - ? "Dedust -" - : "Ston.fi -"} -
*/} - {bestRoute.pool_data.route_view.join(" > ")} +
+ {bestRoute.pool_data.route_view.join(' > ')}
) : ( - "Enter amount" + 'Enter amount' ) } />
-
-
diff --git a/lib/components/SwapButton/Inprogress.tsx b/lib/components/SwapButton/Inprogress.tsx index 089c2cd..5c64d75 100644 --- a/lib/components/SwapButton/Inprogress.tsx +++ b/lib/components/SwapButton/Inprogress.tsx @@ -5,7 +5,6 @@ import { Dex, fromNano } from '@mytonswap/sdk'; import { FaArrowRightArrowLeft } from 'react-icons/fa6'; import formatNumber from '../../utils/formatNum'; import { ImSpinner8 } from 'react-icons/im'; -import './Inprogress.scss'; import { useEventsStore } from '../../store/events.store'; import { useTranslation } from 'react-i18next'; @@ -78,34 +77,37 @@ const Inprogress = () => { }; return ( -
- -
+
+ +
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol}
- +
{bestRoute!.pool_data.receive_show!} {receive_token?.symbol}
-
+
≈{' '} {formatNumber( Number(bestRoute!.pool_data.receive_show) * @@ -116,12 +118,14 @@ const Inprogress = () => {
-
{t('transaction.pending')}
-

+

+ {t('transaction.pending')} +
+

{t('transaction.action_in_progress')}

-
- +
+
); diff --git a/lib/components/SwapButton/SwapButton.tsx b/lib/components/SwapButton/SwapButton.tsx index 5e06ba5..2fde65e 100644 --- a/lib/components/SwapButton/SwapButton.tsx +++ b/lib/components/SwapButton/SwapButton.tsx @@ -6,7 +6,6 @@ import ConfirmationModal from './ConfirmationModal'; import WaitingForWallet from './WaitingForWallet'; import Inprogress from './Inprogress'; import Done from './Done'; -import './SwapButton.scss'; import { useMediaQuery } from 'usehooks-ts'; import { modalAnimationDesktop, @@ -39,8 +38,8 @@ const SwapButton = () => { const getSwapText = () => { if (isSelectingToken) return ( - - Loading ... + + Loading ... ); if (!tonConnectInstance?.wallet) return t('button_text.connect_wallet'); @@ -97,11 +96,11 @@ const SwapButton = () => { initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} - className="modal-container" + className="mts-fixed mts-top-0 mts-left-0 mts-z-[9999999999999999999999999] mts-bg-[rgba(0,0,0,0.5)] mts-w-full mts-h-full mts-overflow-hidden" > {
-
- +
+ = ({
{pinnedTokens && ( -
+
{pinnedTokens.map((item) => { return (
{activeTab === TABS.ALL && (
= ({ next={() => onNextPage(page)} scrollableTarget="scroll-div" loader={ -
- +
+
} endMessage={ filteredAssets.length === 0 ? (
{t( 'token_notfound' )} - + {t( 'not_found_desc' )} @@ -412,7 +416,7 @@ const CardDialog: FC = ({
) : (
{t( @@ -444,18 +448,18 @@ const CardDialog: FC = ({ )} {promptForCommunity && ( -
+
{contractCommunity && ( <> -
-
- -

+
+
+ +

{t( 'trade_warning.trade_title' )}

-

+

{t( 'trade_warning.trade_description' )} @@ -474,7 +478,7 @@ const CardDialog: FC = ({ )}

)} -
+
diff --git a/lib/components/SwapCard/FavList.tsx b/lib/components/SwapCard/FavList.tsx index 71dbe2b..5529066 100644 --- a/lib/components/SwapCard/FavList.tsx +++ b/lib/components/SwapCard/FavList.tsx @@ -1,13 +1,13 @@ -import { CSSProperties, FC, useEffect, useState } from "react"; -import { useFavoriteStore } from "../../store/favtorite.store"; -import { useSwapStore } from "../../store/swap.store"; -import { Asset } from "@mytonswap/sdk"; -import Token from "./Token"; -import { CgSpinnerTwo } from "react-icons/cg"; +import { CSSProperties, FC, useEffect, useState } from 'react'; +import { useFavoriteStore } from '../../store/favtorite.store'; +import { useSwapStore } from '../../store/swap.store'; +import { Asset } from '@mytonswap/sdk'; +import Token from './Token'; +import { CgSpinnerTwo } from 'react-icons/cg'; type FavListProps = { onTokenSelect: (asset: Asset) => void; - type: "pay" | "receive"; + type: 'pay' | 'receive'; }; const FavList: FC = ({ onTokenSelect, type }) => { @@ -32,10 +32,10 @@ const FavList: FC = ({ onTokenSelect, type }) => { }, []); return (
= ({ onTokenSelect, type }) => { /> ))} {isLoading && ( -
- +
+
)} {isError && ( -
+
Something went wrong...
)} {!isLoading && !isError && favItems?.length === 0 && ( -
-
No favorite tokens
+
+
+ No favorite tokens +
)}
diff --git a/lib/components/SwapCard/SwapCard.tsx b/lib/components/SwapCard/SwapCard.tsx index 4b9c5d3..eab5be3 100644 --- a/lib/components/SwapCard/SwapCard.tsx +++ b/lib/components/SwapCard/SwapCard.tsx @@ -1,9 +1,8 @@ -import { useSwapStore } from "../../store/swap.store"; -import Card from "./Card"; -import { LuArrowDownUp } from "react-icons/lu"; +import { useSwapStore } from '../../store/swap.store'; +import Card from './Card'; +import { LuArrowDownUp } from 'react-icons/lu'; -import "./SwapCard.scss"; -import { useOptionsStore } from "../../store/options.store"; +import { useOptionsStore } from '../../store/options.store'; const SwapCard = () => { const { changeDirection } = useSwapStore(); const { options } = useOptionsStore(); @@ -13,16 +12,16 @@ const SwapCard = () => { const isDisabled = options.lock_pay_token || options.lock_receive_token; return ( -
+
-
+
{shouldShowChangeDirection && ( - +
-
- )} - + +
+ ) ); }; diff --git a/lib/components/Swap/Swap.scss b/lib/components/Swap/Swap.scss index 1ada41c..417179e 100644 --- a/lib/components/Swap/Swap.scss +++ b/lib/components/Swap/Swap.scss @@ -17,12 +17,6 @@ } .mytonswap-app { - font-family: 'Plus Jakarta Sans', sans-serif; - * { - font-family: 'Plus Jakarta Sans', sans-serif !important; - -webkit-tap-highlight-color: transparent; - } - input { outline: none; border: none; @@ -55,10 +49,10 @@ line-clamp: 1; } .container { - border-width: 1px; - border-style: solid; - border-color: var(--swap-container-border-color); - border-radius: 1rem; + // border-width: 1px; + // border-style: solid; + // border-color: var(--swap-container-border-color); + // border-radius: 1rem; // background: var(--swap-container-background-color); padding: 0.5rem; max-width: 21.875rem; diff --git a/lib/components/Swap/Swap.stories.tsx b/lib/components/Swap/Swap.stories.tsx index 2175557..1f87849 100644 --- a/lib/components/Swap/Swap.stories.tsx +++ b/lib/components/Swap/Swap.stories.tsx @@ -32,7 +32,7 @@ export const Default: Story = { args: { options: { ui_preferences: { - primary_color: '#1971ff', + primary_color: '#f94905', }, }, }, diff --git a/lib/components/Swap/Swap.tsx b/lib/components/Swap/Swap.tsx index 2e96e04..7e4af1b 100644 --- a/lib/components/Swap/Swap.tsx +++ b/lib/components/Swap/Swap.tsx @@ -161,13 +161,17 @@ export const SwapComponent: FC = ({ return ( Something went wrong
}>
-
+
- {shouldShowSwapDetails && } + {shouldShowSwapDetails && } {shouldShowProvidedText && ( -
+
{t('service_provided')}{' '} void; }; @@ -21,16 +21,11 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => { receive_rate, slippage, setModalState, - setErrorMessage, } = useSwapStore(); const { t } = useTranslation(); const handleConfirmClose = () => { - setErrorMessage({ - errorMessage: t('error.cancel_swap'), - errorTitle: t('error.cancel_swap_title'), - }); - setConfirmModal(ModalState.ERROR); + setConfirmModal(ModalState.NONE); }; const { tonConnectInstance } = useOptionsStore(); useEffect(() => { @@ -49,25 +44,24 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => { } }; return ( -
-
- +
+
+ {t('confirm.confirm_title')} {' '} - +
= ({ setConfirmModal }) => { $
-
+
+ {slippage === 'auto' ? '1% Auto' : slippage + '%'} +
+ } /> = ({ setConfirmModal }) => { } />
-
+
diff --git a/lib/components/SwapButton/Done.tsx b/lib/components/SwapButton/Done.tsx index eface52..3f35e04 100644 --- a/lib/components/SwapButton/Done.tsx +++ b/lib/components/SwapButton/Done.tsx @@ -1,10 +1,10 @@ import { FaArrowRightArrowLeft, FaCircleCheck } from 'react-icons/fa6'; -import { IoClose } from 'react-icons/io5'; import { ModalState, useSwapStore } from '../../store/swap.store'; import { fromNano } from '@mytonswap/sdk'; import formatNumber from '../../utils/formatNum'; import './Done.scss'; import { useTranslation } from 'react-i18next'; +import Close from '../icons/Close'; const Done = () => { const { t } = useTranslation(); @@ -16,31 +16,30 @@ const Done = () => { }; return (
- -
+ +
-
+
{t('transaction.complete')}
-
+
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} diff --git a/lib/components/SwapButton/ErrorTonConnect.tsx b/lib/components/SwapButton/ErrorTonConnect.tsx index 9bd806b..18abba6 100644 --- a/lib/components/SwapButton/ErrorTonConnect.tsx +++ b/lib/components/SwapButton/ErrorTonConnect.tsx @@ -1,6 +1,6 @@ import { ModalState, useSwapStore } from '../../store/swap.store'; -import { IoClose } from 'react-icons/io5'; import { IoCloseCircle } from 'react-icons/io5'; +import Close from '../icons/Close'; const ErrorTonConnect = () => { const { transactionError, transactionErrorBody, setModalState } = @@ -15,13 +15,14 @@ const ErrorTonConnect = () => { }; return (
- - -
-

{transactionError}

+ +
+ +
+
+

{transactionError}

{transactionErrorBody}

diff --git a/lib/components/SwapButton/Inprogress.tsx b/lib/components/SwapButton/Inprogress.tsx index 5c64d75..eb702f9 100644 --- a/lib/components/SwapButton/Inprogress.tsx +++ b/lib/components/SwapButton/Inprogress.tsx @@ -4,9 +4,9 @@ import { IoClose } from 'react-icons/io5'; import { Dex, fromNano } from '@mytonswap/sdk'; import { FaArrowRightArrowLeft } from 'react-icons/fa6'; import formatNumber from '../../utils/formatNum'; -import { ImSpinner8 } from 'react-icons/im'; import { useEventsStore } from '../../store/events.store'; import { useTranslation } from 'react-i18next'; +import Spinner from '../icons/Spinner'; const Inprogress = () => { const { t } = useTranslation(); @@ -84,30 +84,30 @@ const Inprogress = () => { />
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol}
- +
{bestRoute!.pool_data.receive_show!} {receive_token?.symbol}
-
+
≈{' '} {formatNumber( Number(bestRoute!.pool_data.receive_show) * @@ -118,14 +118,14 @@ const Inprogress = () => {
-
+
{t('transaction.pending')}

{t('transaction.action_in_progress')}

-
- +
+
); diff --git a/lib/components/SwapButton/SwapButton.tsx b/lib/components/SwapButton/SwapButton.tsx index 2fde65e..df58f41 100644 --- a/lib/components/SwapButton/SwapButton.tsx +++ b/lib/components/SwapButton/SwapButton.tsx @@ -100,7 +100,7 @@ const SwapButton = () => { > { +
+
+
-
+
+
+ {fromNano(pay_amount, pay_token?.decimal)}{' '} + {pay_token?.symbol} +
+
+ +
+
+ {bestRoute!.pool_data.receive_show!} {receive_token?.symbol} +
+
+ ≈{' '} + {formatNumber( + Number(bestRoute!.pool_data.receive_show) * + receive_rate!.USD, + 4 + )} + $ +
+
+ +
{ }} >
-

{t('confirm.action_in_progress')}

+

{t('confirm.action_in_progress')}

+
+ +
); }; diff --git a/lib/components/SwapCard/Card.tsx b/lib/components/SwapCard/Card.tsx index f1beddd..1dbfb08 100644 --- a/lib/components/SwapCard/Card.tsx +++ b/lib/components/SwapCard/Card.tsx @@ -171,56 +171,23 @@ const Card: FC = ({ type }) => { })(); return ( <> -
-
+
+
{type === 'pay' ? t('you_pay') : t('you_receive')} - {type === 'pay' && balanceToken ? ( - - - {t('max')} :{' '} - - - {formatNumber( - +fromNano( - balanceToken.balance, - pay_token!.decimal - ), - 2, - false - )}{' '} - {pay_token?.symbol} - - - ) : ( - - {balanceToken && receive_token && ( - - {formatNumber( - +fromNano( - balanceToken.balance, - receive_token!.decimal - ), - 2, - false - )}{' '} - {receive_token?.symbol} - - )} - - )}
@@ -240,13 +207,13 @@ const Card: FC = ({ type }) => { onChange={handlePayAmountChange} pattern="^[0-9]*[.,]?[0-9]*$" placeholder="0" - className={`mts-outline-none mts-bg-transparent mts-h-7.5 mts-text-black mts-font-bold mts-text-2xl mts-font-inherit ${type}`} + className={`mts-outline-none mts-bg-transparent mts-h-7 mts-text-black mts-font-bold mts-font-inherit mts-text-lg ${type}`} data-testid={`swapcard-input-${type}`} /> )} {type === 'receive' && isFindingBestRoute && (
= ({ type }) => { )} {((type === 'receive' && !isFindingBestRoute) || type === 'pay') && ( - - ${calculatedRate} + + {calculatedRate} $ )} {type === 'receive' && isFindingBestRoute && ( @@ -275,7 +242,7 @@ const Card: FC = ({ type }) => { /> )}
-
+
setIsSelectVisible(true)} @@ -294,6 +261,43 @@ const Card: FC = ({ type }) => {
)} + {type === 'pay' && balanceToken ? ( + + + {formatNumber( + +fromNano( + balanceToken.balance, + pay_token!.decimal + ), + 2, + false + )}{' '} + {pay_token?.symbol} + + + {t('max')} + + + ) : ( + + {balanceToken && receive_token && ( + + {formatNumber( + +fromNano( + balanceToken.balance, + receive_token!.decimal + ), + 2, + false + )}{' '} + {receive_token?.symbol} + + )} + + )}
diff --git a/lib/components/SwapCard/CardButton.tsx b/lib/components/SwapCard/CardButton.tsx index 67d4dae..3ebf3d8 100644 --- a/lib/components/SwapCard/CardButton.tsx +++ b/lib/components/SwapCard/CardButton.tsx @@ -39,7 +39,7 @@ const CardButton: FC = ({ }} data-testid={`card-button-${type}`} className={cn( - 'mts-flex mts-gap-1 mts-items-center mts-transition-all mts-ease-in-out mts-rounded-full mts-py-1 mts-pr-2 mts-pl-1 mts-h-10 mts-font-bold mts-text-2xl mts-ltr mts-bg-zinc-100 mts-text-black', + 'mts-flex mts-gap-1 mts-items-center mts-transition-all mts-ease-in-out mts-rounded-full mts-py-1 mts-pr-2 mts-pl-1 mts-h-10 mts-font-semibold mts-text-sm mts-ltr mts-text-black mts-border-[1px]', isLoading && 'mts-w-20 mts-h-10', type === 'pay' && isLoading && 'mts-pointer-events-none', type === 'receive' && diff --git a/lib/components/SwapCard/CardDialog.tsx b/lib/components/SwapCard/CardDialog.tsx index 611f0f9..daa9cbb 100644 --- a/lib/components/SwapCard/CardDialog.tsx +++ b/lib/components/SwapCard/CardDialog.tsx @@ -8,8 +8,7 @@ import { useRef, useState, } from 'react'; -import { IoClose } from 'react-icons/io5'; -import { MdOutlineSearch } from 'react-icons/md'; + import { AnimatePresence, motion } from 'framer-motion'; import Token from './Token'; import InfiniteScroll from 'react-infinite-scroll-component'; @@ -18,7 +17,6 @@ import { Asset } from '@mytonswap/sdk'; import sortAssets from '../../utils/sortAssets'; import { CgSpinnerTwo } from 'react-icons/cg'; import { address } from '@ton/ton'; -import { TiWarning } from 'react-icons/ti'; import './CardDialog.scss'; import { useMediaQuery, useOnClickOutside } from 'usehooks-ts'; import { modalAnimationDesktop, modalAnimationMobile } from '../../constants'; @@ -27,6 +25,9 @@ import catchError from '../../utils/catchErrors'; import { reportErrorWithToast } from '../../services/errorAnalytics'; import { useTranslation } from 'react-i18next'; import FavList from './FavList'; +import Close from '../icons/Close'; +import Search from '../icons/Search'; +import Warning from '../icons/Warning'; type CardDialogProps = { isSelectVisible: boolean; setIsSelectVisible: Dispatch>; @@ -277,27 +278,27 @@ const CardDialog: FC = ({ animate={modalAnimation.animate} exit={modalAnimation.exit} className={clsx( - 'mts-fixed mts-bottom-0 mts-left-0 mts-flex mts-flex-col mts-shadow-[0px_0px_10px_rgba(0,0,0,0.05)] mts-rounded-t-2xl mts-bg-white mts-p-3 mts-pt-4 mts-pb-2 mts-w-full mts-min-h-[92.5dvh] mts-max-h-[92.5dvh] mts-overflow-y-auto md:mts-shadow-[0_0px_10px_rgba(0,0,0,0.05)] md:mts-rounded-2xl md:mts-w-[90%] md:mts-max-w-[34.375rem] md:mts-h-auto md:mts-min-h-[21.875rem] md:mts-max-h-[70dvh]' + 'mts-fixed mts-bottom-0 mts-left-0 mts-flex mts-flex-col mts-shadow-[0px_0px_10px_rgba(0,0,0,0.05)] mts-rounded-t-2xl mts-bg-white mts-p-4 mts-pt-4 mts-pb-2 mts-w-full mts-min-h-[92.5dvh] mts-max-h-[92.5dvh] mts-overflow-y-auto md:mts-shadow-[0_0px_10px_rgba(0,0,0,0.05)] md:mts-rounded-2xl md:mts-w-[90%] md:mts-max-w-[34.375rem] md:mts-h-auto md:mts-min-h-[21.875rem] md:mts-max-h-[70dvh]' )} ref={ref} onClick={(e) => { e.stopPropagation(); }} > -
+
{t('select_a_token')}
-
- +
+ = ({
diff --git a/lib/components/SwapCard/SwapCard.tsx b/lib/components/SwapCard/SwapCard.tsx index eab5be3..f6c9311 100644 --- a/lib/components/SwapCard/SwapCard.tsx +++ b/lib/components/SwapCard/SwapCard.tsx @@ -12,20 +12,22 @@ const SwapCard = () => { const isDisabled = options.lock_pay_token || options.lock_receive_token; return ( -
+
-
+ {shouldShowChangeDirection && ( - +
+ +
)}
diff --git a/lib/components/SwapCard/Token.tsx b/lib/components/SwapCard/Token.tsx index c204b89..dbeaef7 100644 --- a/lib/components/SwapCard/Token.tsx +++ b/lib/components/SwapCard/Token.tsx @@ -3,7 +3,6 @@ import { useWalletStore } from '../../store/wallet.store'; import { FC } from 'react'; import formatNumber from '../../utils/formatNum'; import './Token.scss'; -import { RiExternalLinkLine } from 'react-icons/ri'; import { PiStarBold, PiStarFill } from 'react-icons/pi'; import { TokenTon } from '../icons/TokenTon'; import { TON_ADDR } from '../../constants'; @@ -11,6 +10,9 @@ import { toFixedDecimal } from '../../utils/toFixedDecimals'; import { useFavoriteStore } from '../../store/favtorite.store'; import clsx from 'clsx'; import { useSwapStore } from '../../store/swap.store'; +import { cn } from '../../utils/cn'; +import Link from '../icons/Link'; +import { useTranslation } from 'react-i18next'; type TokenProps = { asset: Asset; @@ -19,6 +21,7 @@ type TokenProps = { }; const Token: FC = ({ asset, onTokenSelect, type }) => { + const { t } = useTranslation(); const { balance } = useWalletStore(); const { pay_token, receive_token } = useSwapStore(); const { isFav, addToFav, removeFromFav } = useFavoriteStore(); @@ -41,22 +44,22 @@ const Token: FC = ({ asset, onTokenSelect, type }) => { pay_token?.address === asset.address; return ( -
onTokenSelect(asset)} className={clsx( - 'mts-flex mts-items-center mts-cursor-pointer mts-mt-1 mts-rounded-lg mts-px-2 mts-w-full mts-h-12', + 'mts-flex mts-items-center mts-cursor-pointer mts-mt-1 mts-rounded-lg mts-w-full mts-h-12', isSelected && 'mts-opacity-50 mts-cursor-auto' )} data-testid={asset.address} > -
+
-
-
-
+
+ -
+
- {asset.name} + + {asset.name} + {asset.address !== TON_ADDR && ( | {asset.liquidity_text} @@ -85,8 +95,8 @@ const Token: FC = ({ asset, onTokenSelect, type }) => {
@@ -108,7 +118,7 @@ const Token: FC = ({ asset, onTokenSelect, type }) => {
-
+ ); }; diff --git a/lib/components/SwapDetails/SwapDetails.tsx b/lib/components/SwapDetails/SwapDetails.tsx index 06178db..3bab5cc 100644 --- a/lib/components/SwapDetails/SwapDetails.tsx +++ b/lib/components/SwapDetails/SwapDetails.tsx @@ -18,7 +18,7 @@ const SwapDetails = () => { const [ref, { height }] = useMeasure(); return ( { setIsOpen((prev) => !prev); }} @@ -60,16 +60,16 @@ const SwapDetails = () => { height: height ?? 0, }} exit={{ opacity: 0, height: 0 }} - className="mts-flex mts-flex-col mts-gap-1 mts-w-full mts-overflow-hidden" + className="mts-flex mts-flex-col mts-gap-1 mts-w-full mts-overflow-hidden mts-bg-zinc-100 mts-rounded-lg mts-border-zinc-200 mts-border-[1px]" >
+
{slippage === 'auto' ? '1' : slippage}%{' '} {slippage === 'auto' ? t('auto') : ''}
diff --git a/lib/components/SwapDetails/SwapKeyValue.tsx b/lib/components/SwapDetails/SwapKeyValue.tsx index 6f1d021..7e63640 100644 --- a/lib/components/SwapDetails/SwapKeyValue.tsx +++ b/lib/components/SwapDetails/SwapKeyValue.tsx @@ -6,9 +6,9 @@ type SwapKeyValueProps = { const SwapKeyValue: FC = ({ keyText, value }) => { return ( -
-
{keyText}
-
{value}
+
+
{keyText}
+
{value}
); }; diff --git a/lib/components/WalletProfile/WalletProfile.tsx b/lib/components/WalletProfile/WalletProfile.tsx index 7a19e67..931da48 100644 --- a/lib/components/WalletProfile/WalletProfile.tsx +++ b/lib/components/WalletProfile/WalletProfile.tsx @@ -11,6 +11,8 @@ import { AnimatePresence, motion } from 'framer-motion'; import Wallet from '../Header/Wallet'; import { useOnClickOutside } from 'usehooks-ts'; import { popOverVariationsKeyValue } from '../../constants'; +import { useTranslation } from 'react-i18next'; +import { cn } from '../../utils/cn'; export type WalletProfileProps = { tonConnectInstance: TonConnectUI; position?: keyof typeof popOverVariationsKeyValue; @@ -29,7 +31,7 @@ export const WalletProfile: FC = ({ position = 'top-right', }) => { const { setWallet, disconnect, wallet } = useWalletStore(); - + const { t } = useTranslation(); const [isOpen, setIsOpen] = useState(false); const ref = useRef(null); const buttonRef = useRef(null); @@ -68,13 +70,16 @@ export const WalletProfile: FC = ({ return (
{wallet ? shortAddress(wallet.account.address, 'mainnet', 4) - : 'Connect Wallet'} + : t('button_text.connect_wallet')}
@@ -85,9 +90,9 @@ export const WalletProfile: FC = ({ animate={popOverAnimationVariation.animate} transition={{ ease: 'easeOut', duration: 0.15 }} ref={ref} - className="wallet-popover" + className="mts-absolute mts-shadow-lg mts-rounded-xl mts-bg-modal-background-color mts-p-1 mts-min-w-[15.625rem] mts-w-full mts-h-fit mts-text-text-black-color" > - + )} diff --git a/lib/components/icons/Close.tsx b/lib/components/icons/Close.tsx new file mode 100644 index 0000000..420bdb7 --- /dev/null +++ b/lib/components/icons/Close.tsx @@ -0,0 +1,27 @@ +import React, { FC } from 'react'; + +type Props = { + className?: string; +}; + +const Close: FC = ({ className }) => { + return ( + + + + + + + ); +}; + +export default Close; diff --git a/lib/components/icons/Copy.tsx b/lib/components/icons/Copy.tsx new file mode 100644 index 0000000..3cc00ac --- /dev/null +++ b/lib/components/icons/Copy.tsx @@ -0,0 +1,27 @@ +import { FC } from 'react'; + +type Props = { + className?: string; +}; + +const Copy: FC = ({ className }) => { + return ( + + + + + + + ); +}; + +export default Copy; diff --git a/lib/components/icons/Link.tsx b/lib/components/icons/Link.tsx new file mode 100644 index 0000000..f3db6ea --- /dev/null +++ b/lib/components/icons/Link.tsx @@ -0,0 +1,35 @@ +import { FC } from 'react'; + +type Props = { + className?: string; +}; + +const Link: FC = ({ className }) => { + return ( + + + + + + + ); +}; + +export default Link; diff --git a/lib/components/icons/Menu.tsx b/lib/components/icons/Menu.tsx new file mode 100644 index 0000000..87b0c02 --- /dev/null +++ b/lib/components/icons/Menu.tsx @@ -0,0 +1,25 @@ +import { FC } from 'react'; + +type Props = { + className?: string; +}; + +const Menu: FC = ({ className }) => { + return ( + + + + + + + + ); +}; + +export default Menu; diff --git a/lib/components/icons/Refresh.tsx b/lib/components/icons/Refresh.tsx new file mode 100644 index 0000000..3afc08d --- /dev/null +++ b/lib/components/icons/Refresh.tsx @@ -0,0 +1,28 @@ +import { FC } from 'react'; + +type Props = { + className?: string; +}; +const Refresh: FC = ({ className }) => { + return ( + + + + + ); +}; + +export default Refresh; diff --git a/lib/components/icons/Search.tsx b/lib/components/icons/Search.tsx new file mode 100644 index 0000000..96aec9f --- /dev/null +++ b/lib/components/icons/Search.tsx @@ -0,0 +1,24 @@ +import React from 'react'; + +type Props = { + className?: string; +}; + +const Search = ({ className }: Props) => { + return ( + + + + + + + ); +}; + +export default Search; diff --git a/lib/components/icons/Spinner.tsx b/lib/components/icons/Spinner.tsx new file mode 100644 index 0000000..4c1f0ce --- /dev/null +++ b/lib/components/icons/Spinner.tsx @@ -0,0 +1,27 @@ +type Props = { + className?: string; +}; + +const Spinner = ({ className }: Props) => { + return ( + + + + + + + ); +}; + +export default Spinner; diff --git a/lib/components/icons/Warning.tsx b/lib/components/icons/Warning.tsx new file mode 100644 index 0000000..05f5b71 --- /dev/null +++ b/lib/components/icons/Warning.tsx @@ -0,0 +1,29 @@ +import { FC } from 'react'; + +type WarningProps = { + className?: string; +}; + +const Warning: FC = ({ className }) => { + return ( + + + + + + + ); +}; + +export default Warning; diff --git a/lib/global.css b/lib/global.css index 71809f3..5a6b172 100644 --- a/lib/global.css +++ b/lib/global.css @@ -1,4 +1,5 @@ -@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap'); +/* @import url('https://fonts.googleapis.com/css2?family=Fira+Mono:wght@400;500;700&display=swap'); */ +@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap'); @tailwind base; @tailwind components; @@ -85,6 +86,12 @@ --skeleton-shine-color: #585959; } +* { + font-family: 'IBM Plex Mono', sans-serif !important; + /* font-family: 'Fira Mono', sans-serif !important; */ + -webkit-tap-highlight-color: transparent; +} + input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-outer-spin-button { -webkit-appearance: none; @@ -159,7 +166,7 @@ input[type='number']::-webkit-outer-spin-button { transition: color 0.25s ease-in-out; width: 100%; height: auto; - color: rgb(108, 108, 108); + color: #919191; } .refresh_icon { @@ -169,7 +176,7 @@ input[type='number']::-webkit-outer-spin-button { transition: color 0.25s ease-in-out; width: 100%; height: auto; - color: #6c6c6c; + color: #919191; } .icon_overlay.overlay { From 7cfb4b6286c17161d3310db448dccd887bda910d Mon Sep 17 00:00:00 2001 From: HoseinBaseri Date: Wed, 22 Jan 2025 13:47:54 +0330 Subject: [PATCH 05/12] feat: enhance dark mode support and update UI styling across components --- lib/components/Header/Header.tsx | 4 +- lib/components/Header/SettingPopover.tsx | 14 +- lib/components/Header/SlippageSetting.tsx | 127 ++++++++---------- lib/components/Header/TokensSettings.tsx | 10 +- lib/components/Header/Wallet.tsx | 18 +-- lib/components/Swap/Swap.scss | 89 ------------ lib/components/Swap/Swap.stories.tsx | 3 +- lib/components/Swap/Swap.tsx | 18 ++- .../SwapButton/ConfirmationModal.tsx | 10 +- lib/components/SwapButton/Done.tsx | 10 +- lib/components/SwapButton/ErrorTonConnect.tsx | 4 +- lib/components/SwapButton/Inprogress.tsx | 10 +- lib/components/SwapButton/SwapButton.tsx | 4 +- .../SwapButton/WaitingForWallet.tsx | 6 +- lib/components/SwapCard/Card.tsx | 10 +- lib/components/SwapCard/CardButton.tsx | 2 +- lib/components/SwapCard/CardDialog.tsx | 22 +-- lib/components/SwapCard/FavList.tsx | 6 +- lib/components/SwapCard/Token.tsx | 13 +- lib/components/SwapDetails/SwapDetails.tsx | 6 +- lib/components/SwapDetails/SwapKeyValue.tsx | 10 +- lib/i18n/langs/en.json | 2 +- lib/store/options.store.ts | 1 + 23 files changed, 161 insertions(+), 238 deletions(-) diff --git a/lib/components/Header/Header.tsx b/lib/components/Header/Header.tsx index 2967662..9f9c929 100644 --- a/lib/components/Header/Header.tsx +++ b/lib/components/Header/Header.tsx @@ -12,7 +12,7 @@ const Header = () => { useSwapStore(); return ( -
+
{t('swap')}
{options.ui_preferences?.show_refresh && ( @@ -28,7 +28,7 @@ const Header = () => { )} {options.ui_preferences?.show_settings && ( - + )}
diff --git a/lib/components/Header/SettingPopover.tsx b/lib/components/Header/SettingPopover.tsx index 6445de3..df1791d 100644 --- a/lib/components/Header/SettingPopover.tsx +++ b/lib/components/Header/SettingPopover.tsx @@ -10,7 +10,7 @@ import { useOptionsStore } from '../../store/options.store'; import { useTranslation } from 'react-i18next'; import { useMediaQuery } from '@uidotdev/usehooks'; import { modalAnimationDesktop, modalAnimationMobile } from '../../constants'; -import { IoClose } from 'react-icons/io5'; +import Close from '../icons/Close'; export type SettingPopoverProps = PropsWithChildren & {}; @@ -65,16 +65,18 @@ const SettingPopover: FC = ({ children }) => { exit={modalAnimation.exit} transition={{ ease: 'easeOut', duration: 0.15 }} ref={ref} - className="mts-flex mts-fixed mts-bottom-0 mts-left-0 mts-flex-col mts-gap-3 mts-shadow-sm mts-rounded-t-2xl mts-bg-zinc-100 mts-p-4 mts-w-full mts-min-w-60 mts-h-fit mts-text-primary-950 rtl:mts-right-auto rtl:left-0 md:mts-min-w-80 md:mts-max-w-[32.5rem] md:mts-rounded-2xl" + className="mts-flex mts-fixed mts-bottom-0 mts-left-0 mts-flex-col mts-gap-3 mts-shadow-sm mts-rounded-t-2xl mts-bg-zinc-100 dark:mts-bg-zinc-900 mts-p-4 mts-w-full mts-min-w-60 mts-h-fit mts-text-primary-950 rtl:mts-right-auto rtl:left-0 md:mts-min-w-80 md:mts-max-w-[32.5rem] md:mts-rounded-2xl" data-testid="setting-popover" > -
-
{t('setting')}
+
+
+ {t('setting')} +
diff --git a/lib/components/Header/SlippageSetting.tsx b/lib/components/Header/SlippageSetting.tsx index bfd678d..a1cebcd 100644 --- a/lib/components/Header/SlippageSetting.tsx +++ b/lib/components/Header/SlippageSetting.tsx @@ -1,5 +1,4 @@ import { ChangeEvent, useState } from 'react'; -import { AnimatePresence, motion } from 'framer-motion'; import { useSwapStore } from '../../store/swap.store'; import './SlippageSetting.scss'; import { useTranslation } from 'react-i18next'; @@ -51,85 +50,77 @@ const SlippageSetting = () => { return (
- - +
+ {t('auto')} +
+
handleOnPercentClick(2)} + className={cn( + `mts-flex mts-relative mts-justify-center mts-items-center mts-transition-all mts-duration-300 mts-cursor-pointer mts-m-[0.125rem] mts-border-[1px] mts-border-transparent mts-rounded-lg mts-bg-white dark:mts-bg-zinc-800 dark:mts-text-white mts-p-1 mts-h-12 md:mts-h-12`, + slippage === 2 + ? 'mts-border-primary-500' + : 'mts-border-zinc-200 dark:mts-border-zinc-700' + )} + data-testid="slippage-setting-2" > -
- {t('auto')} -
-
handleOnPercentClick(2)} - className={cn( - `mts-flex mts-relative mts-justify-center mts-items-center mts-transition-all mts-duration-300 mts-cursor-pointer mts-m-[0.125rem] mts-border-[1px] mts-border-transparent mts-rounded-lg mts-bg-white mts-p-1 mts-h-12 md:mts-h-10`, - slippage === 2 - ? 'mts-border-primary-500' - : 'mts-border-zinc-200' - )} - data-testid="slippage-setting-2" - > - 2% -
-
handleOnPercentClick(5)} - className={cn( - `mts-flex mts-relative mts-justify-center mts-items-center mts-transition-all mts-duration-300 mts-cursor-pointer mts-m-[0.125rem] mts-border-[1px] mts-border-transparent mts-rounded-lg mts-bg-white mts-p-1 mts-h-12 md:mts-h-10`, - slippage === 5 - ? 'mts-border-primary-500' - : 'mts-border-zinc-200' - )} - data-testid="slippage-setting-5" - > - 5% -
-
- - - % - -
- - + 2% +
+
handleOnPercentClick(5)} + className={cn( + `mts-flex mts-relative mts-justify-center mts-items-center mts-transition-all mts-duration-300 mts-cursor-pointer mts-m-[0.125rem] mts-border-[1px] mts-border-transparent mts-rounded-lg mts-bg-white dark:mts-bg-zinc-800 dark:mts-text-white mts-p-1 mts-h-12 md:mts-h-12`, + slippage === 5 + ? 'mts-border-primary-500' + : 'mts-border-zinc-200 dark:mts-border-zinc-700' + )} + data-testid="slippage-setting-5" + > + 5% +
+
+ + % +
+
); }; diff --git a/lib/components/Header/TokensSettings.tsx b/lib/components/Header/TokensSettings.tsx index 2c80136..f49ca05 100644 --- a/lib/components/Header/TokensSettings.tsx +++ b/lib/components/Header/TokensSettings.tsx @@ -7,15 +7,17 @@ const TokensSettings = () => { const { communityTokens, setCommunityTokens } = useSwapStore(); return (
-
+
{t('community_tokens')}
diff --git a/lib/components/Header/Wallet.tsx b/lib/components/Header/Wallet.tsx index 7dbcebc..2bdb0b1 100644 --- a/lib/components/Header/Wallet.tsx +++ b/lib/components/Header/Wallet.tsx @@ -53,28 +53,30 @@ const Wallet: FC = ({ isWalletPopover }) => {
-

{t('account')}

+

+ {t('account')} +

{t('balance')}

-
+
{TON_BALANCE} {t('ton')}
-
+
{shortAddress( wallet.account.address, 'mainnet', @@ -82,7 +84,7 @@ const Wallet: FC = ({ isWalletPopover }) => { )}
@@ -105,7 +107,7 @@ const Wallet: FC = ({ isWalletPopover }) => {
}> -
+
@@ -171,7 +179,7 @@ export const SwapComponent: FC = ({ {shouldShowSwapDetails && } {shouldShowProvidedText && ( -
+
{t('service_provided')}{' '} = ({ diff --git a/lib/components/SwapButton/ConfirmationModal.tsx b/lib/components/SwapButton/ConfirmationModal.tsx index b83570f..930d4dd 100644 --- a/lib/components/SwapButton/ConfirmationModal.tsx +++ b/lib/components/SwapButton/ConfirmationModal.tsx @@ -44,13 +44,13 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => { } }; return ( -
+
- + {t('confirm.confirm_title')} {' '}
@@ -67,7 +67,7 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => { }} >
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} @@ -92,7 +92,7 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => { +
{slippage === 'auto' ? '1% Auto' : slippage + '%'}
} diff --git a/lib/components/SwapButton/Done.tsx b/lib/components/SwapButton/Done.tsx index 3f35e04..f7b862f 100644 --- a/lib/components/SwapButton/Done.tsx +++ b/lib/components/SwapButton/Done.tsx @@ -15,14 +15,14 @@ const Done = () => { setModalState(ModalState.NONE); }; return ( -
+
-
+
-
+
{t('transaction.complete')}
@@ -39,7 +39,7 @@ const Done = () => { }} >
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} diff --git a/lib/components/SwapButton/ErrorTonConnect.tsx b/lib/components/SwapButton/ErrorTonConnect.tsx index 18abba6..6b29063 100644 --- a/lib/components/SwapButton/ErrorTonConnect.tsx +++ b/lib/components/SwapButton/ErrorTonConnect.tsx @@ -14,11 +14,11 @@ const ErrorTonConnect = () => { setModalState(ModalState.NONE); }; return ( -
+
-
+
diff --git a/lib/components/SwapButton/Inprogress.tsx b/lib/components/SwapButton/Inprogress.tsx index eb702f9..9462413 100644 --- a/lib/components/SwapButton/Inprogress.tsx +++ b/lib/components/SwapButton/Inprogress.tsx @@ -80,7 +80,7 @@ const Inprogress = () => {
{ }} >
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} @@ -118,13 +118,13 @@ const Inprogress = () => {
-
+
{t('transaction.pending')}
-

+

{t('transaction.action_in_progress')}

-
+
diff --git a/lib/components/SwapButton/SwapButton.tsx b/lib/components/SwapButton/SwapButton.tsx index df58f41..de684a8 100644 --- a/lib/components/SwapButton/SwapButton.tsx +++ b/lib/components/SwapButton/SwapButton.tsx @@ -100,7 +100,7 @@ const SwapButton = () => { > {
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} @@ -79,7 +79,7 @@ const WaitingForWallet = () => { >

{t('confirm.action_in_progress')}

-
+
diff --git a/lib/components/SwapCard/Card.tsx b/lib/components/SwapCard/Card.tsx index 1dbfb08..0af64db 100644 --- a/lib/components/SwapCard/Card.tsx +++ b/lib/components/SwapCard/Card.tsx @@ -173,14 +173,14 @@ const Card: FC = ({ type }) => { <>
{type === 'pay' ? t('you_pay') : t('you_receive')} @@ -207,7 +207,7 @@ const Card: FC = ({ type }) => { onChange={handlePayAmountChange} pattern="^[0-9]*[.,]?[0-9]*$" placeholder="0" - className={`mts-outline-none mts-bg-transparent mts-h-7 mts-text-black mts-font-bold mts-font-inherit mts-text-lg ${type}`} + className={`mts-outline-none mts-bg-transparent mts-h-7 mts-w-full mts-text-black dark:mts-text-white mts-font-bold mts-font-inherit mts-text-lg ${type}`} data-testid={`swapcard-input-${type}`} /> )} @@ -225,7 +225,7 @@ const Card: FC = ({ type }) => { )} {((type === 'receive' && !isFindingBestRoute) || type === 'pay') && ( - + {calculatedRate} $ )} @@ -277,7 +277,7 @@ const Card: FC = ({ type }) => { )}{' '} {pay_token?.symbol} - + {t('max')} diff --git a/lib/components/SwapCard/CardButton.tsx b/lib/components/SwapCard/CardButton.tsx index 3ebf3d8..91d8d74 100644 --- a/lib/components/SwapCard/CardButton.tsx +++ b/lib/components/SwapCard/CardButton.tsx @@ -39,7 +39,7 @@ const CardButton: FC = ({ }} data-testid={`card-button-${type}`} className={cn( - 'mts-flex mts-gap-1 mts-items-center mts-transition-all mts-ease-in-out mts-rounded-full mts-py-1 mts-pr-2 mts-pl-1 mts-h-10 mts-font-semibold mts-text-sm mts-ltr mts-text-black mts-border-[1px]', + 'mts-flex mts-gap-1 mts-items-center mts-transition-all mts-ease-in-out mts-rounded-full mts-py-1 mts-pr-2 mts-pl-1 mts-h-10 mts-font-semibold mts-text-sm mts-ltr mts-text-black dark:mts-text-white dark:mts-border-zinc-800 mts-border-[1px]', isLoading && 'mts-w-20 mts-h-10', type === 'pay' && isLoading && 'mts-pointer-events-none', type === 'receive' && diff --git a/lib/components/SwapCard/CardDialog.tsx b/lib/components/SwapCard/CardDialog.tsx index daa9cbb..ba39e71 100644 --- a/lib/components/SwapCard/CardDialog.tsx +++ b/lib/components/SwapCard/CardDialog.tsx @@ -278,24 +278,24 @@ const CardDialog: FC = ({ animate={modalAnimation.animate} exit={modalAnimation.exit} className={clsx( - 'mts-fixed mts-bottom-0 mts-left-0 mts-flex mts-flex-col mts-shadow-[0px_0px_10px_rgba(0,0,0,0.05)] mts-rounded-t-2xl mts-bg-white mts-p-4 mts-pt-4 mts-pb-2 mts-w-full mts-min-h-[92.5dvh] mts-max-h-[92.5dvh] mts-overflow-y-auto md:mts-shadow-[0_0px_10px_rgba(0,0,0,0.05)] md:mts-rounded-2xl md:mts-w-[90%] md:mts-max-w-[34.375rem] md:mts-h-auto md:mts-min-h-[21.875rem] md:mts-max-h-[70dvh]' + 'mts-fixed mts-bottom-0 mts-left-0 mts-flex mts-flex-col mts-shadow-[0px_0px_10px_rgba(0,0,0,0.05)] mts-rounded-t-2xl mts-bg-white dark:mts-bg-zinc-900 mts-p-4 mts-pt-4 mts-pb-2 mts-w-full mts-min-h-[92.5dvh] mts-max-h-[92.5dvh] mts-overflow-y-auto md:mts-shadow-[0_0px_10px_rgba(0,0,0,0.05)] md:mts-rounded-2xl md:mts-w-[90%] md:mts-max-w-[34.375rem] md:mts-h-auto md:mts-min-h-[21.875rem] md:mts-max-h-[70dvh]' )} ref={ref} onClick={(e) => { e.stopPropagation(); }} > -
+
{t('select_a_token')}
-
+
= ({ {pinnedTokens.map((item) => { return ( diff --git a/lib/components/SwapCard/FavList.tsx b/lib/components/SwapCard/FavList.tsx index 5529066..8172f97 100644 --- a/lib/components/SwapCard/FavList.tsx +++ b/lib/components/SwapCard/FavList.tsx @@ -49,17 +49,17 @@ const FavList: FC = ({ onTokenSelect, type }) => { /> ))} {isLoading && ( -
+
)} {isError && ( -
+
Something went wrong...
)} {!isLoading && !isError && favItems?.length === 0 && ( -
+
No favorite tokens
diff --git a/lib/components/SwapCard/Token.tsx b/lib/components/SwapCard/Token.tsx index dbeaef7..f186c28 100644 --- a/lib/components/SwapCard/Token.tsx +++ b/lib/components/SwapCard/Token.tsx @@ -58,7 +58,7 @@ const Token: FC = ({ asset, onTokenSelect, type }) => { style={{ background: `url(${asset.image})` }} >
-
+
{asset.symbol}{' '} @@ -72,21 +72,21 @@ const Token: FC = ({ asset, onTokenSelect, type }) => { {asset.warning && ( -
+
{t('community')}
)}
{tokenBalance}
-
+
{asset.name} {asset.address !== TON_ADDR && ( - | {asset.liquidity_text} + | {asset.liquidity_text ?? 0} )}
@@ -96,8 +96,9 @@ const Token: FC = ({ asset, onTokenSelect, type }) => {
{isTokenFav ? ( diff --git a/lib/components/SwapDetails/SwapDetails.tsx b/lib/components/SwapDetails/SwapDetails.tsx index 3bab5cc..5047dd8 100644 --- a/lib/components/SwapDetails/SwapDetails.tsx +++ b/lib/components/SwapDetails/SwapDetails.tsx @@ -18,7 +18,7 @@ const SwapDetails = () => { const [ref, { height }] = useMeasure(); return ( { setIsOpen((prev) => !prev); }} @@ -60,7 +60,7 @@ const SwapDetails = () => { height: height ?? 0, }} exit={{ opacity: 0, height: 0 }} - className="mts-flex mts-flex-col mts-gap-1 mts-w-full mts-overflow-hidden mts-bg-zinc-100 mts-rounded-lg mts-border-zinc-200 mts-border-[1px]" + className="mts-flex mts-flex-col mts-gap-1 mts-w-full mts-overflow-hidden mts-bg-zinc-100 dark:mts-bg-zinc-900 dark:mts-border-zinc-800 mts-rounded-lg mts-border-zinc-200 mts-border-[1px]" >
{ +
{slippage === 'auto' ? '1' : slippage}%{' '} {slippage === 'auto' ? t('auto') : ''}
diff --git a/lib/components/SwapDetails/SwapKeyValue.tsx b/lib/components/SwapDetails/SwapKeyValue.tsx index 7e63640..17a4c3a 100644 --- a/lib/components/SwapDetails/SwapKeyValue.tsx +++ b/lib/components/SwapDetails/SwapKeyValue.tsx @@ -6,9 +6,13 @@ type SwapKeyValueProps = { const SwapKeyValue: FC = ({ keyText, value }) => { return ( -
-
{keyText}
-
{value}
+
+
+ {keyText} +
+
+ {value} +
); }; diff --git a/lib/i18n/langs/en.json b/lib/i18n/langs/en.json index 351df14..fb5b0ba 100644 --- a/lib/i18n/langs/en.json +++ b/lib/i18n/langs/en.json @@ -2,7 +2,7 @@ "swap": "Swap", "max_slippage": "Max Slippage", "auto": "Auto", - "search": "Search ...", + "search": "Search", "not_found_desc": "Double-check your request and try again", "no_more_tokens": "No more tokens", "service_provided": "Service provided by", diff --git a/lib/store/options.store.ts b/lib/store/options.store.ts index a206b2f..ae4dfec 100644 --- a/lib/store/options.store.ts +++ b/lib/store/options.store.ts @@ -26,6 +26,7 @@ export type SwapOptions = { layout_direction?: 'ltr' | 'rtl'; ui_preferences?: { primary_color?: string; + theme?: 'light' | 'dark'; disable_provided_text?: boolean; show_swap_details?: boolean; show_settings_wallet?: boolean; From 12d0a9eb0de2be87b083bade0f10a70e22e1169c Mon Sep 17 00:00:00 2001 From: HoseinBaseri Date: Wed, 22 Jan 2025 15:32:00 +0330 Subject: [PATCH 06/12] refactor: update component styles for improved responsiveness and consistency --- lib/components/Swap/Swap.tsx | 2 +- .../SwapButton/ConfirmationModal.tsx | 13 ++++++------- lib/components/SwapButton/Done.tsx | 12 +++++------- lib/components/SwapButton/ErrorTonConnect.tsx | 1 - lib/components/SwapButton/Inprogress.tsx | 9 ++++----- lib/components/SwapButton/SwapButton.tsx | 2 +- .../SwapButton/WaitingForWallet.tsx | 19 ++++++------------- lib/components/SwapCard/Card.tsx | 4 ++-- lib/components/SwapCard/CardButton.tsx | 2 +- lib/components/SwapCard/CardDialog.tsx | 4 ++-- lib/components/SwapCard/Token.tsx | 8 ++++---- lib/components/SwapDetails/SwapDetails.tsx | 2 +- 12 files changed, 33 insertions(+), 45 deletions(-) diff --git a/lib/components/Swap/Swap.tsx b/lib/components/Swap/Swap.tsx index 176e10d..8358b90 100644 --- a/lib/components/Swap/Swap.tsx +++ b/lib/components/Swap/Swap.tsx @@ -171,7 +171,7 @@ export const SwapComponent: FC = ({ >
diff --git a/lib/components/SwapButton/ConfirmationModal.tsx b/lib/components/SwapButton/ConfirmationModal.tsx index 930d4dd..6f81bb3 100644 --- a/lib/components/SwapButton/ConfirmationModal.tsx +++ b/lib/components/SwapButton/ConfirmationModal.tsx @@ -18,7 +18,6 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => { pay_token, bestRoute, receive_token, - receive_rate, slippage, setModalState, } = useSwapStore(); @@ -44,7 +43,7 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => { } }; return ( -
+
{t('confirm.confirm_title')} @@ -53,7 +52,7 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => {
-
+
= ({ setConfirmModal }) => { }} >
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} @@ -78,7 +77,7 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => {
{bestRoute!.pool_data.receive_show!} {receive_token?.symbol}
-
+ {/*
≈{' '} {formatNumber( Number(bestRoute!.pool_data.receive_show) * @@ -86,9 +85,9 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => { 4 )} $ -
+
*/}
-
+
{ const { t } = useTranslation(); - const { bestRoute, pay_amount, pay_token, receive_token, receive_rate } = - useSwapStore(); + const { bestRoute, pay_amount, pay_token, receive_token } = useSwapStore(); const { setModalState } = useSwapStore(); const handleCloseModal = () => { setModalState(ModalState.NONE); }; return ( -
+
@@ -39,7 +37,7 @@ const Done = () => { }} >
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} @@ -50,7 +48,7 @@ const Done = () => {
{bestRoute!.pool_data.receive_show!} {receive_token?.symbol}
-
+ {/*
≈{' '} {formatNumber( Number(bestRoute!.pool_data.receive_show) * @@ -58,7 +56,7 @@ const Done = () => { 4 )} $ -
+
*/}
); diff --git a/lib/components/SwapButton/ErrorTonConnect.tsx b/lib/components/SwapButton/ErrorTonConnect.tsx index 6b29063..969d976 100644 --- a/lib/components/SwapButton/ErrorTonConnect.tsx +++ b/lib/components/SwapButton/ErrorTonConnect.tsx @@ -10,7 +10,6 @@ const ErrorTonConnect = () => { transactionError: null, transactionErrorBody: null, }); - // close modal setModalState(ModalState.NONE); }; return ( diff --git a/lib/components/SwapButton/Inprogress.tsx b/lib/components/SwapButton/Inprogress.tsx index 9462413..f786a91 100644 --- a/lib/components/SwapButton/Inprogress.tsx +++ b/lib/components/SwapButton/Inprogress.tsx @@ -3,7 +3,6 @@ import { ModalState, useSwapStore } from '../../store/swap.store'; import { IoClose } from 'react-icons/io5'; import { Dex, fromNano } from '@mytonswap/sdk'; import { FaArrowRightArrowLeft } from 'react-icons/fa6'; -import formatNumber from '../../utils/formatNum'; import { useEventsStore } from '../../store/events.store'; import { useTranslation } from 'react-i18next'; import Spinner from '../icons/Spinner'; @@ -77,7 +76,7 @@ const Inprogress = () => { }; return ( -
+
{ }} >
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} @@ -107,7 +106,7 @@ const Inprogress = () => {
{bestRoute!.pool_data.receive_show!} {receive_token?.symbol}
-
+ {/*
≈{' '} {formatNumber( Number(bestRoute!.pool_data.receive_show) * @@ -115,7 +114,7 @@ const Inprogress = () => { 4 )} $ -
+
*/}
diff --git a/lib/components/SwapButton/SwapButton.tsx b/lib/components/SwapButton/SwapButton.tsx index de684a8..58bec24 100644 --- a/lib/components/SwapButton/SwapButton.tsx +++ b/lib/components/SwapButton/SwapButton.tsx @@ -100,7 +100,7 @@ const SwapButton = () => { > { const { t } = useTranslation(); const { tonConnectInstance } = useOptionsStore(); - const { - pay_amount, - pay_token, - bestRoute, - receive_token, - receive_rate, - setModalState, - } = useSwapStore(); + const { pay_amount, pay_token, bestRoute, receive_token, setModalState } = + useSwapStore(); const handleCloseModal = () => { setModalState(ModalState.NONE); @@ -29,7 +22,7 @@ const WaitingForWallet = () => { initial={{ opacity: 0 }} whileInView={{ opacity: 1 }} exit={{ opacity: 0 }} - className="mts-flex mts-relative mts-flex-col mts-justify-center mts-items-center mts-px-4 mts-h-full mts-text-black dark:mts-text-white" + className="mts-flex mts-relative mts-flex-col mts-w-full mts-justify-center mts-items-center mts-px-4 mts-h-full mts-text-black dark:mts-text-white" >
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} @@ -59,7 +52,7 @@ const WaitingForWallet = () => {
{bestRoute!.pool_data.receive_show!} {receive_token?.symbol}
-
+ {/*
≈{' '} {formatNumber( Number(bestRoute!.pool_data.receive_show) * @@ -67,7 +60,7 @@ const WaitingForWallet = () => { 4 )} $ -
+
*/}
diff --git a/lib/components/SwapCard/Card.tsx b/lib/components/SwapCard/Card.tsx index 0af64db..241f361 100644 --- a/lib/components/SwapCard/Card.tsx +++ b/lib/components/SwapCard/Card.tsx @@ -207,7 +207,7 @@ const Card: FC = ({ type }) => { onChange={handlePayAmountChange} pattern="^[0-9]*[.,]?[0-9]*$" placeholder="0" - className={`mts-outline-none mts-bg-transparent mts-h-7 mts-w-full mts-text-black dark:mts-text-white mts-font-bold mts-font-inherit mts-text-lg ${type}`} + className={`mts-outline-none mts-bg-transparent mts-h-7 mts-w-full mts-text-black dark:mts-text-white mts-font-bold mts-font-inherit mts-text-lg md:mts-text-2xl ${type}`} data-testid={`swapcard-input-${type}`} /> )} @@ -225,7 +225,7 @@ const Card: FC = ({ type }) => { )} {((type === 'receive' && !isFindingBestRoute) || type === 'pay') && ( - + {calculatedRate} $ )} diff --git a/lib/components/SwapCard/CardButton.tsx b/lib/components/SwapCard/CardButton.tsx index 91d8d74..8e785da 100644 --- a/lib/components/SwapCard/CardButton.tsx +++ b/lib/components/SwapCard/CardButton.tsx @@ -39,7 +39,7 @@ const CardButton: FC = ({ }} data-testid={`card-button-${type}`} className={cn( - 'mts-flex mts-gap-1 mts-items-center mts-transition-all mts-ease-in-out mts-rounded-full mts-py-1 mts-pr-2 mts-pl-1 mts-h-10 mts-font-semibold mts-text-sm mts-ltr mts-text-black dark:mts-text-white dark:mts-border-zinc-800 mts-border-[1px]', + 'mts-flex mts-gap-1 mts-items-center mts-transition-all mts-ease-in-out mts-rounded-full mts-py-1 mts-pr-2 mts-pl-1 mts-h-10 mts-font-semibold mts-text-sm md:mts-text-base mts-ltr mts-text-black dark:mts-text-white dark:mts-border-zinc-800 mts-border-[1px]', isLoading && 'mts-w-20 mts-h-10', type === 'pay' && isLoading && 'mts-pointer-events-none', type === 'receive' && diff --git a/lib/components/SwapCard/CardDialog.tsx b/lib/components/SwapCard/CardDialog.tsx index ba39e71..b2141c3 100644 --- a/lib/components/SwapCard/CardDialog.tsx +++ b/lib/components/SwapCard/CardDialog.tsx @@ -295,10 +295,10 @@ const CardDialog: FC = ({
-
+
= ({ asset, onTokenSelect, type }) => {
diff --git a/lib/components/Header/Wallet.tsx b/lib/components/Header/Wallet.tsx index 2bdb0b1..2ecebc4 100644 --- a/lib/components/Header/Wallet.tsx +++ b/lib/components/Header/Wallet.tsx @@ -58,7 +58,7 @@ const Wallet: FC = ({ isWalletPopover }) => { >
@@ -76,7 +76,7 @@ const Wallet: FC = ({ isWalletPopover }) => {
-
+
{shortAddress( wallet.account.address, 'mainnet', diff --git a/lib/components/Swap/Swap.stories.tsx b/lib/components/Swap/Swap.stories.tsx index 4c483e0..55734e5 100644 --- a/lib/components/Swap/Swap.stories.tsx +++ b/lib/components/Swap/Swap.stories.tsx @@ -33,7 +33,6 @@ export const Default: Story = { options: { ui_preferences: { primary_color: '#e82113', - theme: 'light', }, }, }, diff --git a/lib/components/Swap/Swap.tsx b/lib/components/Swap/Swap.tsx index 8358b90..d40ac93 100644 --- a/lib/components/Swap/Swap.tsx +++ b/lib/components/Swap/Swap.tsx @@ -160,15 +160,7 @@ export const SwapComponent: FC = ({ return ( Something went wrong
}> -
+
= ({ setConfirmModal }) => { }} >
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} @@ -91,7 +91,7 @@ const ConfirmationModal: FC = ({ setConfirmModal }) => { +
{slippage === 'auto' ? '1% Auto' : slippage + '%'}
} diff --git a/lib/components/SwapButton/Done.tsx b/lib/components/SwapButton/Done.tsx index a4cff8b..a292bda 100644 --- a/lib/components/SwapButton/Done.tsx +++ b/lib/components/SwapButton/Done.tsx @@ -17,7 +17,7 @@ const Done = () => { -
+
@@ -37,7 +37,7 @@ const Done = () => { }} >
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} diff --git a/lib/components/SwapButton/ErrorTonConnect.tsx b/lib/components/SwapButton/ErrorTonConnect.tsx index 969d976..1a2d5ea 100644 --- a/lib/components/SwapButton/ErrorTonConnect.tsx +++ b/lib/components/SwapButton/ErrorTonConnect.tsx @@ -17,7 +17,7 @@ const ErrorTonConnect = () => { -
+
diff --git a/lib/components/SwapButton/Inprogress.tsx b/lib/components/SwapButton/Inprogress.tsx index f786a91..d98ae5d 100644 --- a/lib/components/SwapButton/Inprogress.tsx +++ b/lib/components/SwapButton/Inprogress.tsx @@ -95,7 +95,7 @@ const Inprogress = () => { }} >
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} @@ -123,7 +123,7 @@ const Inprogress = () => {

{t('transaction.action_in_progress')}

-
+
diff --git a/lib/components/SwapButton/SwapButton.tsx b/lib/components/SwapButton/SwapButton.tsx index 58bec24..a45ad83 100644 --- a/lib/components/SwapButton/SwapButton.tsx +++ b/lib/components/SwapButton/SwapButton.tsx @@ -100,7 +100,7 @@ const SwapButton = () => { > { }} >
-
+
{fromNano(pay_amount, pay_token?.decimal)}{' '} {pay_token?.symbol} @@ -72,7 +72,7 @@ const WaitingForWallet = () => { >

{t('confirm.action_in_progress')}

-
+
diff --git a/lib/components/SwapCard/Card.tsx b/lib/components/SwapCard/Card.tsx index 241f361..d63562d 100644 --- a/lib/components/SwapCard/Card.tsx +++ b/lib/components/SwapCard/Card.tsx @@ -173,7 +173,7 @@ const Card: FC = ({ type }) => { <>
@@ -263,7 +263,7 @@ const Card: FC = ({ type }) => { {type === 'pay' && balanceToken ? ( @@ -277,12 +277,12 @@ const Card: FC = ({ type }) => { )}{' '} {pay_token?.symbol} - + {t('max')} ) : ( - + {balanceToken && receive_token && ( {formatNumber( diff --git a/lib/components/SwapCard/CardButton.tsx b/lib/components/SwapCard/CardButton.tsx index 8e785da..075802a 100644 --- a/lib/components/SwapCard/CardButton.tsx +++ b/lib/components/SwapCard/CardButton.tsx @@ -39,7 +39,7 @@ const CardButton: FC = ({ }} data-testid={`card-button-${type}`} className={cn( - 'mts-flex mts-gap-1 mts-items-center mts-transition-all mts-ease-in-out mts-rounded-full mts-py-1 mts-pr-2 mts-pl-1 mts-h-10 mts-font-semibold mts-text-sm md:mts-text-base mts-ltr mts-text-black dark:mts-text-white dark:mts-border-zinc-800 mts-border-[1px]', + 'mts-flex mts-gap-1 mts-items-center mts-transition-all mts-ease-in-out mts-rounded-full mts-py-1 mts-pr-2 mts-pl-1 mts-h-10 mts-font-semibold mts-text-sm md:mts-text-base mts-ltr mts-text-black dark:mts-text-white mts-border-dark-300 dark:mts-border-dark-800 mts-border-[1px]', isLoading && 'mts-w-20 mts-h-10', type === 'pay' && isLoading && 'mts-pointer-events-none', type === 'receive' && diff --git a/lib/components/SwapCard/CardDialog.tsx b/lib/components/SwapCard/CardDialog.tsx index b2141c3..7318226 100644 --- a/lib/components/SwapCard/CardDialog.tsx +++ b/lib/components/SwapCard/CardDialog.tsx @@ -278,7 +278,7 @@ const CardDialog: FC = ({ animate={modalAnimation.animate} exit={modalAnimation.exit} className={clsx( - 'mts-fixed mts-bottom-0 mts-left-0 mts-flex mts-flex-col mts-shadow-[0px_0px_10px_rgba(0,0,0,0.05)] mts-rounded-t-2xl mts-bg-white dark:mts-bg-zinc-900 mts-p-4 mts-pt-4 mts-pb-2 mts-w-full mts-min-h-[92.5dvh] mts-max-h-[92.5dvh] mts-overflow-y-auto md:mts-shadow-[0_0px_10px_rgba(0,0,0,0.05)] md:mts-rounded-2xl md:mts-w-[90%] md:mts-max-w-[34.375rem] md:mts-h-auto md:mts-min-h-[21.875rem] md:mts-max-h-[70dvh]' + 'mts-fixed mts-bottom-0 mts-left-0 mts-flex mts-flex-col mts-shadow-[0px_0px_10px_rgba(0,0,0,0.05)] mts-rounded-t-2xl mts-bg-white dark:mts-bg-dark-900 mts-p-4 mts-pt-4 mts-pb-2 mts-w-full mts-min-h-[92.5dvh] mts-max-h-[92.5dvh] mts-overflow-y-auto md:mts-shadow-[0_0px_10px_rgba(0,0,0,0.05)] md:mts-rounded-2xl md:mts-w-[90%] md:mts-max-w-[34.375rem] md:mts-h-auto md:mts-min-h-[21.875rem] md:mts-max-h-[70dvh]' )} ref={ref} onClick={(e) => { @@ -295,8 +295,8 @@ const CardDialog: FC = ({
-
- +
+ = ({ {pinnedTokens.map((item) => { return ( diff --git a/lib/components/SwapDetails/SwapDetails.tsx b/lib/components/SwapDetails/SwapDetails.tsx index 376eee9..d14ba79 100644 --- a/lib/components/SwapDetails/SwapDetails.tsx +++ b/lib/components/SwapDetails/SwapDetails.tsx @@ -60,7 +60,7 @@ const SwapDetails = () => { height: height ?? 0, }} exit={{ opacity: 0, height: 0 }} - className="mts-flex mts-flex-col mts-gap-1 mts-w-full mts-overflow-hidden mts-bg-zinc-100 dark:mts-bg-zinc-900 dark:mts-border-zinc-800 mts-rounded-lg mts-border-zinc-200 mts-border-[1px]" + className="mts-flex mts-flex-col mts-gap-1 mts-w-full mts-overflow-hidden mts-bg-dark-100 dark:mts-bg-dark-900 dark:mts-border-dark-800 mts-rounded-lg mts-border-dark-200 mts-border-[1px]" >
{ +
{slippage === 'auto' ? '1' : slippage}%{' '} {slippage === 'auto' ? t('auto') : ''}
diff --git a/lib/components/WalletProfile/WalletProfile.tsx b/lib/components/WalletProfile/WalletProfile.tsx index 931da48..50a453b 100644 --- a/lib/components/WalletProfile/WalletProfile.tsx +++ b/lib/components/WalletProfile/WalletProfile.tsx @@ -72,7 +72,7 @@ export const WalletProfile: FC = ({
( const { options, userOptions } = get(); if (JSON.stringify(option) === JSON.stringify(userOptions)) return; if (option.ui_preferences?.primary_color) { - setupColors(option.ui_preferences.primary_color); + setupColors( + option.ui_preferences.primary_color, + option.ui_preferences.dark_color + ); } const newSchema = defaultsDeep( option, diff --git a/lib/utils/color/setupColors.ts b/lib/utils/color/setupColors.ts index 0b6a5df..2effa5c 100644 --- a/lib/utils/color/setupColors.ts +++ b/lib/utils/color/setupColors.ts @@ -2,7 +2,7 @@ import { DEFAULT_PALETTE_CONFIG } from './constants'; import { nanoid } from 'nanoid'; import { createSwatches } from './createSwatches'; import Color from 'color'; -export const setupColors = (color_raw: string) => { +export const setupColors = (color_raw: string, dark_color_base?: string) => { try { const color = Color(color_raw).hex(); const pallet = createSwatches({ @@ -15,6 +15,7 @@ export const setupColors = (color_raw: string) => { // Remove the first and last item const modifiedPallet = pallet.slice(1, -1); + const cssVariableKeys = [ '--mts-primary-50', '--mts-primary-100', @@ -37,4 +38,40 @@ export const setupColors = (color_raw: string) => { } catch (error) { console.log(error); } + + try { + if (!dark_color_base) return; + const darkColor = Color(dark_color_base).hex(); + const darkPallet = createSwatches({ + ...DEFAULT_PALETTE_CONFIG, + id: nanoid(), + + value: darkColor.replace('#', '').toUpperCase(), + swatches: [], + }).map((item) => item.hex); + + // Remove the first and last item + const modifiedDarkPallet = darkPallet.slice(1, -1); + const darkCssVariableKeys = [ + '--mts-dark-50', + '--mts-dark-100', + '--mts-dark-200', + '--mts-dark-300', + '--mts-dark-400', + '--mts-dark-500', + '--mts-dark-600', + '--mts-dark-700', + '--mts-dark-800', + '--mts-dark-900', + '--mts-dark-950', + ]; + modifiedDarkPallet.map((item, idx) => { + document.documentElement.style.setProperty( + darkCssVariableKeys[idx], + Color(item).rgb().array().join(' ') + ); + }); + } catch (error) { + console.log(error); + } }; diff --git a/tailwind.config.js b/tailwind.config.js index 3046420..98a70a2 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -23,6 +23,19 @@ export default { 900: 'rgb(var(--mts-primary-900) / )', 950: 'rgb(var(--mts-primary-950) / )', }, + dark: { + 50: 'rgb(var(--mts-dark-50) / )', + 100: 'rgb(var(--mts-dark-100) / )', + 200: 'rgb(var(--mts-dark-200) / )', + 300: 'rgb(var(--mts-dark-300) / )', + 400: 'rgb(var(--mts-dark-400) / )', + 500: 'rgb(var(--mts-dark-500) / )', + 600: 'rgb(var(--mts-dark-600) / )', + 700: 'rgb(var(--mts-dark-700) / )', + 800: 'rgb(var(--mts-dark-800) / )', + 900: 'rgb(var(--mts-dark-900) / )', + 950: 'rgb(var(--mts-dark-950) / )', + }, }, }, }, From 3e34795261ba42bf99a47eba1a39904e5c7b11fa Mon Sep 17 00:00:00 2001 From: HoseinBaseri Date: Thu, 30 Jan 2025 10:16:53 +0330 Subject: [PATCH 08/12] refactor: update styling for Swap components to enhance visual consistency and responsiveness --- lib/components/SwapButton/SwapButton.tsx | 2 +- lib/components/SwapCard/Card.tsx | 8 ++++---- lib/components/SwapCard/CardButton.tsx | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/components/SwapButton/SwapButton.tsx b/lib/components/SwapButton/SwapButton.tsx index a45ad83..d586e6d 100644 --- a/lib/components/SwapButton/SwapButton.tsx +++ b/lib/components/SwapButton/SwapButton.tsx @@ -126,7 +126,7 @@ const SwapButton = () => {