init
This commit is contained in:
parent
2d87e1d9b8
commit
453e77b3f8
24
banquise-website/.gitignore
vendored
24
banquise-website/.gitignore
vendored
@ -1,24 +0,0 @@
|
|||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
|
|
||||||
node_modules
|
|
||||||
dist
|
|
||||||
dist-ssr
|
|
||||||
*.local
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.idea
|
|
||||||
.DS_Store
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.sw?
|
|
@ -1,54 +0,0 @@
|
|||||||
# React + TypeScript + Vite
|
|
||||||
|
|
||||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
|
||||||
|
|
||||||
Currently, two official plugins are available:
|
|
||||||
|
|
||||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
|
|
||||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
|
||||||
|
|
||||||
## Expanding the ESLint configuration
|
|
||||||
|
|
||||||
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
|
|
||||||
|
|
||||||
```js
|
|
||||||
export default tseslint.config({
|
|
||||||
extends: [
|
|
||||||
// Remove ...tseslint.configs.recommended and replace with this
|
|
||||||
...tseslint.configs.recommendedTypeChecked,
|
|
||||||
// Alternatively, use this for stricter rules
|
|
||||||
...tseslint.configs.strictTypeChecked,
|
|
||||||
// Optionally, add this for stylistic rules
|
|
||||||
...tseslint.configs.stylisticTypeChecked,
|
|
||||||
],
|
|
||||||
languageOptions: {
|
|
||||||
// other options...
|
|
||||||
parserOptions: {
|
|
||||||
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
|
||||||
tsconfigRootDir: import.meta.dirname,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
|
|
||||||
|
|
||||||
```js
|
|
||||||
// eslint.config.js
|
|
||||||
import reactX from 'eslint-plugin-react-x'
|
|
||||||
import reactDom from 'eslint-plugin-react-dom'
|
|
||||||
|
|
||||||
export default tseslint.config({
|
|
||||||
plugins: {
|
|
||||||
// Add the react-x and react-dom plugins
|
|
||||||
'react-x': reactX,
|
|
||||||
'react-dom': reactDom,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
// other rules...
|
|
||||||
// Enable its recommended typescript rules
|
|
||||||
...reactX.configs['recommended-typescript'].rules,
|
|
||||||
...reactDom.configs.recommended.rules,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
```
|
|
@ -1,2 +0,0 @@
|
|||||||
npm install
|
|
||||||
npm run build
|
|
@ -1,28 +0,0 @@
|
|||||||
import js from '@eslint/js'
|
|
||||||
import globals from 'globals'
|
|
||||||
import reactHooks from 'eslint-plugin-react-hooks'
|
|
||||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
||||||
import tseslint from 'typescript-eslint'
|
|
||||||
|
|
||||||
export default tseslint.config(
|
|
||||||
{ ignores: ['dist'] },
|
|
||||||
{
|
|
||||||
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
|
||||||
files: ['**/*.{ts,tsx}'],
|
|
||||||
languageOptions: {
|
|
||||||
ecmaVersion: 2020,
|
|
||||||
globals: globals.browser,
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
'react-hooks': reactHooks,
|
|
||||||
'react-refresh': reactRefresh,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
...reactHooks.configs.recommended.rules,
|
|
||||||
'react-refresh/only-export-components': [
|
|
||||||
'warn',
|
|
||||||
{ allowConstantExport: true },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
@ -1,19 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="fr"> <!-- Changement de "en" à "fr" pour refléter la langue du contenu -->
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<!-- Remplacement du favicon par le logo de La Banquise -->
|
|
||||||
<link rel="icon" type="image/png" href="/src/assets/banquise.png" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
||||||
<meta name="description" content="Services d'hébergement La Banquise - Accédez à notre Wiki, Gitea et Panel de jeux" />
|
|
||||||
<title>La Banquise - Services d'hébergement</title>
|
|
||||||
<!-- Ajout des polices Google Fonts -->
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Dela+Gothic+One&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="root"></div>
|
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "banquise-website",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.0.0",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "tsc -b && vite build",
|
|
||||||
"lint": "eslint .",
|
|
||||||
"preview": "vite preview"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"axios": "^1.6.5",
|
|
||||||
"clsx": "^2.1.0",
|
|
||||||
"framer-motion": "^10.18.0",
|
|
||||||
"react": "^18.2.0",
|
|
||||||
"react-dom": "^18.2.0",
|
|
||||||
"react-icons": "^4.12.0",
|
|
||||||
"react-router-dom": "^6.22.0",
|
|
||||||
"@tanstack/react-query": "^5.17.9",
|
|
||||||
"tailwind-merge": "^2.2.0",
|
|
||||||
"zustand": "^4.4.7"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@eslint/js": "^9.25.0",
|
|
||||||
"@tailwindcss/forms": "^0.5.7",
|
|
||||||
"@tailwindcss/typography": "^0.5.10",
|
|
||||||
"@types/react": "^18.2.58",
|
|
||||||
"@types/react-dom": "^18.2.19",
|
|
||||||
"@vitejs/plugin-react": "^4.4.1",
|
|
||||||
"autoprefixer": "^10.4.16",
|
|
||||||
"eslint": "^9.25.0",
|
|
||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
|
||||||
"eslint-plugin-react-refresh": "^0.4.19",
|
|
||||||
"eslint-plugin-tailwindcss": "^3.14.0",
|
|
||||||
"globals": "^16.0.0",
|
|
||||||
"postcss": "^8.4.33",
|
|
||||||
"typescript": "~5.8.3",
|
|
||||||
"typescript-eslint": "^8.30.1",
|
|
||||||
"vite": "^6.3.5",
|
|
||||||
"vite-plugin-compression": "^0.5.1",
|
|
||||||
"tailwindcss": "^3.4.1"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
export default {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
/* This file is no longer needed - all styles have been converted to Tailwind CSS */
|
|
@ -1,106 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
import { Navigation } from './components/layout/Navigation';
|
|
||||||
import { Footer } from './components/layout/Footer';
|
|
||||||
import { HeroSection } from './components/sections/HeroSection';
|
|
||||||
import { TechFeaturesSection } from './components/sections/TechFeaturesSection';
|
|
||||||
import { ServicesSection } from './components/sections/ServicesSection';
|
|
||||||
import { AboutSection } from './components/sections/AboutSection';
|
|
||||||
import { Popup } from './components/ui/Popup';
|
|
||||||
import { ScrollToTopButton } from './components/ui/ScrollToTopButton';
|
|
||||||
import { URLS } from './config/constants';
|
|
||||||
|
|
||||||
// Define Service interface directly in App
|
|
||||||
interface Service {
|
|
||||||
name: string;
|
|
||||||
url: string;
|
|
||||||
image: string;
|
|
||||||
description: string;
|
|
||||||
features: string[];
|
|
||||||
icon: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const App: React.FC = () => {
|
|
||||||
// Define services directly in the component with enhanced data
|
|
||||||
const services: Service[] = [
|
|
||||||
{
|
|
||||||
name: "Wiki",
|
|
||||||
url: URLS.services.wiki,
|
|
||||||
image: "/src/assets/iceberg.png",
|
|
||||||
icon: "📚",
|
|
||||||
description: "Notre wiki collaboratif est votre centre de documentation technique. Accédez à des guides détaillés, des tutoriels et de la documentation API pour tous nos services.",
|
|
||||||
features: [
|
|
||||||
"Documentation collaborative en temps réel",
|
|
||||||
"Guides d'installation détaillés",
|
|
||||||
"API et références techniques",
|
|
||||||
"Tutoriels pas à pas",
|
|
||||||
"Base de connaissances communautaire",
|
|
||||||
"Recherche avancée intégrée"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Gitea",
|
|
||||||
url: URLS.services.gitea,
|
|
||||||
image: "/src/assets/iceberg.png",
|
|
||||||
icon: "🔧",
|
|
||||||
description: "Instance Gitea auto-hébergée pour la gestion de vos dépôts Git. Collaborez sur vos projets avec un contrôle total sur votre code source.",
|
|
||||||
features: [
|
|
||||||
"Dépôts Git illimités",
|
|
||||||
"Issues et pull requests",
|
|
||||||
"Actions CI/CD intégrées",
|
|
||||||
"Gestion d'équipes et permissions",
|
|
||||||
"Interface web intuitive",
|
|
||||||
"Intégration avec outils externes"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Panel",
|
|
||||||
url: URLS.services.panel,
|
|
||||||
image: "/src/assets/iceberg.png",
|
|
||||||
icon: "🎮",
|
|
||||||
description: "Interface de gestion centralisée pour vos serveurs de jeux. Déployez, configurez et surveillez vos serveurs gaming en quelques clics.",
|
|
||||||
features: [
|
|
||||||
"Déploiement automatisé de serveurs",
|
|
||||||
"Monitoring en temps réel",
|
|
||||||
"Gestion des ressources système",
|
|
||||||
"Interface d'administration web",
|
|
||||||
"Support multi-jeux",
|
|
||||||
"Sauvegarde automatique des données"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const [selectedService, setSelectedService] = useState<Service | null>(null);
|
|
||||||
|
|
||||||
// Inline accordion logic
|
|
||||||
const [openAccordion, setOpenAccordion] = useState<string | null>(null);
|
|
||||||
const toggleAccordion = (title: string) => {
|
|
||||||
setOpenAccordion(openAccordion === title ? null : title);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col min-h-screen w-full">
|
|
||||||
<Navigation />
|
|
||||||
|
|
||||||
<main className="flex-1 flex flex-col overflow-x-hidden overflow-y-auto">
|
|
||||||
<div className="relative flex-1 bg-ocean-gradient w-full min-h-screen flex flex-col justify-start items-center overflow-x-hidden">
|
|
||||||
|
|
||||||
<HeroSection />
|
|
||||||
<TechFeaturesSection />
|
|
||||||
<ServicesSection services={services} onServiceClick={setSelectedService} />
|
|
||||||
<AboutSection openAccordion={openAccordion} toggleAccordion={toggleAccordion} />
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<Footer />
|
|
||||||
|
|
||||||
{/* Bouton de retour en haut */}
|
|
||||||
<ScrollToTopButton />
|
|
||||||
|
|
||||||
{selectedService && (
|
|
||||||
<Popup service={selectedService} onClose={() => setSelectedService(null)} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default App;
|
|
Binary file not shown.
Before Width: | Height: | Size: 188 KiB |
@ -1,53 +0,0 @@
|
|||||||
<svg width="6000" height="6000" viewBox="1550 250 2805 4040" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<rect width="6000" height="6000" fill="none"/>
|
|
||||||
<path d="M1555.65 1896.61V1820.67L4326.47 1818.24V1901.46H3909.18C3816.01 2210.62 3627.34 2832.01 3618 2844.29C3606.32 2859.64 3599.32 2864.49 3578.3 2867.72C3561.48 2870.3 3547.41 2853.18 3542.48 2844.29L3215.5 4262.17C3213.94 4273.48 3204.13 4296.26 3177.35 4296.91C3150.57 4297.56 3137.12 4269.17 3133.75 4254.9L3023.2 3937.39C2992.57 4016.3 2928.53 4181.06 2917.32 4208.85C2903.3 4243.59 2904.08 4256.51 2868.27 4262.17C2839.62 4266.69 2826.74 4228.51 2823.89 4208.85L2486 3026.07L2398.81 3163.41C2392.84 3181.46 2374.83 3216.41 2350.54 3211.89C2326.25 3207.36 2316.54 3177.69 2314.72 3163.41L2059.36 1896.61H1555.65Z" fill="#34A6FC"/>
|
|
||||||
<path d="M2892.4 2234.25L2720.09 2368.34L2558.7 2764.97L2892.4 2234.25Z" fill="#76BEEE"/>
|
|
||||||
<path d="M3437.39 2690.66L3230 2403.89L3141.89 2884.53L3242.47 3181.8L3437.39 2690.66Z" fill="#76BEEE"/>
|
|
||||||
<path d="M3199.59 3291.66L3114.6 3038.01L2964.13 3888.62L3199.59 3291.66Z" fill="#76BEEE"/>
|
|
||||||
<path d="M2525.75 1895.43H2164.98L2627.04 2257.4L2525.75 1895.43Z" fill="#A0ECF9"/>
|
|
||||||
<path d="M2708.08 2285.68C2706.21 2292.15 2674.57 2166.64 2658.99 2103.08L3111.7 1965.73C2977.94 2069.68 2709.95 2279.22 2708.08 2285.68Z" fill="#A0ECF9"/>
|
|
||||||
<path d="M3347.02 1903.51H3834.02L3577.66 2709.86L3347.02 1903.51Z" fill="#A0ECF9"/>
|
|
||||||
<path d="M3172.48 2318.81L3038.46 2134.59L2536.66 2936.1L2563.93 3023.36L3078.98 2851.26L3172.48 2318.81Z" fill="#A0ECF9"/>
|
|
||||||
<path d="M3381.31 3218.08L3480.26 2776.12L3250.4 3356.24L3381.31 3218.08Z" fill="#A0ECF9"/>
|
|
||||||
<path d="M3347.02 3364.32L3182.61 3538.84L3200.53 3996.15L3347.02 3364.32Z" fill="#A0ECF9"/>
|
|
||||||
<path d="M2643.12 2367.1L2152.51 1981.71L2366.67 3048.2L2643.12 2367.1Z" fill="#1F5078"/>
|
|
||||||
<path d="M2638.45 2029.38L2604.18 1900.11H3077.66L2638.45 2029.38Z" fill="#1F5078"/>
|
|
||||||
<path d="M3279.35 1930L3088.56 2078.67L3484.94 2628.88L3279.35 1930Z" fill="#1F5078"/>
|
|
||||||
<path d="M3055.85 2938.32L2583.94 3095.87L2858.83 4046.02L3055.85 2938.32Z" fill="#1F5078"/>
|
|
||||||
<path d="M3116.59 3698.6L3064.42 3827.07L3128.28 4006.43L3116.59 3698.6Z" fill="#1F5078"/>
|
|
||||||
<path d="M2643.12 2367.1L2152.51 1981.71L2366.67 3048.2L2643.12 2367.1Z" fill="#1F5078"/>
|
|
||||||
<path d="M2638.45 2029.38L2604.18 1900.11H3077.66L2638.45 2029.38Z" fill="#1F5078"/>
|
|
||||||
<path d="M3279.35 1930L3088.56 2078.67L3484.94 2628.88L3279.35 1930Z" fill="#1F5078"/>
|
|
||||||
<path d="M3055.85 2938.32L2583.94 3095.87L2858.83 4046.02L3055.85 2938.32Z" fill="#1F5078"/>
|
|
||||||
<path d="M3116.59 3698.6L3064.42 3827.07L3128.28 4006.43L3116.59 3698.6Z" fill="#1F5078"/>
|
|
||||||
<path d="M1554.09 1348.69V1426.25L4325.7 1425.44L4324.14 1347.88H3844.93L3541.04 821.124C3537.93 815.199 3529.67 802.219 3521.56 797.694C3513.46 793.17 3493.77 802.272 3484.94 807.389L3316.63 876.062C3225.73 677.315 3044.07 279.822 3044.69 279.822C3033.78 265.28 3033.78 260.432 3010.41 256.393C2991.71 253.161 2979.76 270.666 2976.12 279.822L2794.57 670.044C2794.57 670.044 2690.94 577.134 2688.6 574.71C2686.26 572.287 2659.77 544.01 2639.51 544.01C2623.3 544.01 2609.38 564.477 2604.45 574.71L2044.98 1348.69H1554.09Z" fill="#34A6FC"/>
|
|
||||||
<path d="M2761.84 740.338L2656.65 642.482L2560.81 1148.74L2577.17 1142.27L2761.84 740.338Z" fill="#F2F2F2"/>
|
|
||||||
<path d="M2723.66 1327.47L2553.8 1231.23L3016.64 1054.93L2723.66 1327.47Z" fill="#F2F2F2"/>
|
|
||||||
<path d="M3534.81 1187.56L3544.16 970.014L3722.6 1285.41L3534.81 1187.56Z" fill="#F2F2F2"/>
|
|
||||||
<path d="M3683.64 1346.88L3529.35 1266.81C3545.98 1293.5 3580.31 1346.88 3584.68 1346.88H3683.64Z" fill="#F2F2F2"/>
|
|
||||||
<path d="M2557.93 767.141L2476.84 1177.5L2173.55 1298.67L2557.93 767.141Z" fill="#76BEEE"/>
|
|
||||||
<path d="M2850.3 1033.71L2671.76 1101.57L2932.16 547.42L2850.3 1033.71Z" fill="#76BEEE"/>
|
|
||||||
<path d="M3186.34 996.556L2805.86 1346.33L3169.18 1347.14L3354.74 1164.58L3186.34 996.556Z" fill="#76BEEE"/>
|
|
||||||
<path d="M3471.69 893.966C3432.71 909.852 3353.81 942.111 3350.07 944.049L3434.27 1133.07L3467.02 1150.04L3471.69 893.966Z" fill="#76BEEE"/>
|
|
||||||
<path d="M3145.16 922.431L2926.99 1004.88L3028.28 419.632L3288.52 996.8C3275.54 984.944 3244.42 955.735 3223.85 933.748C3198.14 906.264 3202.04 914.347 3192.69 908.689C3185.21 904.162 3157.88 915.964 3145.16 922.431Z" fill="#A0ECF9"/>
|
|
||||||
<path d="M2464.18 1261.94L2243.68 1348.44H2609.1L2464.18 1261.94Z" fill="#A0ECF9"/>
|
|
||||||
<path d="M3404.61 1219.91C3362.8 1260.59 3278.08 1343.26 3273.72 1348.44H3495C3497.49 1348.44 3435.78 1262.75 3404.61 1219.91Z" fill="#A0ECF9"/>
|
|
||||||
<path d="M1555.65 1769.2V1485.57C1554.87 1473.37 1561.88 1448.95 1596.16 1448.95H4293.75C4319.31 1448.95 4329.33 1469.21 4331.15 1479.34V1773.88C4331.15 1795.07 4310.37 1798.81 4299.98 1798.03H1596.16C1562.66 1798.03 1555.65 1780.89 1555.65 1769.2Z" fill="#878787"/>
|
|
||||||
<path d="M3246.51 1796.53V1447.45C3585.98 1446.67 4271 1445.74 4295.31 1448.23C4319.62 1450.73 4328.81 1469.53 4330.37 1478.62C4328.55 1562 4326.01 1736.07 4330.37 1765.37C4334.73 1794.66 4309.85 1798.35 4296.86 1796.53H3246.51Z" fill="#595959"/>
|
|
||||||
<path d="M3568.31 1485.57C3541.82 1485.57 3523.9 1506.61 3523.9 1527.65C3523.9 1561.31 3553.51 1569.73 3568.31 1569.73C3603.85 1569.73 3612.73 1541.68 3612.73 1527.65C3612.73 1490.87 3583.9 1485.57 3568.31 1485.57Z" fill="#29C939"/>
|
|
||||||
<path d="M3798.18 1527.65C3798.18 1493.99 3827.53 1485.57 3842.2 1485.57C3856.88 1485.57 3886.23 1493.99 3886.23 1527.65C3886.23 1541.68 3877.42 1569.73 3842.2 1569.73C3827.53 1569.73 3798.18 1561.31 3798.18 1527.65Z" fill="#29C939"/>
|
|
||||||
<path d="M4059.99 1527.65C4059.99 1493.99 4088.3 1485.57 4102.45 1485.57C4136.43 1485.57 4144.92 1513.63 4144.92 1527.65C4144.92 1561.31 4116.61 1569.73 4102.45 1569.73C4068.48 1569.73 4059.99 1541.68 4059.99 1527.65Z" fill="#29C939"/>
|
|
||||||
<path d="M3523.9 1706.09C3523.9 1672.43 3553.51 1664.01 3568.31 1664.01C3603.85 1664.01 3612.73 1692.06 3612.73 1706.09C3612.73 1739.75 3583.12 1748.16 3568.31 1748.16C3532.78 1748.16 3523.9 1720.11 3523.9 1706.09Z" fill="#29C939"/>
|
|
||||||
<path d="M3842.2 1664.01C3806.98 1664.01 3798.18 1692.06 3798.18 1706.09C3798.18 1739.75 3827.53 1748.16 3842.2 1748.16C3877.42 1748.16 3886.23 1720.11 3886.23 1706.09C3886.23 1692.06 3877.42 1664.01 3842.2 1664.01Z" fill="#29C939"/>
|
|
||||||
<path d="M4144.92 1706.09C4144.92 1672.43 4116.61 1664.01 4102.45 1664.01C4068.48 1664.01 4059.99 1692.06 4059.99 1706.09C4059.99 1739.75 4088.3 1748.16 4102.45 1748.16C4116.61 1748.16 4144.92 1739.75 4144.92 1706.09Z" fill="#29C939"/>
|
|
||||||
<path d="M3568.31 1485.57C3541.82 1485.57 3523.9 1506.61 3523.9 1527.65C3523.9 1561.31 3553.51 1569.73 3568.31 1569.73C3603.85 1569.73 3612.73 1541.68 3612.73 1527.65C3612.73 1490.87 3583.9 1485.57 3568.31 1485.57Z" fill="#34A6FC"/>
|
|
||||||
<path d="M3523.9 1706.09C3523.9 1672.43 3553.51 1664.01 3568.31 1664.01C3603.85 1664.01 3612.73 1692.06 3612.73 1706.09C3612.73 1739.75 3583.12 1748.16 3568.31 1748.16C3532.78 1748.16 3523.9 1720.11 3523.9 1706.09Z" fill="#34A6FC"/>
|
|
||||||
<path d="M3842.2 1664.01C3806.98 1664.01 3798.18 1692.06 3798.18 1706.09C3798.18 1739.75 3827.53 1748.16 3842.2 1748.16C3877.42 1748.16 3886.23 1720.11 3886.23 1706.09C3886.23 1692.06 3877.42 1664.01 3842.2 1664.01Z" fill="#34A6FC"/>
|
|
||||||
<path d="M4144.92 1706.09C4144.92 1672.43 4116.61 1664.01 4102.45 1664.01C4068.48 1664.01 4059.99 1692.06 4059.99 1706.09C4059.99 1739.75 4088.3 1748.16 4102.45 1748.16C4116.61 1748.16 4144.92 1739.75 4144.92 1706.09Z" fill="#34A6FC"/>
|
|
||||||
<path d="M1731.75 1569.73V1485.57H1998.23V1569.73H1731.75Z" fill="#D9D9D9"/>
|
|
||||||
<path d="M2373.03 1748.16V1664.01H2639.51V1748.16H2373.03Z" fill="#D9D9D9"/>
|
|
||||||
<path d="M2056.67 1569.73V1485.57H2323.16V1569.73H2056.67Z" fill="#D9D9D9"/>
|
|
||||||
<path d="M2373.03 1485.57V1569.73H2639.51V1485.57H2373.03Z" fill="#D9D9D9"/>
|
|
||||||
<path d="M2323.16 1664.01H2056.67V1748.16H2323.16V1664.01Z" fill="#D9D9D9"/>
|
|
||||||
<path d="M1998.23 1748.16V1664.01H1731.75V1748.16H1998.23Z" fill="#D9D9D9"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 7.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 121 KiB |
@ -1,66 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { URLS, SITE_CONFIG } from '../../config/constants';
|
|
||||||
|
|
||||||
export const Footer: React.FC = () => (
|
|
||||||
<footer className="bg-banquise-blue-dark text-white py-12 sm:py-16 md:py-20 px-4 sm:px-6 md:px-8 relative z-10 border-t border-banquise-blue-lightest/20 w-full box-border">
|
|
||||||
<div className="flex flex-col md:flex-row justify-between max-w-6xl mx-auto gap-6 sm:gap-8">
|
|
||||||
<div className="flex-1 min-w-0 mb-6 sm:mb-8 md:mb-0 text-left">
|
|
||||||
<h4 className="text-lg sm:text-xl mb-6 sm:mb-8 text-banquise-blue-lightest relative pb-3 sm:pb-4 after:content-[''] after:absolute after:bottom-0 after:left-0 after:w-12 after:h-0.5 after:bg-gradient-to-r after:from-banquise-blue-lightest after:to-banquise-blue">
|
|
||||||
Services
|
|
||||||
</h4>
|
|
||||||
<ul className="list-none p-0 m-0 space-y-2 sm:space-y-3">
|
|
||||||
<li>
|
|
||||||
<a href={URLS.services.wiki} className="text-banquise-gray/80 no-underline transition-all duration-200 inline-flex items-center hover:text-banquise-gray hover:translate-x-1 text-sm sm:text-base">
|
|
||||||
Wiki
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href={URLS.services.gitea} className="text-banquise-gray/80 no-underline transition-all duration-200 inline-flex items-center hover:text-banquise-gray hover:translate-x-1 text-sm sm:text-base">
|
|
||||||
Gitea
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href={URLS.services.panel} className="text-banquise-gray/80 no-underline transition-all duration-200 inline-flex items-center hover:text-banquise-gray hover:translate-x-1 text-sm sm:text-base">
|
|
||||||
Panel
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex-1 min-w-0 mb-6 sm:mb-8 md:mb-0 text-left">
|
|
||||||
<h4 className="text-lg sm:text-xl mb-6 sm:mb-8 text-banquise-blue-lightest relative pb-3 sm:pb-4 after:content-[''] after:absolute after:bottom-0 after:left-0 after:w-12 after:h-0.5 after:bg-gradient-to-r after:from-banquise-blue-lightest after:to-banquise-blue">
|
|
||||||
Communauté
|
|
||||||
</h4>
|
|
||||||
<ul className="list-none p-0 m-0 space-y-2 sm:space-y-3">
|
|
||||||
<li>
|
|
||||||
<a href={URLS.social.discord} className="text-banquise-gray/80 no-underline transition-all duration-200 inline-flex items-center hover:text-banquise-gray hover:translate-x-1 text-sm sm:text-base">
|
|
||||||
Discord
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex-1 min-w-0 mb-6 sm:mb-8 md:mb-0 text-left">
|
|
||||||
<h4 className="text-lg sm:text-xl mb-6 sm:mb-8 text-banquise-blue-lightest relative pb-3 sm:pb-4 after:content-[''] after:absolute after:bottom-0 after:left-0 after:w-12 after:h-0.5 after:bg-gradient-to-r after:from-banquise-blue-lightest after:to-banquise-blue">
|
|
||||||
Support
|
|
||||||
</h4>
|
|
||||||
<ul className="list-none p-0 m-0 space-y-2 sm:space-y-3">
|
|
||||||
<li>
|
|
||||||
<a href="#" className="text-banquise-gray/80 no-underline transition-all duration-200 inline-flex items-center hover:text-banquise-gray hover:translate-x-1 text-sm sm:text-base">
|
|
||||||
Documentation
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href={URLS.contact.email} className="text-banquise-gray/80 no-underline transition-all duration-200 inline-flex items-center hover:text-banquise-gray hover:translate-x-1 text-sm sm:text-base">
|
|
||||||
Contact
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="border-t border-banquise-blue-lightest/20 pt-6 sm:pt-8 mt-8 sm:mt-12 text-center text-xs sm:text-sm text-banquise-gray/70 max-w-6xl mx-auto">
|
|
||||||
© 2024 {SITE_CONFIG.name}. Tous droits réservés.
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
);
|
|
@ -1,154 +0,0 @@
|
|||||||
import React, { useEffect } from 'react';
|
|
||||||
import banquiseServer from '../../assets/banquise_server.svg'
|
|
||||||
import { URLS, SITE_CONFIG } from '../../config/constants';
|
|
||||||
import { commonStyles } from '../../styles/components';
|
|
||||||
|
|
||||||
interface MobileMenuProps {
|
|
||||||
isOpen: boolean;
|
|
||||||
onClose: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose }) => {
|
|
||||||
useEffect(() => {
|
|
||||||
if (isOpen) {
|
|
||||||
document.body.style.overflow = 'hidden';
|
|
||||||
} else {
|
|
||||||
document.body.style.overflow = 'unset';
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.body.style.overflow = 'unset';
|
|
||||||
};
|
|
||||||
}, [isOpen]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={`md:hidden fixed inset-0 z-[100] transition-all duration-300 ${isOpen ? 'visible' : 'invisible'}`}>
|
|
||||||
{/* Overlay */}
|
|
||||||
<div
|
|
||||||
className={`absolute inset-0 bg-gradient-to-br from-black/70 via-banquise-blue-dark/50 to-black/70 backdrop-blur-md transition-opacity duration-300 ${isOpen ? 'opacity-100' : 'opacity-0'}`}
|
|
||||||
onClick={onClose}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Menu mobile */}
|
|
||||||
<div className={`absolute top-0 right-0 h-full w-72 max-w-[85vw] bg-gradient-to-b from-banquise-blue-dark via-banquise-blue-dark/98 to-banquise-blue-dark/95 backdrop-blur-2xl shadow-2xl transition-transform duration-300 border-l border-banquise-blue-lightest/20 ${isOpen ? 'translate-x-0' : 'translate-x-full'}`}>
|
|
||||||
|
|
||||||
{/* Header */}
|
|
||||||
<div className="flex items-center justify-between p-4 sm:p-6 pt-6 sm:pt-8 border-b border-banquise-blue-lightest/20 bg-gradient-to-r from-banquise-blue-dark/50 to-transparent">
|
|
||||||
<div className="flex items-center space-x-3">
|
|
||||||
<div className="relative">
|
|
||||||
<div className="absolute inset-0 bg-banquise-blue-light/20 rounded-full blur-md"></div>
|
|
||||||
<img
|
|
||||||
src={banquiseServer}
|
|
||||||
alt="Logo"
|
|
||||||
className="h-8 sm:h-10 w-auto relative z-10"
|
|
||||||
style={{ filter: 'drop-shadow(0 0 8px rgba(168, 218, 255, 0.6))' }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span className={`text-base sm:text-lg font-bold text-white ${commonStyles.text.heading}`}>
|
|
||||||
{SITE_CONFIG.name}
|
|
||||||
</span>
|
|
||||||
<p className="text-banquise-blue-lightest/70 text-xs">Menu Navigation</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
|
||||||
className="group relative p-3 bg-white/10 hover:bg-white/20 rounded-xl transition-all duration-200 hover:scale-105 active:scale-95"
|
|
||||||
onClick={onClose}
|
|
||||||
aria-label="Fermer"
|
|
||||||
>
|
|
||||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" className="text-white">
|
|
||||||
<path d="M15 5L5 15M5 5L15 15" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Navigation */}
|
|
||||||
<div className="flex flex-col justify-start px-6 py-8 space-y-6 overflow-y-auto" style={{ height: 'calc(100vh - 120px)' }}>
|
|
||||||
|
|
||||||
{/* Navigation Links */}
|
|
||||||
<div className="space-y-3">
|
|
||||||
<a href="#services" className={commonStyles.nav.mobileItem} onClick={onClose}>
|
|
||||||
<div className="flex items-center space-x-4">
|
|
||||||
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.primaryBr} group-hover:scale-110 transition-transform duration-200`}>
|
|
||||||
<svg className="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span className="font-semibold text-lg">Nos Services</span>
|
|
||||||
<p className="text-white/60 text-sm">Découvrir notre offre</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<svg className="w-5 h-5 ml-auto opacity-50 group-hover:opacity-100 group-hover:translate-x-1 transition-all duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="#about" className={commonStyles.nav.mobileItem} onClick={onClose}>
|
|
||||||
<div className="flex items-center space-x-4">
|
|
||||||
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.primaryBr} group-hover:scale-110 transition-transform duration-200`}>
|
|
||||||
<svg className="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span className="font-semibold text-lg">À propos</span>
|
|
||||||
<p className="text-white/60 text-sm">En savoir plus sur nous</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<svg className="w-5 h-5 ml-auto opacity-50 group-hover:opacity-100 group-hover:translate-x-1 transition-all duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href={URLS.social.discord} className={commonStyles.nav.mobileItem} onClick={onClose}>
|
|
||||||
<div className="flex items-center space-x-4">
|
|
||||||
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.discord} group-hover:scale-110 transition-transform duration-200`}>
|
|
||||||
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.211.375-.445.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span className="font-semibold text-lg">Discord</span>
|
|
||||||
<p className="text-white/60 text-sm">Rejoindre la communauté</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<svg className="w-5 h-5 ml-auto opacity-50 group-hover:opacity-100 group-hover:translate-x-1 transition-all duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* CTA Button */}
|
|
||||||
<div className="pt-6 border-t border-banquise-blue-lightest/20">
|
|
||||||
<a
|
|
||||||
href={URLS.services.auth}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className={`w-full ${commonStyles.buttons.primary} ${commonStyles.gradients.primary} py-4 px-6 text-lg shadow-xl border border-banquise-blue-lightest/20`}
|
|
||||||
onClick={onClose}
|
|
||||||
>
|
|
||||||
<svg className="w-6 h-6 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
|
|
||||||
</svg>
|
|
||||||
Se connecter
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Footer */}
|
|
||||||
<div className="absolute bottom-6 left-6 right-6">
|
|
||||||
<div className="text-center py-4 border-t border-banquise-blue-lightest/20">
|
|
||||||
<p className="text-white/50 text-sm">
|
|
||||||
© 2024 {SITE_CONFIG.name}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Effet glassmorphism */}
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-banquise-blue-dark/20 pointer-events-none"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,147 +0,0 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import { MobileMenu } from './MobileMenu';
|
|
||||||
import banquiseServer from '/src/assets/banquise_server.svg'
|
|
||||||
import { URLS, SITE_CONFIG } from '../../config/constants';
|
|
||||||
import { commonStyles } from '../../styles/components';
|
|
||||||
|
|
||||||
export const Navigation: React.FC = () => {
|
|
||||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
|
||||||
const [scrolled, setScrolled] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const handleScroll = () => {
|
|
||||||
const isScrolled = window.scrollY > 20;
|
|
||||||
setScrolled(isScrolled);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('scroll', handleScroll);
|
|
||||||
return () => window.removeEventListener('scroll', handleScroll);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const handleResize = () => {
|
|
||||||
if (window.innerWidth >= 768) {
|
|
||||||
setMobileMenuOpen(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('resize', handleResize);
|
|
||||||
return () => window.removeEventListener('resize', handleResize);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<nav className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${
|
|
||||||
scrolled
|
|
||||||
? 'bg-banquise-blue-dark/98 backdrop-blur-xl shadow-2xl border-b border-banquise-blue-lightest/30'
|
|
||||||
: 'bg-banquise-blue-dark/95 backdrop-blur-lg shadow-xl border-b border-banquise-blue-lightest/20'
|
|
||||||
}`}>
|
|
||||||
<div className={commonStyles.layout.container}>
|
|
||||||
<div className="flex justify-between items-center h-16 sm:h-18 lg:h-20 px-4 sm:px-6 lg:px-8">
|
|
||||||
|
|
||||||
{/* Logo section */}
|
|
||||||
<div className="flex items-center space-x-3 sm:space-x-4 group">
|
|
||||||
<div className="relative">
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-full blur-lg opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
|
||||||
<img
|
|
||||||
src={banquiseServer}
|
|
||||||
alt="Logo La Banquise"
|
|
||||||
className="h-10 sm:h-12 lg:h-14 w-auto relative z-10 transition-transform duration-300 group-hover:scale-110"
|
|
||||||
style={{ filter: 'drop-shadow(0 0 12px rgba(168, 218, 255, 0.4))' }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="hidden sm:block">
|
|
||||||
<h1 className={`text-xl sm:text-2xl lg:text-3xl font-bold text-white tracking-wide ${commonStyles.text.heading}`}>
|
|
||||||
{SITE_CONFIG.name}
|
|
||||||
</h1>
|
|
||||||
<p className="text-banquise-blue-lightest/80 text-xs lg:text-sm font-medium">
|
|
||||||
{SITE_CONFIG.tagline}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Navigation links desktop */}
|
|
||||||
<div className="hidden md:flex items-center space-x-1 lg:space-x-2">
|
|
||||||
<a href="#services" className={commonStyles.nav.link}>
|
|
||||||
<span className="relative z-10">Services</span>
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="#about" className={commonStyles.nav.link}>
|
|
||||||
<span className="relative z-10">À propos</span>
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Action buttons desktop */}
|
|
||||||
<div className="hidden md:flex items-center space-x-3 lg:space-x-4">
|
|
||||||
<a
|
|
||||||
href={URLS.social.discord}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className={`${commonStyles.buttons.discord} ${commonStyles.gradients.discord}`}
|
|
||||||
>
|
|
||||||
<div className={`absolute inset-0 ${commonStyles.gradients.discordHover} opacity-0 group-hover:opacity-100 transition-opacity duration-300`}></div>
|
|
||||||
<div className="relative z-10 flex items-center space-x-2">
|
|
||||||
<svg className="w-4 h-4 lg:w-5 lg:h-5" fill="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.211.375-.445.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/>
|
|
||||||
</svg>
|
|
||||||
<span>Discord</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href={URLS.services.auth}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className={`${commonStyles.buttons.auth} ${
|
|
||||||
scrolled
|
|
||||||
? `${commonStyles.gradients.primary} border border-banquise-blue-lightest/30 hover:shadow-banquise-blue/25`
|
|
||||||
: 'bg-gradient-to-r from-banquise-blue-light to-banquise-blue border-2 border-white/20 hover:shadow-banquise-blue-light/25'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<div className={`absolute inset-0 transition-opacity duration-300 opacity-0 group-hover:opacity-100 ${
|
|
||||||
scrolled
|
|
||||||
? 'bg-gradient-to-r from-banquise-blue-light to-banquise-blue'
|
|
||||||
: 'bg-gradient-to-r from-white/10 to-banquise-blue-lightest/20'
|
|
||||||
}`}></div>
|
|
||||||
<div className="relative z-10 flex items-center space-x-2">
|
|
||||||
<svg className="w-4 h-4 lg:w-5 lg:h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
|
|
||||||
</svg>
|
|
||||||
<span className="hidden lg:inline">Connexion</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Mobile menu button */}
|
|
||||||
<button
|
|
||||||
className="md:hidden relative p-3 rounded-xl bg-white/10 hover:bg-white/20 transition-all duration-300 hover:scale-105 active:scale-95 group"
|
|
||||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
|
||||||
aria-label={mobileMenuOpen ? "Fermer le menu" : "Ouvrir le menu"}
|
|
||||||
aria-expanded={mobileMenuOpen}
|
|
||||||
>
|
|
||||||
<div className="w-6 h-6 relative">
|
|
||||||
<span className={`absolute block w-6 h-0.5 bg-white transition-all duration-300 ${mobileMenuOpen ? 'rotate-45 top-3' : 'top-1'}`}></span>
|
|
||||||
<span className={`absolute block w-6 h-0.5 bg-white transition-all duration-300 top-3 ${mobileMenuOpen ? 'opacity-0 scale-0' : 'opacity-100'}`}></span>
|
|
||||||
<span className={`absolute block w-6 h-0.5 bg-white transition-all duration-300 ${mobileMenuOpen ? '-rotate-45 top-3' : 'top-5'}`}></span>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Glassmorphism effect bar */}
|
|
||||||
<div className="absolute bottom-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-banquise-blue-lightest/30 to-transparent"></div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{/* Spacer pour compenser la navbar fixed */}
|
|
||||||
<div className="h-16 sm:h-18 lg:h-20"></div>
|
|
||||||
|
|
||||||
{/* Menu mobile */}
|
|
||||||
<MobileMenu
|
|
||||||
isOpen={mobileMenuOpen}
|
|
||||||
onClose={() => setMobileMenuOpen(false)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,124 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { AccordionItem } from '../ui/AccordionItem';
|
|
||||||
import { URLS } from '../../config/constants';
|
|
||||||
import { commonStyles } from '../../styles/components';
|
|
||||||
|
|
||||||
interface AboutSectionProps {
|
|
||||||
openAccordion: string | null;
|
|
||||||
toggleAccordion: (title: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AboutSection: React.FC<AboutSectionProps> = ({ openAccordion, toggleAccordion }) => (
|
|
||||||
<section id="about" className="relative bg-gradient-to-b from-banquise-blue-dark/15 to-banquise-blue-dark/20 backdrop-blur-lg py-16 sm:py-20 md:py-24 px-4 sm:px-6 md:px-8 z-2 border-t border-banquise-blue-lightest/20 w-full box-border">
|
|
||||||
<div className="max-w-4xl mx-auto">
|
|
||||||
{/* Header */}
|
|
||||||
<div className="text-center mb-12 sm:mb-16 md:mb-20">
|
|
||||||
<div className={commonStyles.layout.divider}></div>
|
|
||||||
<h2 className={`${commonStyles.text.headingXl} mb-6 sm:mb-8 px-2`} style={{ textShadow: '0 2px 4px rgba(0, 0, 0, 0.2)' }}>
|
|
||||||
À Propos de La Banquise
|
|
||||||
</h2>
|
|
||||||
<p className={`${commonStyles.text.muted} text-lg sm:text-xl max-w-3xl mx-auto px-2`} style={{ textShadow: '0 1px 2px rgba(0, 0, 0, 0.1)' }}>
|
|
||||||
Une communauté passionnée qui propose des services d'hébergement et des outils collaboratifs pour les développeurs et les gamers.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* FAQ Section */}
|
|
||||||
<div className="space-y-4 sm:space-y-6">
|
|
||||||
<h3 className={`${commonStyles.text.headingLg} mb-8 sm:mb-12 flex items-center justify-center px-2`}>
|
|
||||||
<span className="text-2xl sm:text-3xl mr-3">❓</span>
|
|
||||||
<span className="text-center">Questions Fréquentes</span>
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<AccordionItem
|
|
||||||
title="🎯 Notre Mission"
|
|
||||||
isOpen={openAccordion === "mission"}
|
|
||||||
onToggle={() => toggleAccordion("mission")}
|
|
||||||
>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<p className={commonStyles.text.muted}>
|
|
||||||
Former les étudiants au déploiment et a la gestion d'une infra, et de maitriser des technologies entreprise grade.
|
|
||||||
Cela permet de fournir une plateforme stable et accessible pour héberger vos projets, partager vos connaissances et jouer ensemble !
|
|
||||||
</p>
|
|
||||||
<p className={commonStyles.text.muted}>
|
|
||||||
Nous croyons en la puissance de la collaboration et mettons à disposition des outils modernes pour faciliter le travail en équipe.
|
|
||||||
</p>
|
|
||||||
<div className="flex flex-wrap gap-2 mt-4">
|
|
||||||
<span className="bg-banquise-blue/20 text-banquise-blue-light px-3 py-1 rounded-full text-sm font-medium">Collaboration</span>
|
|
||||||
<span className="bg-banquise-blue/20 text-banquise-blue-light px-3 py-1 rounded-full text-sm font-medium">Innovation</span>
|
|
||||||
<span className="bg-banquise-blue/20 text-banquise-blue-light px-3 py-1 rounded-full text-sm font-medium">Accessibilité</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</AccordionItem>
|
|
||||||
|
|
||||||
<AccordionItem
|
|
||||||
title="🛠️ Nos Services"
|
|
||||||
isOpen={openAccordion === "services"}
|
|
||||||
onToggle={() => toggleAccordion("services")}
|
|
||||||
>
|
|
||||||
<div className="space-y-6">
|
|
||||||
<div className="grid gap-4">
|
|
||||||
<div className={`flex items-start space-x-4 p-4 ${commonStyles.gradients.card} rounded-xl ${commonStyles.cards.base}`}>
|
|
||||||
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.primaryBr} font-bold`}>📚</div>
|
|
||||||
<div>
|
|
||||||
<h4 className="font-semibold text-banquise-gray mb-1">Wiki</h4>
|
|
||||||
<p className="text-banquise-gray/80 text-sm">Documentation collaborative et guides détaillés</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={`flex items-start space-x-4 p-4 ${commonStyles.gradients.card} rounded-xl ${commonStyles.cards.base}`}>
|
|
||||||
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.primaryBr} font-bold`}>🔧</div>
|
|
||||||
<div>
|
|
||||||
<h4 className="font-semibold text-banquise-gray mb-1">Gitea</h4>
|
|
||||||
<p className="text-banquise-gray/80 text-sm">Gestion de versions Git auto-hébergée</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={`flex items-start space-x-4 p-4 ${commonStyles.gradients.card} rounded-xl ${commonStyles.cards.base}`}>
|
|
||||||
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.primaryBr} font-bold`}>🎮</div>
|
|
||||||
<div>
|
|
||||||
<h4 className="font-semibold text-banquise-gray mb-1">Panel de Jeux</h4>
|
|
||||||
<p className="text-banquise-gray/80 text-sm">Interface de gestion pour serveurs de jeux</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p className={`${commonStyles.text.muted} mt-4`}>
|
|
||||||
Tous nos services sont maintenus avec soin et régulièrement mis à jour pour garantir une expérience optimale.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</AccordionItem>
|
|
||||||
|
|
||||||
<AccordionItem
|
|
||||||
title="🤝 Rejoindre l'association"
|
|
||||||
isOpen={openAccordion === "community"}
|
|
||||||
onToggle={() => toggleAccordion("community")}
|
|
||||||
>
|
|
||||||
<div className="space-y-6">
|
|
||||||
<p className={commonStyles.text.muted}>
|
|
||||||
Rejoignez notre serveur Discord pour rejoindre l'asso, échanger avec nous, obtenir de l'aide et rester informé des dernières nouveautés !
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className={`${commonStyles.cards.base} bg-gradient-to-r from-banquise-blue-dark/20 to-banquise-blue/10 rounded-2xl p-6`}>
|
|
||||||
<h4 className="font-semibold text-banquise-gray mb-3 flex items-center">
|
|
||||||
<span className="text-xl mr-2">💬</span>
|
|
||||||
Comment rejoindre l'asso ?
|
|
||||||
</h4>
|
|
||||||
<ul className="space-y-2 text-banquise-gray/80 text-sm mb-6">
|
|
||||||
<li className="flex items-center"><span className="text-banquise-blue-light mr-2">•</span> Creez un ticket banquise</li>
|
|
||||||
<li className="flex items-center"><span className="text-banquise-blue-light mr-2">•</span> Donnez votre login EPITA ou expliquez votre situation</li>
|
|
||||||
<li className="flex items-center"><span className="text-banquise-blue-light mr-2">•</span> Un moderateur validera votre demande et vous donnera acces aux salons discord de l'asso !</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href={URLS.social.discord}
|
|
||||||
className={`${commonStyles.buttons.primary} ${commonStyles.gradients.primary} py-3 px-6 rounded-xl`}
|
|
||||||
>
|
|
||||||
<span className="mr-3 text-lg">🚀</span>
|
|
||||||
Rejoindre Discord
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</AccordionItem>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
@ -1,30 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import banquiseServer from '/src/assets/banquise_server.svg'
|
|
||||||
|
|
||||||
export const HeroSection: React.FC = () => (
|
|
||||||
<section className="min-h-[calc(80vh-72px)] flex flex-col justify-center items-center text-center py-12 sm:py-16 md:py-20 w-full max-w-6xl mx-auto px-4 sm:px-6 md:px-8 relative z-3">
|
|
||||||
<div className="mb-8 sm:mb-10 md:mb-12 w-32 h-32 sm:w-40 sm:h-40 md:w-48 md:h-48 rounded-full bg-gradient-to-br from-banquise-blue-dark/20 to-banquise-blue/10 p-4 sm:p-5 md:p-6 shadow-2xl backdrop-blur-sm border border-banquise-blue-lightest/30 relative group">
|
|
||||||
<img
|
|
||||||
src={banquiseServer}
|
|
||||||
alt="Logo La Banquise"
|
|
||||||
className="w-full h-full object-contain relative z-10 transition-transform duration-300 group-hover:scale-110"
|
|
||||||
style={{
|
|
||||||
filter: 'drop-shadow(0 10px 25px rgba(31, 93, 137, 0.3))'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1 className="text-banquise-gray text-3xl sm:text-4xl md:text-5xl lg:text-6xl mb-6 sm:mb-7 md:mb-8 font-extrabold leading-tight max-w-4xl font-heading px-2 relative z-10" style={{ textShadow: '0 2px 10px rgba(0, 0, 0, 0.3)' }}>
|
|
||||||
Bienvenue sur La Banquise
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p className="text-banquise-gray text-lg sm:text-xl md:text-2xl mb-8 sm:mb-10 md:mb-12 max-w-3xl font-normal opacity-90 leading-relaxed px-2 relative z-10" style={{ textShadow: '0 1px 4px rgba(0, 0, 0, 0.2)' }}>
|
|
||||||
Association d'hébergement et lab réseau pour tous les étudiants et associations de l'EPITA !
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<a href="#services" className="inline-flex items-center justify-center bg-gradient-to-r from-banquise-gray to-white text-banquise-blue-dark border-0 py-4 sm:py-5 px-8 sm:px-10 md:px-12 rounded-2xl text-base sm:text-lg font-bold no-underline shadow-xl transition-all duration-300 min-w-48 sm:min-w-56 md:min-w-64 hover:-translate-y-2 hover:shadow-2xl hover:scale-105 backdrop-blur-sm border border-banquise-blue-lightest/20 mx-4 group relative z-10">
|
|
||||||
<span className="text-center text-banquise-blue-dark">Découvrir nos services</span>
|
|
||||||
<span className="ml-2 sm:ml-3 text-lg sm:text-xl transition-transform duration-300 group-hover:translate-x-1 text-banquise-blue-dark">→</span>
|
|
||||||
</a>
|
|
||||||
</section>
|
|
||||||
);
|
|
@ -1,63 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
// Declare the Service interface here
|
|
||||||
interface Service {
|
|
||||||
name: string;
|
|
||||||
url: string;
|
|
||||||
image: string;
|
|
||||||
icon: string;
|
|
||||||
description: string;
|
|
||||||
features: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define interface directly in the component file
|
|
||||||
interface ServicesSectionProps {
|
|
||||||
services: Service[];
|
|
||||||
onServiceClick: (service: Service) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ServicesSection: React.FC<ServicesSectionProps> = ({ services, onServiceClick }) => (
|
|
||||||
<section id="services" className="relative z-2 py-12 sm:py-16 md:py-20 w-full max-w-6xl mx-auto px-4 sm:px-6 md:px-8">
|
|
||||||
<div className="w-20 h-1 bg-gradient-to-r from-banquise-blue-lightest to-banquise-blue mx-auto mb-6 sm:mb-8 rounded-full"></div>
|
|
||||||
<h2 className="text-banquise-gray text-2xl sm:text-3xl md:text-4xl mb-4 sm:mb-6 text-center font-heading font-bold tracking-tight px-2" style={{ textShadow: '0 2px 4px rgba(0, 0, 0, 0.2)' }}>
|
|
||||||
Nos Services
|
|
||||||
</h2>
|
|
||||||
<p className="text-banquise-gray text-lg sm:text-xl opacity-90 mb-12 sm:mb-14 md:mb-16 max-w-4xl text-center mx-auto leading-relaxed px-2" style={{ textShadow: '0 1px 3px rgba(0, 0, 0, 0.2)' }}>
|
|
||||||
Cliquez sur un service pour découvrir toutes ses fonctionnalités
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 sm:gap-8 w-full">
|
|
||||||
{services.map((service) => (
|
|
||||||
<div
|
|
||||||
key={service.name}
|
|
||||||
className="group relative bg-gradient-to-br from-banquise-blue-dark/10 to-banquise-blue-dark/5 backdrop-blur-lg rounded-2xl p-6 sm:p-8 border border-banquise-blue-lightest/30 transition-all duration-300 cursor-pointer hover:-translate-y-4 hover:shadow-2xl hover:border-banquise-blue-lightest/50 hover:from-banquise-blue-dark/15 hover:to-banquise-blue-dark/8 active:scale-95"
|
|
||||||
onClick={() => onServiceClick(service)}
|
|
||||||
>
|
|
||||||
{/* Icon */}
|
|
||||||
<div className="mb-6 sm:mb-8 w-20 h-20 sm:w-24 sm:h-24 bg-gradient-to-br from-banquise-blue to-banquise-blue-light rounded-2xl flex items-center justify-center text-3xl sm:text-4xl shadow-lg group-hover:scale-110 transition-transform duration-300 mx-auto">
|
|
||||||
{service.icon}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Service name */}
|
|
||||||
<h3 className="text-xl sm:text-2xl font-bold text-banquise-gray mb-4 sm:mb-6 font-heading text-center group-hover:text-banquise-blue-lightest transition-colors duration-300">
|
|
||||||
{service.name}
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
{/* Short teaser description */}
|
|
||||||
<p className="text-banquise-gray/80 leading-relaxed mb-6 sm:mb-8 text-center text-sm sm:text-base">
|
|
||||||
{service.description.split('.')[0]}.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{/* CTA */}
|
|
||||||
<div className="flex items-center justify-center text-banquise-blue-light font-bold group-hover:text-banquise-blue-lightest transition-colors duration-300 text-sm sm:text-base">
|
|
||||||
<span className="text-center">Découvrir toutes les fonctionnalités</span>
|
|
||||||
<span className="ml-2 text-lg transition-transform duration-300 group-hover:translate-x-2">→</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Subtle hover effect */}
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-br from-banquise-blue-lightest/10 to-banquise-blue/5 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-300 pointer-events-none"></div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
@ -1,47 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
export const TechFeaturesSection: React.FC = () => (
|
|
||||||
<section className="py-12 sm:py-16 md:py-20 relative z-2 w-full max-w-6xl mx-auto px-4 sm:px-6 md:px-8">
|
|
||||||
<div className="w-20 h-1 bg-gradient-to-r from-banquise-blue-lightest to-banquise-blue mx-auto mb-6 sm:mb-8 rounded-full"></div>
|
|
||||||
<h2 className="text-banquise-gray text-2xl sm:text-3xl md:text-4xl mb-4 sm:mb-6 text-center font-heading font-bold tracking-tight px-2" style={{ textShadow: '0 2px 4px rgba(0, 0, 0, 0.2)' }}>
|
|
||||||
Notre Infrastructure
|
|
||||||
</h2>
|
|
||||||
<p className="text-banquise-gray text-lg sm:text-xl opacity-90 mb-12 sm:mb-14 md:mb-16 max-w-4xl text-center mx-auto leading-relaxed px-2" style={{ textShadow: '0 1px 3px rgba(0, 0, 0, 0.2)' }}>
|
|
||||||
25+ serveurs pour répondre à vos besoins
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4 sm:gap-6 w-full">
|
|
||||||
<div className="bg-gradient-to-br from-banquise-blue-dark/10 to-banquise-blue-dark/5 backdrop-blur-lg rounded-2xl p-6 sm:p-8 flex flex-col items-center text-center transition-all duration-300 border border-banquise-blue-lightest/30 hover:-translate-y-3 hover:from-banquise-blue-dark/15 hover:to-banquise-blue-dark/8 hover:shadow-xl hover:border-banquise-blue-lightest/50 group">
|
|
||||||
<div className="text-3xl sm:text-4xl mb-4 sm:mb-6 text-white bg-gradient-to-br from-banquise-blue to-banquise-blue-light w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center rounded-2xl shadow-lg group-hover:scale-110 transition-transform duration-300">
|
|
||||||
🚀
|
|
||||||
</div>
|
|
||||||
<h3 className="text-lg sm:text-xl mb-3 sm:mb-4 text-banquise-gray font-heading font-semibold group-hover:text-banquise-blue-lightest transition-colors duration-300">Serveurs performants</h3>
|
|
||||||
<p className="text-banquise-gray/80 leading-relaxed text-sm">Infrastructure optimisée pour assurer des performances élevées et une disponibilité maximale de vos applications</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-gradient-to-br from-banquise-blue-dark/10 to-banquise-blue-dark/5 backdrop-blur-lg rounded-2xl p-6 sm:p-8 flex flex-col items-center text-center transition-all duration-300 border border-banquise-blue-lightest/30 hover:-translate-y-3 hover:from-banquise-blue-dark/15 hover:to-banquise-blue-dark/8 hover:shadow-xl hover:border-banquise-blue-lightest/50 group">
|
|
||||||
<div className="text-3xl sm:text-4xl mb-4 sm:mb-6 text-white bg-gradient-to-br from-banquise-blue to-banquise-blue-light w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center rounded-2xl shadow-lg group-hover:scale-110 transition-transform duration-300">
|
|
||||||
💾
|
|
||||||
</div>
|
|
||||||
<h3 className="text-lg sm:text-xl mb-3 sm:mb-4 text-banquise-gray font-heading font-semibold group-hover:text-banquise-blue-lightest transition-colors duration-300">Stockage sécurisé</h3>
|
|
||||||
<p className="text-banquise-gray/80 leading-relaxed text-sm">Solutions de stockage distribuées avec redondance pour garantir l'intégrité et la durabilité de vos données</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-gradient-to-br from-banquise-blue-dark/10 to-banquise-blue-dark/5 backdrop-blur-lg rounded-2xl p-6 sm:p-8 flex flex-col items-center text-center transition-all duration-300 border border-banquise-blue-lightest/30 hover:-translate-y-3 hover:from-banquise-blue-dark/15 hover:to-banquise-blue-dark/8 hover:shadow-xl hover:border-banquise-blue-lightest/50 group">
|
|
||||||
<div className="text-3xl sm:text-4xl mb-4 sm:mb-6 text-white bg-gradient-to-br from-banquise-blue to-banquise-blue-light w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center rounded-2xl shadow-lg group-hover:scale-110 transition-transform duration-300">
|
|
||||||
🌐
|
|
||||||
</div>
|
|
||||||
<h3 className="text-lg sm:text-xl mb-3 sm:mb-4 text-banquise-gray font-heading font-semibold group-hover:text-banquise-blue-lightest transition-colors duration-300">Réseau optimisé</h3>
|
|
||||||
<p className="text-banquise-gray/80 leading-relaxed text-sm">Architecture réseau à haute disponibilité avec une faible latence pour vos applications critiques</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-gradient-to-br from-banquise-blue-dark/10 to-banquise-blue-dark/5 backdrop-blur-lg rounded-2xl p-6 sm:p-8 flex flex-col items-center text-center transition-all duration-300 border border-banquise-blue-lightest/30 hover:-translate-y-3 hover:from-banquise-blue-dark/15 hover:to-banquise-blue-dark/8 hover:shadow-xl hover:border-banquise-blue-lightest/50 group">
|
|
||||||
<div className="text-3xl sm:text-4xl mb-4 sm:mb-6 text-white bg-gradient-to-br from-banquise-blue to-banquise-blue-light w-16 h-16 sm:w-20 sm:h-20 flex items-center justify-center rounded-2xl shadow-lg group-hover:scale-110 transition-transform duration-300">
|
|
||||||
🛡️
|
|
||||||
</div>
|
|
||||||
<h3 className="text-lg sm:text-xl mb-3 sm:mb-4 text-banquise-gray font-heading font-semibold group-hover:text-banquise-blue-lightest transition-colors duration-300">Sécurité renforcée</h3>
|
|
||||||
<p className="text-banquise-gray/80 leading-relaxed text-sm">Protection contre les menaces avec systèmes de sécurité modernes et mises à jour régulières</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
@ -1,28 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
// Définir l'interface localement :
|
|
||||||
interface AccordionItemProps {
|
|
||||||
title: string;
|
|
||||||
children: React.ReactNode;
|
|
||||||
isOpen: boolean;
|
|
||||||
onToggle: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AccordionItem: React.FC<AccordionItemProps> = ({ title, children, isOpen, onToggle }) => (
|
|
||||||
<div className={`bg-gradient-to-br from-banquise-blue-dark/15 to-banquise-blue-dark/5 backdrop-blur-lg rounded-2xl overflow-hidden border border-banquise-blue-lightest/30 transition-all duration-300 shadow-sm ${isOpen ? 'shadow-xl border-banquise-blue-lightest/50 scale-[1.01]' : ''} hover:shadow-lg hover:border-banquise-blue-lightest/40`}>
|
|
||||||
<div
|
|
||||||
className="p-4 sm:p-6 md:p-8 cursor-pointer flex items-center justify-between font-semibold text-banquise-gray transition-all duration-200 text-base sm:text-lg select-none hover:bg-banquise-blue-dark/10 active:bg-banquise-blue-dark/15"
|
|
||||||
onClick={onToggle}
|
|
||||||
>
|
|
||||||
<span className="flex items-center flex-1 mr-4 font-heading">{title}</span>
|
|
||||||
<span className={`text-xl sm:text-2xl transition-transform duration-300 text-banquise-blue-lightest flex-shrink-0 ${isOpen ? 'rotate-180' : ''}`}>
|
|
||||||
▼
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className={`transition-all duration-500 overflow-hidden ${isOpen ? 'max-h-[1000px] pb-4 px-4 sm:pb-6 sm:px-6 md:pb-8 md:px-8' : 'max-h-0'}`}>
|
|
||||||
<div className="text-banquise-gray/90 leading-relaxed text-sm sm:text-base">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
@ -1,146 +0,0 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
|
|
||||||
export const ParallaxBackground: React.FC = () => {
|
|
||||||
const [scrollY, setScrollY] = useState(0);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const handleScroll = () => {
|
|
||||||
setScrollY(window.scrollY);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('scroll', handleScroll);
|
|
||||||
return () => window.removeEventListener('scroll', handleScroll);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Éléments flottants avec différentes vitesses de parallaxe
|
|
||||||
const floatingElements = [
|
|
||||||
// Serveurs et équipements
|
|
||||||
{ icon: '🖥️', x: 10, y: 20, speed: 0.3, size: 'text-2xl', opacity: 0.1 },
|
|
||||||
{ icon: '🖲️', x: 85, y: 15, speed: 0.2, size: 'text-xl', opacity: 0.08 },
|
|
||||||
{ icon: '⚙️', x: 75, y: 45, speed: 0.4, size: 'text-3xl', opacity: 0.12 },
|
|
||||||
{ icon: '🔧', x: 15, y: 60, speed: 0.25, size: 'text-lg', opacity: 0.06 },
|
|
||||||
{ icon: '💾', x: 90, y: 70, speed: 0.35, size: 'text-2xl', opacity: 0.1 },
|
|
||||||
|
|
||||||
// Code et développement
|
|
||||||
{ icon: '<>', x: 30, y: 35, speed: 0.15, size: 'text-xl', opacity: 0.08, isText: true },
|
|
||||||
{ icon: '{ }', x: 60, y: 25, speed: 0.28, size: 'text-2xl', opacity: 0.1, isText: true },
|
|
||||||
{ icon: '#!/bin', x: 5, y: 80, speed: 0.2, size: 'text-sm', opacity: 0.06, isText: true },
|
|
||||||
{ icon: 'git', x: 80, y: 85, speed: 0.32, size: 'text-lg', opacity: 0.08, isText: true },
|
|
||||||
|
|
||||||
// Réseau et connectivité
|
|
||||||
{ icon: '🌐', x: 45, y: 10, speed: 0.22, size: 'text-2xl', opacity: 0.09 },
|
|
||||||
{ icon: '🔗', x: 25, y: 75, speed: 0.18, size: 'text-xl', opacity: 0.07 },
|
|
||||||
{ icon: '📡', x: 70, y: 55, speed: 0.26, size: 'text-lg', opacity: 0.08 },
|
|
||||||
|
|
||||||
// Sécurité
|
|
||||||
{ icon: '🔒', x: 55, y: 40, speed: 0.3, size: 'text-xl', opacity: 0.09 },
|
|
||||||
{ icon: '🛡️', x: 35, y: 65, speed: 0.24, size: 'text-2xl', opacity: 0.1 },
|
|
||||||
{ icon: '🔑', x: 85, y: 30, speed: 0.16, size: 'text-lg', opacity: 0.07 },
|
|
||||||
|
|
||||||
// Données et stockage
|
|
||||||
{ icon: '💿', x: 20, y: 45, speed: 0.28, size: 'text-xl', opacity: 0.08 },
|
|
||||||
{ icon: '📊', x: 65, y: 75, speed: 0.22, size: 'text-2xl', opacity: 0.09 },
|
|
||||||
{ icon: '📈', x: 40, y: 20, speed: 0.34, size: 'text-lg', opacity: 0.07 },
|
|
||||||
|
|
||||||
// Éléments techniques supplémentaires
|
|
||||||
{ icon: 'sudo', x: 12, y: 90, speed: 0.19, size: 'text-sm', opacity: 0.06, isText: true },
|
|
||||||
{ icon: 'SSH', x: 78, y: 12, speed: 0.31, size: 'text-base', opacity: 0.08, isText: true },
|
|
||||||
{ icon: 'API', x: 92, y: 50, speed: 0.27, size: 'text-lg', opacity: 0.09, isText: true },
|
|
||||||
{ icon: 'TCP', x: 8, y: 30, speed: 0.23, size: 'text-base', opacity: 0.07, isText: true },
|
|
||||||
{ icon: 'HTTP', x: 50, y: 80, speed: 0.29, size: 'text-sm', opacity: 0.06, isText: true },
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="fixed inset-0 pointer-events-none overflow-hidden z-0">
|
|
||||||
{/* Grille de fond subtile */}
|
|
||||||
<div className="absolute inset-0 opacity-[0.02]">
|
|
||||||
<div
|
|
||||||
className="absolute inset-0 bg-gradient-to-br from-banquise-blue-dark/20 to-transparent"
|
|
||||||
style={{
|
|
||||||
backgroundImage: `
|
|
||||||
linear-gradient(rgba(31, 93, 137, 0.03) 1px, transparent 1px),
|
|
||||||
linear-gradient(90deg, rgba(31, 93, 137, 0.03) 1px, transparent 1px)
|
|
||||||
`,
|
|
||||||
backgroundSize: '50px 50px',
|
|
||||||
transform: `translateY(${scrollY * 0.1}px)`
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Particules de code flottantes */}
|
|
||||||
<div className="absolute inset-0">
|
|
||||||
{floatingElements.map((element, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={`absolute ${element.size} font-mono select-none transition-all duration-1000 ease-out`}
|
|
||||||
style={{
|
|
||||||
left: `${element.x}%`,
|
|
||||||
top: `${element.y}%`,
|
|
||||||
transform: `translateY(${scrollY * element.speed}px) rotate(${scrollY * 0.01}deg)`,
|
|
||||||
opacity: element.opacity,
|
|
||||||
color: element.isText ? '#a8daff' : 'inherit',
|
|
||||||
textShadow: element.isText ? '0 0 10px rgba(168, 218, 255, 0.3)' : 'none',
|
|
||||||
filter: 'blur(0.5px)',
|
|
||||||
animation: `float-${index % 3} ${6 + (index % 4)}s ease-in-out infinite`
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{element.icon}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Lignes de connexion animées */}
|
|
||||||
<svg
|
|
||||||
className="absolute inset-0 w-full h-full opacity-[0.03]"
|
|
||||||
style={{
|
|
||||||
transform: `translateY(${scrollY * 0.2}px)`
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<defs>
|
|
||||||
<linearGradient id="lineGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
||||||
<stop offset="0%" stopColor="#a8daff" stopOpacity="0" />
|
|
||||||
<stop offset="50%" stopColor="#a8daff" stopOpacity="0.5" />
|
|
||||||
<stop offset="100%" stopColor="#a8daff" stopOpacity="0" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
|
|
||||||
{/* Lignes de connexion entre les éléments */}
|
|
||||||
{[...Array(8)].map((_, i) => (
|
|
||||||
<line
|
|
||||||
key={i}
|
|
||||||
x1={`${10 + i * 12}%`}
|
|
||||||
y1={`${20 + i * 8}%`}
|
|
||||||
x2={`${30 + i * 15}%`}
|
|
||||||
y2={`${40 + i * 12}%`}
|
|
||||||
stroke="url(#lineGradient)"
|
|
||||||
strokeWidth="1"
|
|
||||||
className="animate-pulse"
|
|
||||||
style={{
|
|
||||||
animationDelay: `${i * 0.5}s`,
|
|
||||||
animationDuration: `${3 + i}s`
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
{/* Cercles de données en mouvement */}
|
|
||||||
<div className="absolute inset-0">
|
|
||||||
{[...Array(6)].map((_, i) => (
|
|
||||||
<div
|
|
||||||
key={i}
|
|
||||||
className="absolute rounded-full border border-banquise-blue-lightest/5 animate-ping"
|
|
||||||
style={{
|
|
||||||
left: `${15 + i * 15}%`,
|
|
||||||
top: `${25 + i * 12}%`,
|
|
||||||
width: `${40 + i * 20}px`,
|
|
||||||
height: `${40 + i * 20}px`,
|
|
||||||
transform: `translateY(${scrollY * (0.1 + i * 0.05)}px)`,
|
|
||||||
animationDelay: `${i * 1.2}s`,
|
|
||||||
animationDuration: `${4 + i}s`
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,141 +0,0 @@
|
|||||||
import React, { useEffect } from 'react';
|
|
||||||
import { URLS } from '../../config/constants';
|
|
||||||
|
|
||||||
interface Service {
|
|
||||||
name: string;
|
|
||||||
url: string;
|
|
||||||
image: string;
|
|
||||||
icon: string;
|
|
||||||
description: string;
|
|
||||||
features: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PopupProps {
|
|
||||||
service: Service;
|
|
||||||
onClose: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Popup: React.FC<PopupProps> = ({ service, onClose }) => {
|
|
||||||
// Empêcher le scroll du body quand la popup est ouverte
|
|
||||||
useEffect(() => {
|
|
||||||
document.body.style.overflow = 'hidden';
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.body.style.overflow = 'unset';
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="fixed inset-0 bg-black/60 flex justify-center items-center z-50 p-4 backdrop-blur-md animate-fadeIn">
|
|
||||||
<div className="bg-white text-banquise-blue-dark rounded-3xl max-w-4xl w-full max-h-[90vh] shadow-2xl relative animate-slideUp border border-banquise-blue-lightest/20 overflow-hidden">
|
|
||||||
|
|
||||||
{/* Bouton de fermeture fixe au-dessus du contenu */}
|
|
||||||
<div className="absolute top-4 right-4 z-50">
|
|
||||||
<button
|
|
||||||
onClick={onClose}
|
|
||||||
className="bg-white/90 hover:bg-white border border-banquise-blue/20 text-xl cursor-pointer text-banquise-blue-dark flex items-center justify-center w-10 h-10 sm:w-12 sm:h-12 rounded-full transition-all duration-200 hover:scale-110 active:scale-95 shadow-lg backdrop-blur-sm"
|
|
||||||
aria-label="Fermer la popup"
|
|
||||||
>
|
|
||||||
×
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Contenu avec scroll vertical uniquement */}
|
|
||||||
<div className="overflow-y-auto overflow-x-hidden max-h-[90vh] popup-content">
|
|
||||||
{/* Header */}
|
|
||||||
<div className="relative bg-gradient-to-r from-banquise-blue to-banquise-blue-light p-6 sm:p-8 text-white pr-16 sm:pr-20">
|
|
||||||
<div className="flex flex-col lg:flex-row items-center lg:items-start mb-4">
|
|
||||||
<div className="w-16 h-16 sm:w-20 sm:h-20 lg:w-24 lg:h-24 bg-white/20 rounded-3xl flex items-center justify-center text-3xl sm:text-4xl lg:text-5xl mb-4 lg:mb-0 lg:mr-8 backdrop-blur-sm">
|
|
||||||
{service.icon}
|
|
||||||
</div>
|
|
||||||
<div className="text-center lg:text-left flex-1">
|
|
||||||
<h2 className="font-heading text-2xl sm:text-3xl lg:text-4xl mt-0 mb-3 lg:mb-4 leading-tight font-bold text-white">
|
|
||||||
{service.name}
|
|
||||||
</h2>
|
|
||||||
<div className="text-white/90 text-base sm:text-lg lg:text-xl font-medium">
|
|
||||||
Service d'hébergement professionnel
|
|
||||||
</div>
|
|
||||||
<div className="mt-4 lg:mt-6 flex flex-wrap gap-2 justify-center lg:justify-start">
|
|
||||||
<span className="bg-white/20 text-white px-3 py-1 rounded-full text-sm font-medium backdrop-blur-sm">Haute disponibilité</span>
|
|
||||||
<span className="bg-white/20 text-white px-3 py-1 rounded-full text-sm font-medium backdrop-blur-sm">Open Source</span>
|
|
||||||
<span className="bg-white/20 text-white px-3 py-1 rounded-full text-sm font-medium backdrop-blur-sm">Communautaire</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Content - Forcer le fond blanc */}
|
|
||||||
<div className="p-6 sm:p-8 bg-white">
|
|
||||||
{/* Description */}
|
|
||||||
<h3 className="text-xl sm:text-2xl lg:text-3xl mb-4 lg:mb-6 text-banquise-blue-dark font-heading font-bold flex items-center">
|
|
||||||
<span className="text-xl sm:text-2xl lg:text-3xl mr-3">📋</span>
|
|
||||||
Description détaillée
|
|
||||||
</h3>
|
|
||||||
<div className="bg-gradient-to-br from-banquise-blue/5 to-banquise-blue-light/5 rounded-2xl p-4 lg:p-6 border border-banquise-blue/10 mb-8">
|
|
||||||
<p className="text-banquise-blue-dark/90 leading-relaxed text-base sm:text-lg lg:text-xl mb-4">
|
|
||||||
{service.description}
|
|
||||||
</p>
|
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mt-6">
|
|
||||||
<div className="flex items-center p-3 bg-white/60 rounded-xl border border-banquise-blue/10">
|
|
||||||
<div className="w-10 h-10 bg-gradient-to-br from-banquise-blue to-banquise-blue-light rounded-lg flex items-center justify-center text-white mr-3">
|
|
||||||
✓
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="font-semibold text-banquise-blue-dark text-sm">99.9% Uptime</div>
|
|
||||||
<div className="text-banquise-blue-dark/70 text-xs">Disponibilité garantie</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center p-3 bg-white/60 rounded-xl border border-banquise-blue/10">
|
|
||||||
<div className="w-10 h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg flex items-center justify-center text-white mr-3">
|
|
||||||
🔒
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="font-semibold text-banquise-blue-dark text-sm">Sécurisé</div>
|
|
||||||
<div className="text-banquise-blue-dark/70 text-xs">SSL & Backups</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Fonctionnalités */}
|
|
||||||
<h3 className="text-xl sm:text-2xl lg:text-3xl mb-4 lg:mb-6 text-banquise-blue-dark font-heading font-bold flex items-center">
|
|
||||||
<span className="text-xl sm:text-2xl lg:text-3xl mr-3">⚡</span>
|
|
||||||
Fonctionnalités principales
|
|
||||||
</h3>
|
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-8">
|
|
||||||
{service.features.map((feature, index) => (
|
|
||||||
<div key={index} className="flex items-start bg-banquise-blue/5 rounded-xl p-4 border border-banquise-blue/10 hover:bg-banquise-blue/10 transition-colors duration-200 group">
|
|
||||||
<div className="w-6 h-6 bg-gradient-to-br from-banquise-blue to-banquise-blue-light rounded-full flex items-center justify-center mr-3 mt-0.5 flex-shrink-0 group-hover:scale-110 transition-transform duration-200">
|
|
||||||
<div className="w-2 h-2 bg-white rounded-full"></div>
|
|
||||||
</div>
|
|
||||||
<span className="text-banquise-blue-dark/90 font-medium text-sm lg:text-base leading-relaxed">{feature}</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Call to action */}
|
|
||||||
<div className="pt-6 lg:pt-8 border-t border-banquise-blue/10">
|
|
||||||
<a
|
|
||||||
href={service.url}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="w-full inline-flex items-center justify-center bg-gradient-to-r from-banquise-blue to-banquise-blue-light text-white border-0 py-4 px-6 sm:px-8 rounded-2xl cursor-pointer no-underline font-bold tracking-wide shadow-lg transition-all duration-300 hover:shadow-xl hover:-translate-y-1 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-banquise-blue-light text-base lg:text-lg hover:scale-[1.02] active:scale-95"
|
|
||||||
>
|
|
||||||
<span className="mr-3 text-xl lg:text-2xl">🚀</span>
|
|
||||||
<span>Accéder à {service.name}</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<p className="text-center text-sm text-banquise-blue-dark/60 mt-4">
|
|
||||||
Besoin d'aide ? Rejoignez notre <a href={URLS.social.discord} className="text-banquise-blue hover:text-banquise-blue-dark transition-colors duration-200 font-medium">Discord</a> pour obtenir du support
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Decorative elements */}
|
|
||||||
<div className="absolute top-0 right-0 w-16 h-16 sm:w-24 sm:h-24 lg:w-32 lg:h-32 bg-banquise-blue-lightest/10 rounded-full -translate-y-8 translate-x-8 sm:-translate-y-12 sm:translate-x-12 lg:-translate-y-16 lg:translate-x-16 hidden sm:block pointer-events-none"></div>
|
|
||||||
<div className="absolute bottom-0 left-0 w-12 h-12 sm:w-16 sm:h-16 lg:w-24 lg:h-24 bg-banquise-blue/5 rounded-full translate-y-6 -translate-x-6 sm:translate-y-8 sm:-translate-x-8 lg:translate-y-12 lg:-translate-x-12 hidden sm:block pointer-events-none"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,51 +0,0 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
|
|
||||||
export const ScrollToTopButton: React.FC = () => {
|
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const toggleVisibility = () => {
|
|
||||||
// Afficher le bouton après avoir scrollé 300px
|
|
||||||
setIsVisible(window.scrollY > 300);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('scroll', toggleVisibility);
|
|
||||||
return () => window.removeEventListener('scroll', toggleVisibility);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const scrollToTop = () => {
|
|
||||||
window.scrollTo({
|
|
||||||
top: 0,
|
|
||||||
behavior: 'smooth'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
onClick={scrollToTop}
|
|
||||||
className={`fixed bottom-6 right-6 z-50 w-12 h-12 sm:w-14 sm:h-14 bg-gradient-to-r from-banquise-blue to-banquise-blue-light text-white rounded-full shadow-lg hover:shadow-xl transition-all duration-300 flex items-center justify-center group border border-banquise-blue-lightest/30 backdrop-blur-sm ${
|
|
||||||
isVisible
|
|
||||||
? 'opacity-100 translate-y-0 scale-100'
|
|
||||||
: 'opacity-0 translate-y-4 scale-95 pointer-events-none'
|
|
||||||
}`}
|
|
||||||
aria-label="Retour en haut de page"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
className="w-5 h-5 sm:w-6 sm:h-6 transition-transform duration-300 group-hover:-translate-y-0.5"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth={2.5}
|
|
||||||
d="M7 11l5-5m0 0l5 5m-5-5v12"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
{/* Effet de lueur au hover */}
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light to-banquise-blue rounded-full opacity-0 group-hover:opacity-75 transition-opacity duration-300 blur-sm"></div>
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,20 +0,0 @@
|
|||||||
export const URLS = {
|
|
||||||
services: {
|
|
||||||
wiki: "https://wiki.la-banquise.fr",
|
|
||||||
gitea: "https://git.la-banquise.fr",
|
|
||||||
panel: "https://panel.la-banquise.fr",
|
|
||||||
auth: "https://auth.la-banquise.fr"
|
|
||||||
},
|
|
||||||
social: {
|
|
||||||
discord: "https://discord.gg/labanquise"
|
|
||||||
},
|
|
||||||
contact: {
|
|
||||||
email: "mailto:contact@la-banquise.fr"
|
|
||||||
}
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const SITE_CONFIG = {
|
|
||||||
name: "La Banquise",
|
|
||||||
description: "Association d'hébergement et lab réseau pour tous les étudiants et associations de l'EPITA",
|
|
||||||
tagline: "Communauté • Hébergement"
|
|
||||||
} as const;
|
|
@ -1,185 +0,0 @@
|
|||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
||||||
/* Variables CSS pour les polices */
|
|
||||||
:root {
|
|
||||||
--font-heading: 'Dela Gothic One', sans-serif;
|
|
||||||
--font-body: 'Roboto', sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parallax animations */
|
|
||||||
@keyframes parallax-slow {
|
|
||||||
0% { transform: translateY(0px); }
|
|
||||||
100% { transform: translateY(-50px); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes parallax-medium {
|
|
||||||
0% { transform: translateY(0px); }
|
|
||||||
100% { transform: translateY(-80px); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes parallax-fast {
|
|
||||||
0% { transform: translateY(0px); }
|
|
||||||
100% { transform: translateY(-120px); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes parallax-very-slow {
|
|
||||||
0% { transform: translateY(0px); }
|
|
||||||
100% { transform: translateY(-20px); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Floating animations with different speeds */
|
|
||||||
@keyframes float-slow {
|
|
||||||
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
|
||||||
50% { transform: translateY(-20px) rotate(5deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes float-medium {
|
|
||||||
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
|
||||||
50% { transform: translateY(-15px) rotate(-3deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes float-fast {
|
|
||||||
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
|
||||||
50% { transform: translateY(-10px) rotate(3deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes float-very-slow {
|
|
||||||
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
|
||||||
50% { transform: translateY(-30px) rotate(-2deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Animations pour les éléments flottants */
|
|
||||||
@keyframes float-0 {
|
|
||||||
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
|
||||||
50% { transform: translateY(-10px) rotate(2deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes float-1 {
|
|
||||||
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
|
||||||
33% { transform: translateY(-8px) rotate(-1deg); }
|
|
||||||
66% { transform: translateY(-15px) rotate(1deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes float-2 {
|
|
||||||
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
|
||||||
25% { transform: translateY(-12px) rotate(1deg); }
|
|
||||||
75% { transform: translateY(-6px) rotate(-2deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Animation pour l'élément principal du hero */
|
|
||||||
@keyframes gentle-float {
|
|
||||||
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
|
||||||
50% { transform: translateY(-15px) rotate(1deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate-gentle-float {
|
|
||||||
animation: gentle-float 6s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Effet de lueur pour les éléments techniques */
|
|
||||||
@keyframes glow-pulse {
|
|
||||||
0%, 100% {
|
|
||||||
text-shadow: 0 0 5px rgba(168, 218, 255, 0.3),
|
|
||||||
0 0 10px rgba(168, 218, 255, 0.2),
|
|
||||||
0 0 15px rgba(168, 218, 255, 0.1);
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
text-shadow: 0 0 10px rgba(168, 218, 255, 0.4),
|
|
||||||
0 0 20px rgba(168, 218, 255, 0.3),
|
|
||||||
0 0 30px rgba(168, 218, 255, 0.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Animation des lignes de connexion */
|
|
||||||
@keyframes data-flow {
|
|
||||||
0% { stroke-dasharray: 0, 100; }
|
|
||||||
50% { stroke-dasharray: 50, 100; }
|
|
||||||
100% { stroke-dasharray: 100, 100; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive pour les animations */
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
.animate-gentle-float,
|
|
||||||
.animate-ping,
|
|
||||||
.animate-pulse {
|
|
||||||
animation: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Apply animations */
|
|
||||||
.animate-parallax-slow {
|
|
||||||
animation: parallax-slow 20s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate-parallax-medium {
|
|
||||||
animation: parallax-medium 15s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate-parallax-fast {
|
|
||||||
animation: parallax-fast 10s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate-parallax-very-slow {
|
|
||||||
animation: parallax-very-slow 30s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate-float-slow {
|
|
||||||
animation: float-slow 8s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate-float-medium {
|
|
||||||
animation: float-medium 6s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate-float-fast {
|
|
||||||
animation: float-fast 4s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate-float-very-slow {
|
|
||||||
animation: float-very-slow 12s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Amélioration du scroll */
|
|
||||||
html {
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Empêcher le scroll horizontal global */
|
|
||||||
body {
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Styles pour les popups */
|
|
||||||
.popup-content {
|
|
||||||
scrollbar-width: thin;
|
|
||||||
scrollbar-color: rgba(31, 93, 137, 0.3) transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-content::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-content::-webkit-scrollbar-track {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-content::-webkit-scrollbar-thumb {
|
|
||||||
background: rgba(31, 93, 137, 0.3);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-content::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: rgba(31, 93, 137, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Animation pour le bouton scroll to top */
|
|
||||||
@keyframes bounce-up {
|
|
||||||
0%, 100% { transform: translateY(0px); }
|
|
||||||
50% { transform: translateY(-4px); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll-to-top:hover {
|
|
||||||
animation: bounce-up 0.6s ease-in-out;
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
import { StrictMode } from 'react'
|
|
||||||
import { createRoot } from 'react-dom/client'
|
|
||||||
import './index.css'
|
|
||||||
import App from './App.tsx'
|
|
||||||
|
|
||||||
// Ajouter les métadonnées SEO
|
|
||||||
document.title = 'La Banquise - Hébergement et Communauté Tech';
|
|
||||||
const metaDescription = document.createElement('meta');
|
|
||||||
metaDescription.name = 'description';
|
|
||||||
metaDescription.content = 'Association d\'hébergement et lab réseau pour tous les étudiants et associations de l\'EPITA. Services Wiki, Gitea, Panel de jeux.';
|
|
||||||
document.head.appendChild(metaDescription);
|
|
||||||
|
|
||||||
const metaViewport = document.createElement('meta');
|
|
||||||
metaViewport.name = 'viewport';
|
|
||||||
metaViewport.content = 'width=device-width, initial-scale=1.0';
|
|
||||||
document.head.appendChild(metaViewport);
|
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
|
||||||
<StrictMode>
|
|
||||||
<App />
|
|
||||||
</StrictMode>,
|
|
||||||
)
|
|
@ -1,63 +0,0 @@
|
|||||||
export const commonStyles = {
|
|
||||||
// Gradients
|
|
||||||
gradients: {
|
|
||||||
primary: "bg-gradient-to-r from-banquise-blue to-banquise-blue-light",
|
|
||||||
primaryBr: "bg-gradient-to-br from-banquise-blue to-banquise-blue-light",
|
|
||||||
card: "bg-gradient-to-br from-banquise-blue-dark/10 to-banquise-blue-dark/5",
|
|
||||||
cardHover: "hover:from-banquise-blue-dark/15 hover:to-banquise-blue-dark/8",
|
|
||||||
discord: "bg-gradient-to-r from-indigo-600 to-purple-600",
|
|
||||||
discordHover: "hover:from-indigo-500 hover:to-purple-500"
|
|
||||||
},
|
|
||||||
|
|
||||||
// Buttons
|
|
||||||
buttons: {
|
|
||||||
primary: "inline-flex items-center justify-center font-bold text-white border-0 rounded-2xl transition-all duration-300 hover:shadow-xl hover:-translate-y-1 hover:scale-105 active:scale-95",
|
|
||||||
discord: "group relative overflow-hidden px-4 lg:px-6 py-2.5 lg:py-3 text-white font-semibold text-sm lg:text-base rounded-xl transition-all duration-300 hover:shadow-xl hover:shadow-indigo-500/25 hover:-translate-y-1 hover:scale-105",
|
|
||||||
auth: "group relative overflow-hidden px-4 lg:px-6 py-2.5 lg:py-3 text-white font-semibold text-sm lg:text-base rounded-xl transition-all duration-300 hover:shadow-xl hover:-translate-y-1 hover:scale-105"
|
|
||||||
},
|
|
||||||
|
|
||||||
// Cards
|
|
||||||
cards: {
|
|
||||||
base: "backdrop-blur-lg rounded-2xl border border-banquise-blue-lightest/30 transition-all duration-300",
|
|
||||||
hover: "hover:shadow-xl hover:border-banquise-blue-lightest/50",
|
|
||||||
interactive: "cursor-pointer hover:-translate-y-4 hover:shadow-2xl active:scale-95"
|
|
||||||
},
|
|
||||||
|
|
||||||
// Text - Hiérarchie améliorée
|
|
||||||
text: {
|
|
||||||
heading: "font-heading font-bold tracking-tight",
|
|
||||||
// Titres principaux de section
|
|
||||||
headingXl: "text-3xl sm:text-4xl md:text-5xl text-banquise-gray font-heading font-bold tracking-tight",
|
|
||||||
headingLg: "text-2xl sm:text-3xl md:text-4xl text-banquise-gray font-heading font-bold tracking-tight",
|
|
||||||
headingMd: "text-xl sm:text-2xl md:text-3xl text-banquise-blue-dark font-heading font-bold tracking-tight",
|
|
||||||
headingSm: "text-lg sm:text-xl md:text-2xl text-banquise-blue-dark font-heading font-semibold tracking-tight",
|
|
||||||
// Sous-titres
|
|
||||||
subheading: "text-base sm:text-lg md:text-xl text-banquise-gray/90 font-medium leading-relaxed",
|
|
||||||
// Corps de texte
|
|
||||||
body: "text-sm sm:text-base md:text-lg text-banquise-blue-dark/90 leading-relaxed",
|
|
||||||
description: "text-banquise-gray/80 leading-relaxed",
|
|
||||||
muted: "text-banquise-gray/90 leading-relaxed",
|
|
||||||
// Texte sur fond sombre
|
|
||||||
lightHeading: "text-banquise-blue-lightest font-heading font-bold tracking-tight",
|
|
||||||
lightBody: "text-white/90 leading-relaxed"
|
|
||||||
},
|
|
||||||
|
|
||||||
// Layout
|
|
||||||
layout: {
|
|
||||||
section: "py-12 sm:py-16 md:py-20 w-full max-w-6xl mx-auto px-4 sm:px-6 md:px-8",
|
|
||||||
container: "max-w-6xl mx-auto",
|
|
||||||
divider: "w-20 h-1 bg-gradient-to-r from-banquise-blue-lightest to-banquise-blue mx-auto mb-6 sm:mb-8 rounded-full"
|
|
||||||
},
|
|
||||||
|
|
||||||
// Icons and decorative elements
|
|
||||||
icons: {
|
|
||||||
base: "w-16 h-16 sm:w-20 sm:h-20 lg:w-24 lg:h-24 rounded-2xl flex items-center justify-center text-3xl sm:text-4xl lg:text-5xl shadow-lg",
|
|
||||||
small: "w-10 h-10 rounded-lg flex items-center justify-center text-white"
|
|
||||||
},
|
|
||||||
|
|
||||||
// Navigation
|
|
||||||
nav: {
|
|
||||||
link: "px-4 lg:px-6 py-2.5 lg:py-3 text-white/90 hover:text-white font-medium text-sm lg:text-base rounded-xl transition-all duration-300 hover:bg-white/10 hover:backdrop-blur-sm relative group",
|
|
||||||
mobileItem: "group flex items-center p-4 text-white/90 hover:text-white no-underline rounded-2xl hover:bg-gradient-to-r hover:from-banquise-blue/20 hover:to-banquise-blue-light/20 transition-all duration-300 border border-transparent hover:border-banquise-blue-lightest/20"
|
|
||||||
}
|
|
||||||
} as const;
|
|
@ -1,15 +0,0 @@
|
|||||||
export interface Service {
|
|
||||||
name: string;
|
|
||||||
url: string;
|
|
||||||
image: string;
|
|
||||||
description: string;
|
|
||||||
features: string[];
|
|
||||||
icon: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AccordionItemProps {
|
|
||||||
title: string;
|
|
||||||
children: React.ReactNode;
|
|
||||||
isOpen: boolean;
|
|
||||||
onToggle: () => void;
|
|
||||||
}
|
|
1
banquise-website/src/vite-env.d.ts
vendored
1
banquise-website/src/vite-env.d.ts
vendored
@ -1 +0,0 @@
|
|||||||
/// <reference types="vite/client" />
|
|
@ -1,119 +0,0 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
export default {
|
|
||||||
content: [
|
|
||||||
"./index.html",
|
|
||||||
"./src/**/*.{js,ts,jsx,tsx}",
|
|
||||||
],
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
colors: {
|
|
||||||
banquise: {
|
|
||||||
blue: '#40B4FF',
|
|
||||||
'blue-dark': '#1F5D89',
|
|
||||||
'blue-light': '#69B7E2',
|
|
||||||
'blue-lightest': '#A5F0FF',
|
|
||||||
gray: '#F6F6F6',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fontFamily: {
|
|
||||||
heading: ['Dela Gothic One', 'sans-serif'],
|
|
||||||
body: ['Roboto', 'sans-serif'],
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
'float': 'float 6s ease-in-out infinite',
|
|
||||||
'float-1': 'float1 5s ease-in-out infinite',
|
|
||||||
'float-2': 'float2 6s ease-in-out infinite',
|
|
||||||
'float-3': 'float3 7s ease-in-out infinite',
|
|
||||||
'wave': 'wave 10s linear infinite',
|
|
||||||
'wave-reverse': 'waveReverse 15s linear infinite',
|
|
||||||
'wave-1': 'wave 20s linear infinite',
|
|
||||||
'wave-2': 'waveReverse 15s linear infinite',
|
|
||||||
'wave-3': 'wave 12s linear infinite',
|
|
||||||
'rise': 'rise 10s infinite ease-in',
|
|
||||||
'tech-float': 'tech-float 10s ease-in-out infinite',
|
|
||||||
'gentle-float': 'gentle-float 6s ease-in-out infinite',
|
|
||||||
'fadeIn': 'fadeIn 0.2s ease-out',
|
|
||||||
'slideUp': 'slideUp 0.3s ease-out',
|
|
||||||
},
|
|
||||||
keyframes: {
|
|
||||||
float: {
|
|
||||||
'0%, 100%': { transform: 'translateY(0)' },
|
|
||||||
'50%': { transform: 'translateY(-10px)' },
|
|
||||||
},
|
|
||||||
float1: {
|
|
||||||
'0%, 100%': { transform: 'translateY(0)' },
|
|
||||||
'50%': { transform: 'translateY(-15px)' },
|
|
||||||
},
|
|
||||||
float2: {
|
|
||||||
'0%, 100%': { transform: 'translateY(0)' },
|
|
||||||
'50%': { transform: 'translateY(-20px)' },
|
|
||||||
},
|
|
||||||
float3: {
|
|
||||||
'0%, 100%': { transform: 'translateY(0)' },
|
|
||||||
'50%': { transform: 'translateY(-10px)' },
|
|
||||||
},
|
|
||||||
'tech-float': {
|
|
||||||
'0%, 100%': { transform: 'translateY(0) rotate(0deg)', opacity: '0.15' },
|
|
||||||
'50%': { transform: 'translateY(-20px) rotate(10deg)', opacity: '0.25' },
|
|
||||||
},
|
|
||||||
'gentle-float': {
|
|
||||||
'0%, 100%': { transform: 'translateY(0)' },
|
|
||||||
'50%': { transform: 'translateY(-10px)' },
|
|
||||||
},
|
|
||||||
wave: {
|
|
||||||
'0%': { backgroundPosition: '0' },
|
|
||||||
'100%': { backgroundPosition: '1200px' },
|
|
||||||
},
|
|
||||||
waveReverse: {
|
|
||||||
'0%': { backgroundPosition: '1200px' },
|
|
||||||
'100%': { backgroundPosition: '0' },
|
|
||||||
},
|
|
||||||
rise: {
|
|
||||||
'0%': {
|
|
||||||
bottom: '-100px',
|
|
||||||
transform: 'translateX(0)',
|
|
||||||
opacity: '0.8',
|
|
||||||
},
|
|
||||||
'50%': {
|
|
||||||
transform: 'translateX(40px)',
|
|
||||||
opacity: '0.4',
|
|
||||||
},
|
|
||||||
'100%': {
|
|
||||||
bottom: '1080px',
|
|
||||||
transform: 'translateX(-40px)',
|
|
||||||
opacity: '0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fadeIn: {
|
|
||||||
from: { opacity: '0' },
|
|
||||||
to: { opacity: '1' },
|
|
||||||
},
|
|
||||||
slideUp: {
|
|
||||||
from: { transform: 'translateY(30px)', opacity: '0' },
|
|
||||||
to: { transform: 'translateY(0)', opacity: '1' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
backdropBlur: {
|
|
||||||
'xs': '2px',
|
|
||||||
},
|
|
||||||
backgroundImage: {
|
|
||||||
'wave-pattern': "url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1200 120\" preserveAspectRatio=\"none\"><path d=\"M0,0V46.29c47.79,22.2,103.59,32.17,158,28,70.36-5.37,136.33-33.31,206.8-37.5C438.64,32.43,512.34,53.67,583,72.05c69.27,18,138.3,24.88,209.4,13.08,36.15-6,69.85-17.84,104.45-29.34C989.49,25,1113-14.29,1200,52.47V0Z\" opacity=\".25\" fill=\"%231F5D89\"/><path d=\"M0,0V15.81C13,36.92,27.64,56.86,47.69,72.05,99.41,111.27,165,111,224.58,91.58c31.15-10.15,60.09-26.07,89.67-39.8,40.92-19,84.73-46,130.83-49.67,36.26-2.85,70.9,9.42,98.6,31.56,31.77,25.39,62.32,62,103.63,73,40.44,10.79,81.35-6.69,119.13-24.28s75.16-39,116.92-43.05c59.73-5.85,113.28,22.88,168.9,38.84,30.2,8.66,59,6.17,87.09-7.5,22.43-10.89,48-26.93,60.65-49.24V0Z\" opacity=\".5\" fill=\"%231F5D89\"/><path d=\"M0,0V5.63C149.93,59,314.09,71.32,475.83,42.57c43-7.64,84.23-20.12,127.61-26.46,59-8.63,112.48,12.24,165.56,35.4C827.93,77.22,886,95.24,951.2,90c86.53-7,172.46-45.71,248.8-84.81V0Z\" fill=\"%231F5D89\"/></svg>')",
|
|
||||||
'ocean-gradient': 'linear-gradient(180deg, #40B4FF 0%, #69B7E2 50%, #1F5D89 100%)',
|
|
||||||
},
|
|
||||||
maxHeight: {
|
|
||||||
'0': '0',
|
|
||||||
'1000': '1000px',
|
|
||||||
},
|
|
||||||
spacing: {
|
|
||||||
'72': '18rem',
|
|
||||||
'80': '20rem',
|
|
||||||
'88': '22rem',
|
|
||||||
'96': '24rem',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
require('@tailwindcss/forms'),
|
|
||||||
require('@tailwindcss/typography'),
|
|
||||||
],
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
||||||
"target": "ES2020",
|
|
||||||
"useDefineForClassFields": true,
|
|
||||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
||||||
"module": "ESNext",
|
|
||||||
"skipLibCheck": true,
|
|
||||||
|
|
||||||
/* Bundler mode */
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowImportingTsExtensions": true,
|
|
||||||
"verbatimModuleSyntax": true,
|
|
||||||
"moduleDetection": "force",
|
|
||||||
"noEmit": true,
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
|
|
||||||
/* Linting */
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"erasableSyntaxOnly": true,
|
|
||||||
"noFallthroughCasesInSwitch": true,
|
|
||||||
"noUncheckedSideEffectImports": true
|
|
||||||
},
|
|
||||||
"include": ["src"]
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"files": [],
|
|
||||||
"references": [
|
|
||||||
{ "path": "./tsconfig.app.json" },
|
|
||||||
{ "path": "./tsconfig.node.json" }
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
||||||
"target": "ES2022",
|
|
||||||
"lib": ["ES2023"],
|
|
||||||
"module": "ESNext",
|
|
||||||
"skipLibCheck": true,
|
|
||||||
|
|
||||||
/* Bundler mode */
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowImportingTsExtensions": true,
|
|
||||||
"verbatimModuleSyntax": true,
|
|
||||||
"moduleDetection": "force",
|
|
||||||
"noEmit": true,
|
|
||||||
|
|
||||||
/* Linting */
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"erasableSyntaxOnly": true,
|
|
||||||
"noFallthroughCasesInSwitch": true,
|
|
||||||
"noUncheckedSideEffectImports": true
|
|
||||||
},
|
|
||||||
"include": ["vite.config.ts"]
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
import { defineConfig } from 'vite'
|
|
||||||
import react from '@vitejs/plugin-react'
|
|
||||||
import viteCompression from 'vite-plugin-compression'
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [
|
|
||||||
react(),
|
|
||||||
viteCompression({
|
|
||||||
verbose: false,
|
|
||||||
algorithm: 'gzip',
|
|
||||||
ext: '.gz',
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
build: {
|
|
||||||
minify: 'esbuild',
|
|
||||||
cssMinify: true,
|
|
||||||
rollupOptions: {
|
|
||||||
output: {
|
|
||||||
manualChunks: {
|
|
||||||
react: ['react', 'react-dom'],
|
|
||||||
router: ['react-router-dom'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
Loading…
x
Reference in New Issue
Block a user