Skip to content

Commit

Permalink
Merge pull request #237 from omsant02/documentation-page-#222
Browse files Browse the repository at this point in the history
feat(FE): Implement Desktop Documentation Component
  • Loading branch information
djeck1432 authored Nov 23, 2024
2 parents 1260769 + f0a7193 commit c6c4448
Show file tree
Hide file tree
Showing 9 changed files with 639 additions and 1 deletion.
2 changes: 2 additions & 0 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { createPortal } from 'react-dom';
import LogoutModal from './components/Logout/LogoutModal';
import { connectWallet, logout, checkForCRMToken } from 'services/wallet';
import { saveTelegramUser, getTelegramUserWalletId } from 'services/telegram';
import Documentation from 'pages/spotnet/documentation/Documentation';

function App() {
const [walletId, setWalletId] = useState(localStorage.getItem('wallet_id'));
Expand Down Expand Up @@ -109,6 +110,7 @@ function App() {
/>
<Route path="/dashboard" element={<Dashboard walletId={walletId} telegramId={tgUser} />} />
<Route path="/form" element={<Form walletId={walletId} setWalletId={setWalletId} />} />
<Route path="/documentation" element={<Documentation/>} />
</Routes>
</main>
<Footer />
Expand Down
13 changes: 12 additions & 1 deletion frontend/src/components/Footer/Footer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,18 @@ function Footer() {
<p>Copyright© Spotnet {new Date().getFullYear()}</p>
</div>
<nav className="footer-docs">
<Link to="/documentation">Documentation</Link>
<NavLink
to="/documentation"
className={({ isActive }) => (isActive ? 'footer-link-active' : '')}
onClick={(e) => {
if (window.location.pathname === '/documentation') {
e.preventDefault();
}
window.scrollTo({ top: 0, behavior: 'smooth' });
}}
>
Documentation
</NavLink>
<Link to="/overview">Overview</Link>
<Link to="/terms">Terms & Conditions</Link>
<Link to="/defi">Defi Spring Rewards</Link>
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/Footer/footer.css
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,7 @@
flex-direction: column;
}
}

.footer-link-active {
color: var(--nav-button-hover) !important;
}
62 changes: 62 additions & 0 deletions frontend/src/components/scrollButton/ScrollButton.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.scroll-button-wrapper {
position: fixed;
bottom: 2rem;
right: 2rem;
z-index: 50;
}

.scroll-button {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1.25rem;
background: rgba(20, 20, 40, 0.8);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 9999px;
color: var(--primary);
font-family: var(--font-family);
font-size: 0.875rem;
cursor: pointer;
transition: all 0.2s ease;
backdrop-filter: blur(8px);
}

.scroll-button:hover {
background: rgba(30, 30, 50, 0.9);
border-color: rgba(255, 255, 255, 0.2);
}

.scroll-text {
font-weight: 500;
}

.scroll-chevron {
transform: translateY(1px);
transition: transform 0.2s ease;
}

.scroll-button:hover .scroll-chevron {
transform: translateY(2px);
}

.scroll-button::after {
content: '';
position: absolute;
inset: -1px;
border-radius: 9999px;
padding: 1px;
background: linear-gradient(45deg,
rgba(111, 63, 245, 0.4),
rgba(111, 63, 245, 0) 50%
);
mask: linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
opacity: 0;
transition: opacity 0.2s ease;
}

.scroll-button:hover::after {
opacity: 1;
}
56 changes: 56 additions & 0 deletions frontend/src/components/scrollButton/ScrollButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React, { useState, useEffect } from 'react';
import './ScrollButton.css';

const ScrollButton = () => {
const [isVisible, setIsVisible] = useState(false);

useEffect(() => {
const toggleVisibility = () => {
const scrollHeight = document.documentElement.scrollHeight;
const scrollPosition = window.innerHeight + window.pageYOffset;
if (scrollHeight - scrollPosition > 100) {
setIsVisible(true);
} else {
setIsVisible(false);
}
};

window.addEventListener('scroll', toggleVisibility);
toggleVisibility();

return () => window.removeEventListener('scroll', toggleVisibility);
}, []);

const scrollToBottom = () => {
window.scrollTo({
top: document.documentElement.scrollHeight,
behavior: 'smooth'
});
};

return isVisible ? (
<div className="scroll-button-wrapper">
<button onClick={scrollToBottom} className="scroll-button">
<span className="scroll-text">Scroll down</span>
<svg
className="scroll-chevron"
width="12"
height="12"
viewBox="0 0 12 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M2 4L6 8L10 4"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</button>
</div>
) : null;
};

export default ScrollButton;
101 changes: 101 additions & 0 deletions frontend/src/pages/spotnet/documentation/Documentation.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import React, { useEffect } from 'react';
import './documentation.css';
import Section from './Section';
import TableOfContents from './TableOfContents';
import ScrollButton from '../../../components/scrollButton/ScrollButton';

const Documentation = () => {

useEffect(() => {
window.scrollTo(0, 0);
}, []);


const tableOfContents = [
{ title: 'Introduction', link: '#introduction' },
{
title: 'Overview',
link: '#overview',
subItems: [
{ title: 'Cosmos Overview', link: '#cosmos-1' },
{ title: 'Cosmos Overview', link: '#cosmos-2' },
{ title: 'Cosmos Overview', link: '#cosmos-3' },
{ title: 'Cosmos Overview', link: '#cosmos-4' }
]
},
{ title: 'Getting Started', link: '#getting-started' },
{ title: 'Features Overview', link: '#features' },
{ title: 'The Hub And Zones', link: '#hub-1' },
{ title: 'The Hub And Zones', link: '#hub-2' },
{ title: 'The Hub And Zones', link: '#hub-3' },
{ title: 'The Hub And Zones', link: '#hub-4' },
{ title: 'The Hub And Zones', link: '#hub-5' }
];

return (
<div className="documentation-page">
<TableOfContents items={tableOfContents} />

<div className="main-content">
<h1 className="main-title">zkLend Documentation</h1>

<Section
id="introduction"
title="Introduction"
content={[
{
type: 'text',
value: "Welcome to [Product Name] Documentation\n[Product Name] is a decentralized platform designed to [describe purpose, e.g., \"empower users to securely manage digital assets and access DeFi tools effortlessly\"]. This documentation provides a comprehensive guide on using [Product Name] and making the most of its features."
}
]}
/>

<Section
id="overview"
title="Overview"
content={[
{
type: 'text',
value: "What is [Product Name]?\n[Product Name] is a Web3 platform that leverages blockchain technology to [describe primary functionalities, e.g., \"facilitate secure transactions, staking, and asset management without intermediaries\"]."
},
{
type: 'text',
value: "Core features include:"
},
{
type: 'list',
items: [
"Decentralized Finance (DeFi): Access a suite of DeFi services, including lending, borrowing, and yield farming.",
"Security-First Design: Built on smart contracts to ensure safety and transparency.",
"Cross-Chain Compatibility: [Product Name] supports multiple blockchains for a seamless user experience."
]
}
]}
/>

<Section
id="getting-started"
title="Getting Started"
content={[
{
type: 'text',
value: "Setting Up Your Wallet"
},
{
type: 'orderedList',
items: [
"Download a compatible Web3 wallet (e.g., MetaMask).",
"Fund your wallet with the supported cryptocurrency.",
"Connect your wallet to [Product Name]."
]
}
]}
/>
</div>

<ScrollButton />
</div>
);
};

export default Documentation;
47 changes: 47 additions & 0 deletions frontend/src/pages/spotnet/documentation/Section.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react';
import './documentation.css';

const Section = ({ id, title, content }) => {
const renderContent = (item, index) => {
switch (item.type) {
case 'text':
return (
<p key={index} className="section-text">
{item.value.split('\n').map((text, i) => (
<React.Fragment key={i}>
{text}
{i < item.value.split('\n').length - 1 && <br />}
</React.Fragment>
))}
</p>
);
case 'list':
return (
<ul key={index} className="feature-list">
{item.items.map((listItem, i) => (
<li key={i}>{listItem}</li>
))}
</ul>
);
case 'orderedList':
return (
<ol key={index} className="setup-steps">
{item.items.map((listItem, i) => (
<li key={i}>{i + 1}. {listItem}</li>
))}
</ol>
);
default:
return null;
}
};

return (
<section id={id} className="documentation-section">
<h2 className="section-title">{title}</h2>
{content.map((item, index) => renderContent(item, index))}
</section>
);
};

export default Section;
Loading

0 comments on commit c6c4448

Please sign in to comment.