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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/components/CardItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const CardItem = ({
{variant === 'input' ? (
<>
<input
id="bluxcc-input"
type={inputType}
value={inputValue}
onChange={handleInputChange}
Expand All @@ -122,7 +123,7 @@ const CardItem = ({
<button
disabled={!isValid}
onClick={() => onSubmit?.(inputValue)}
className={`bluxcc:absolute bluxcc:right-0 bluxcc:flex bluxcc:h-8 bluxcc:w-[68px]! bluxcc:items-center bluxcc:justify-center bluxcc:border bluxcc:!text-sm bluxcc:font-medium bluxcc:transition-[border-radius,background,border-color] bluxcc:duration-150`}
className={`bluxcc:absolute bluxcc:right-0 bluxcc:flex bluxcc:h-8 bluxcc:w-[68px]! bluxcc:items-center bluxcc:justify-center bluxcc:border bluxcc:!text-sm bluxcc:font-medium bluxcc:transition-[border-radius,background,border-color] bluxcc:duration-200`}
style={{
background: appearance.bgField,
borderRadius: appearance.borderRadius,
Expand Down Expand Up @@ -158,7 +159,7 @@ const CardItem = ({

{endArrow && (
<span className="bluxcc:ml-auto bluxcc:flex bluxcc:items-center">
<ArrowRight fill={appearance.textColor} />
<ArrowRight fill={`${hexToRgba(appearance.textColor, 0.7)}`} />
</span>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import { ArrowLeft, Close } from '../../../assets/Icons';
import { useProvider } from '../../../context/provider';
import { ArrowLeft, Close } from '../../assets/Icons';
import { useProvider } from '../../context/provider';
import hexToRgba from '../../utils/hexToRgba';

interface HeaderProps {
icon?: 'info' | 'back';
Expand All @@ -11,7 +12,7 @@ interface HeaderProps {
onClose: () => void;
}

const ModalHeader = ({
const Header = ({
icon,
onInfo,
onBack,
Expand All @@ -20,8 +21,9 @@ const ModalHeader = ({
onClose,
}: HeaderProps) => {
const context = useProvider();
const { appearance } = context.value.config;
return (
<div className="bluxcc:flex bluxcc:h-[60px] bluxcc:w-full bluxcc:items-center bluxcc:justify-between">
<div className="bluxcc:flex bluxcc:w-full bluxcc:items-center bluxcc:justify-between bluxcc:pb-5">
{icon === 'info' ? (
<div
onClick={onInfo}
Expand All @@ -35,19 +37,19 @@ const ModalHeader = ({
onClick={onBack}
className="bluxcc:flex bluxcc:size-5 bluxcc:cursor-pointer bluxcc:items-center bluxcc:justify-center"
>
<ArrowLeft fill={context.value.config.appearance.textColor} />
<ArrowLeft fill={`${hexToRgba(appearance.textColor, 0.7)}`} />
</div>
) : (
<div className="bluxcc:size-5" />
)}

<p className="bluxcc:grow bluxcc:select-none bluxcc:text-center bluxcc:text-base bluxcc:font-medium">
<p className="bluxcc:grow bluxcc:text-center bluxcc:text-base bluxcc:font-medium bluxcc:select-none">
{title}
</p>

{closeButton ? (
<div onClick={onClose} className="bluxcc:size-5 bluxcc:cursor-pointer">
<Close fill={context.value.config.appearance.textColor} />
<Close fill={`${hexToRgba(appearance.textColor, 0.7)}`} />
</div>
) : (
<div className="bluxcc:size-5" />
Expand All @@ -56,4 +58,4 @@ const ModalHeader = ({
);
};

export default ModalHeader;
export default Header;
96 changes: 28 additions & 68 deletions src/components/Modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,36 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { useRef } from 'react';

import { useProvider } from '../../context/provider';
import { useModalAnimation } from '../../hooks/useModalAnimation';

import ModalHeader from './Header';
import ModalBackdrop from './Backdrop';
import { useIsMobile } from '../../hooks/useIsMobile';
import { useDynamicHeight } from '../../hooks/useDynamicHeight';

interface ModalProps {
isOpen: boolean;
onClose?: () => void;
onBack?: () => void;
children: React.ReactNode;
icon?: 'info' | 'back';
onInfo?: () => void;
closeButton?: boolean;
title: string;
isSticky?: boolean;
}

const Modal = ({
isOpen,
onClose = () => {},
onBack,
onInfo,
children,
title,
icon,
isSticky = false,
closeButton = true,
}: ModalProps) => {
const [height, setHeight] = useState<string | number>('auto');
const [isMobile, setIsMobile] = useState(false);
const [heightReady, setHeightReady] = useState(false);

const contentRef = useRef<HTMLDivElement>(null);
const context = useProvider();
const contentRef = useRef<HTMLDivElement>(null);

const isMobile = useIsMobile();
const { isOpening, isClosing, handleClose } = useModalAnimation(isOpen);
const { height, ready: heightReady } = useDynamicHeight(contentRef, [
isOpen,
children,
]);

const { appearance } = context.value.config;

useEffect(() => {
const checkMobile = () => setIsMobile(window.innerWidth < 760);

checkMobile();

window.addEventListener('resize', checkMobile);

return () => window.removeEventListener('resize', checkMobile);
}, []);

useEffect(() => {
if (!isOpen || !contentRef.current) return;

// Initialize height when modal opens
setHeight(contentRef.current.offsetHeight);
setHeightReady(true);

// Set up the resize observer to update height when content changes
const resizeObserver = new ResizeObserver(() => {
if (contentRef.current) {
setHeight(contentRef.current.offsetHeight);
}
});

resizeObserver.observe(contentRef.current);

return () => resizeObserver.disconnect();
}, [isOpen, children]);

if (!isOpen) return null;

return (
Expand All @@ -87,30 +50,27 @@ const Modal = ({
onClick={(e) => e.target === e.currentTarget && handleClose(onClose)}
>
<div
className={`bluxcc:box-border bluxcc:overflow-hidden bluxcc:!shadow-[0px_4px_80px_0px_#00000008] bluxcc:transition-all bluxcc:duration-300 ${
className={`bluxcc:box-border bluxcc:!shadow-[0px_4px_80px_0px_#00000008] ${
isMobile
? 'bluxcc:fixed bluxcc:bottom-0 bluxcc:left-0 bluxcc:max-h-[90vh] bluxcc:w-full bluxcc:!rounded-b-none'
: 'bluxcc:relative bluxcc:!w-[360px]'
}`}
style={{
height:
typeof height === 'number'
? `${isMobile ? height + 40 : height}px`
? `${isMobile ? height + 20 : height}px`
: height,
transition: heightReady
? `height 300ms ease-in-out, border-radius 300ms, opacity 300ms ease-out${
isMobile ? ', transform 300ms ease-out' : ''
? `height 250ms ease-in-out, border-radius 250ms, opacity 250ms ease-out, outline 250ms ease-out, color 250ms ease-out${
isMobile ? ', transform 250ms ease-out' : ''
}`
: `border-radius 300ms, opacity 300ms ease-out${
isMobile ? ', transform 300ms ease-out' : ''
: `border-radius 250ms, opacity 250ms ease-out${
isMobile ? ', transform 250ms ease-out' : ''
}`,
transform: isMobile
? isOpening
transform:
isMobile && (isOpening || isClosing)
? 'translateY(100%)'
: isClosing
? 'translateY(100%)'
: 'translateY(0%)'
: 'none',
: 'translateY(0%)',
backgroundColor: appearance.background,
opacity: isClosing && !isSticky ? '0' : '1',
color: appearance.textColor,
Expand All @@ -120,17 +80,17 @@ const Modal = ({
outlineColor: appearance.borderColor,
outlineWidth: appearance.borderWidth,
borderRadius: appearance.borderRadius,
overflow: 'hidden',
}}
>
<div ref={contentRef} className="bluxcc:px-6 bluxcc:pb-4">
<ModalHeader
icon={icon}
onInfo={onInfo}
onBack={onBack}
title={title}
closeButton={closeButton}
onClose={() => handleClose(onClose)}
/>
<div
ref={contentRef}
className={`bluxcc:px-6 bluxcc:pt-5 bluxcc:pb-4`}
style={{
opacity: heightReady ? 1 : 0,
transition: 'opacity 250ms ease-in-out',
}}
>
{children}
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const defaultLightTheme: IAppearance = {
accent: '#0c1083',
borderWidth: '1px',
bgField: '#ffffff',
borderRadius: '32px',
borderRadius: '24px',
textColor: '#000000',
background: '#ffffff',
includeBorders: true,
Expand All @@ -23,7 +23,7 @@ export const defaultDarkTheme: IAppearance = {
accent: '#ffffff',
borderWidth: '1px',
bgField: '#1a1a1a',
borderRadius: '32px',
borderRadius: '24px',
textColor: '#ffffff',
background: '#000000',
includeBorders: true,
Expand Down
2 changes: 1 addition & 1 deletion src/containers/BluxModal/content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const getModalContent = (
Component: <Activity />,
},
[Routes.OTP]: {
title: translate('enterConfirmationCodeTitle', lang),
title: '',
Component: <ConfirmCode />,
},
[Routes.WRONG_NETWORK]: {
Expand Down
22 changes: 13 additions & 9 deletions src/containers/BluxModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';

import Modal from '../../components/Modal';
import Header from '../../components/Header';
import { useProvider } from '../../context/provider';

import { Routes } from '../../types';
Expand Down Expand Up @@ -60,25 +61,28 @@ export default function BluxModal({ isOpen, closeModal }: BluxModalProps) {
}
}
};
const modalContent = getModalContent(value.config.lang as LanguageKey);

const { title, Component, isSticky } = modalContent[route];

const showCloseModalIcon =
route === Routes.WRONG_NETWORK ||
route === Routes.WAITING ||
route === Routes.SUCCESSFUL;

const modalContent = getModalContent(value.config.lang as LanguageKey);

const { title, Component, isSticky } = modalContent[route];

return (
<Modal
isOpen={isOpen}
onBack={handleBackNavigation}
onClose={isSticky ? () => {} : handleCloseModal}
title={title}
isSticky={isSticky}
icon={modalIcon}
closeButton={!showCloseModalIcon}
onClose={isSticky ? () => {} : handleCloseModal}
>
<Header
onBack={handleBackNavigation}
onClose={isSticky ? () => {} : handleCloseModal}
title={title}
icon={modalIcon}
closeButton={!showCloseModalIcon}
/>
{Component}
</Modal>
);
Expand Down
4 changes: 2 additions & 2 deletions src/containers/Pages/Activity/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const Activity: React.FC = () => {
details.description = `${humanizeAmount(op.amount)} ${handleAssetText(op)}`;
} else if (
op.type ===
Horizon.HorizonApi.OperationResponseType.pathPaymentStrictSend ||
Horizon.HorizonApi.OperationResponseType.pathPaymentStrictSend ||
op.type === Horizon.HorizonApi.OperationResponseType.pathPayment
) {
console.log(op);
Expand All @@ -90,7 +90,7 @@ const Activity: React.FC = () => {
const isEmpty = !loading && transactionsDetails.length === 0;

return (
<div className="bluxcc:flex bluxcc:h-[335px] bluxcc:flex-col">
<div className="bluxcc:flex bluxcc:h-[355px] bluxcc:flex-col">
{loading ? (
<div className="bluxcc:flex bluxcc:h-full bluxcc:flex-col bluxcc:items-center bluxcc:justify-center bluxcc:text-center bluxcc:text-gray-700">
{t('loadingActivity')}
Expand Down
2 changes: 1 addition & 1 deletion src/containers/Pages/OnBoarding/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ const OnBoarding = () => {
alt={value.config.appName}
width={152}
height={60}
className="bluxcc:max-h-[80px] bluxcc:max-w-[180px]"
className="bluxcc:max-h-[80px] bluxcc:max-w-[180px] bluxcc:select-none"
loading="eager"
decoding="async"
draggable="false"
Expand Down
28 changes: 28 additions & 0 deletions src/hooks/useDynamicHeight.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useEffect, useState } from 'react';

export const useDynamicHeight = (
ref: React.RefObject<HTMLDivElement | null>,
deps: React.DependencyList = [],
) => {
const [height, setHeight] = useState<string | number>('auto');
const [ready, setReady] = useState(false);

useEffect(() => {
const el = ref.current;
if (!el) return;

const updateHeight = () => {
setHeight(el.offsetHeight);
};

updateHeight();
setReady(true);

const observer = new ResizeObserver(updateHeight);
observer.observe(el);

return () => observer.disconnect();
}, deps);

return { height, ready };
};
14 changes: 14 additions & 0 deletions src/hooks/useIsMobile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useEffect, useState } from 'react';

export const useIsMobile = (breakpoint = 760) => {
const [isMobile, setIsMobile] = useState(false);

useEffect(() => {
const update = () => setIsMobile(window.innerWidth < breakpoint);
update();
window.addEventListener('resize', update);
return () => window.removeEventListener('resize', update);
}, [breakpoint]);

return isMobile;
};
11 changes: 11 additions & 0 deletions src/tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,14 @@
#bluxcc-input[type='number'] {
-moz-appearance: textfield !important;
}

#bluxcc-input:-webkit-autofill,
#bluxcc-input:-webkit-autofill:hover,
#bluxcc-input:-webkit-autofill:focus,
#bluxcc-input:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 1000px transparent inset !important;
box-shadow: 0 0 0 1000px transparent inset !important;
-webkit-text-fill-color: inherit !important;
color: inherit !important;
transition: background-color 5000s ease-in-out 0s !important;
}
Loading