Start project
This commit is contained in:
parent
38160791db
commit
f0100cfbbb
|
@ -0,0 +1,10 @@
|
||||||
|
module.exports = {
|
||||||
|
style: {
|
||||||
|
postcss: {
|
||||||
|
plugins: [
|
||||||
|
require('tailwindcss')('./tailwind.config.js'),
|
||||||
|
require('autoprefixer')
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"name": "simple-light-react",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@craco/craco": "^5.7.0",
|
||||||
|
"@tailwindcss/custom-forms": "^0.2.1",
|
||||||
|
"@testing-library/jest-dom": "^4.2.4",
|
||||||
|
"@testing-library/react": "^9.3.2",
|
||||||
|
"@testing-library/user-event": "^7.1.2",
|
||||||
|
"aos": "^3.0.0-beta.6",
|
||||||
|
"autoprefixer": "^9.8.6",
|
||||||
|
"cruip-js-toolkit": "^1.0.2",
|
||||||
|
"formik": "^2.2.2",
|
||||||
|
"node-sass": "^4.14.1",
|
||||||
|
"postcss-cli": "^7.1.2",
|
||||||
|
"react": "^16.13.1",
|
||||||
|
"react-dom": "^16.13.1",
|
||||||
|
"react-router-dom": "^5.2.0",
|
||||||
|
"react-scripts": "3.4.1",
|
||||||
|
"react-transition-group": "^4.4.1",
|
||||||
|
"tailwindcss": "^1.8.10"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "craco start",
|
||||||
|
"build": "craco build",
|
||||||
|
"test": "craco test",
|
||||||
|
"eject": "craco eject"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"extends": "react-app"
|
||||||
|
},
|
||||||
|
"browserslist": {
|
||||||
|
"production": [
|
||||||
|
">0.2%",
|
||||||
|
"not dead",
|
||||||
|
"not op_mini all"
|
||||||
|
],
|
||||||
|
"development": [
|
||||||
|
"last 1 chrome version",
|
||||||
|
"last 1 firefox version",
|
||||||
|
"last 1 safari version"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
|
@ -0,0 +1,43 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="icon" href="%PUBLIC_URL%/favicon.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Web site created using create-react-app"
|
||||||
|
/>
|
||||||
|
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||||
|
<!--
|
||||||
|
manifest.json provides metadata used when your web app is installed on a
|
||||||
|
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||||
|
-->
|
||||||
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
|
<!--
|
||||||
|
Notice the use of %PUBLIC_URL% in the tags above.
|
||||||
|
It will be replaced with the URL of the `public` folder during the build.
|
||||||
|
Only files inside the `public` folder can be referenced from the HTML.
|
||||||
|
|
||||||
|
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||||
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
|
-->
|
||||||
|
<title>Status Affilate</title>
|
||||||
|
</head>
|
||||||
|
<body class="font-inter antialiased bg-white text-gray-900 tracking-tight">
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
<!--
|
||||||
|
This HTML file is a template.
|
||||||
|
If you open it directly in the browser, you will see an empty page.
|
||||||
|
|
||||||
|
You can add webfonts, meta tags, or analytics to this file.
|
||||||
|
The build step will place the bundled scripts into the <body> tag.
|
||||||
|
|
||||||
|
To begin the development, run `npm start` or `yarn start`.
|
||||||
|
To create a production bundle, use `npm run build` or `yarn build`.
|
||||||
|
-->
|
||||||
|
</body>
|
||||||
|
</html>
|
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 9.4 KiB |
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"short_name": "React App",
|
||||||
|
"name": "Create React App Sample",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "favicon.ico",
|
||||||
|
"sizes": "64x64 32x32 24x24 16x16",
|
||||||
|
"type": "image/x-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "logo192.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "192x192"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "logo512.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "512x512"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": ".",
|
||||||
|
"display": "standalone",
|
||||||
|
"theme_color": "#000000",
|
||||||
|
"background_color": "#ffffff"
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
# https://www.robotstxt.org/robotstxt.html
|
||||||
|
User-agent: *
|
||||||
|
Disallow:
|
|
@ -0,0 +1,46 @@
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import {
|
||||||
|
Switch,
|
||||||
|
Route,
|
||||||
|
useLocation
|
||||||
|
} from 'react-router-dom';
|
||||||
|
|
||||||
|
import './css/style.scss';
|
||||||
|
|
||||||
|
import AOS from 'aos';
|
||||||
|
import { focusHandling } from 'cruip-js-toolkit';
|
||||||
|
|
||||||
|
import Home from './pages/Home';
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
AOS.init({
|
||||||
|
once: true,
|
||||||
|
disable: 'phone',
|
||||||
|
duration: 700,
|
||||||
|
easing: 'ease-out-cubic',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.querySelector('html').style.scrollBehavior = 'auto'
|
||||||
|
window.scroll({ top: 0 })
|
||||||
|
document.querySelector('html').style.scrollBehavior = ''
|
||||||
|
focusHandling('outline');
|
||||||
|
}, [location.pathname]); // triggered on route change
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Switch>
|
||||||
|
<Route exact path="/">
|
||||||
|
<Home />
|
||||||
|
</Route>
|
||||||
|
</Switch>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
|
@ -0,0 +1,9 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
test('renders learn react link', () => {
|
||||||
|
const { getByText } = render(<App />);
|
||||||
|
const linkElement = getByText(/learn react/i);
|
||||||
|
expect(linkElement).toBeInTheDocument();
|
||||||
|
});
|
|
@ -0,0 +1,55 @@
|
||||||
|
// Range slider
|
||||||
|
$range-thumb-size: 36px;
|
||||||
|
|
||||||
|
input[type=range] {
|
||||||
|
appearance: none;
|
||||||
|
background: #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
height: 6px;
|
||||||
|
margin-top: ($range-thumb-size - 6px) / 2;
|
||||||
|
margin-bottom: ($range-thumb-size - 6px) / 2;
|
||||||
|
--thumb-size: #{$range-thumb-size};
|
||||||
|
|
||||||
|
&::-webkit-slider-thumb {
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
background-color: #000;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 .5v7L12 4zM0 4l4 3.5v-7z' fill='%23FFF' fillRule='nonzero'/%3E%3C/svg%3E");
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
height: $range-thumb-size;
|
||||||
|
width: $range-thumb-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-moz-range-thumb {
|
||||||
|
background-color: #000;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 .5v7L12 4zM0 4l4 3.5v-7z' fill='%23FFF' fillRule='nonzero'/%3E%3C/svg%3E");
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
border: 0;
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
height: $range-thumb-size;
|
||||||
|
width: $range-thumb-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-ms-thumb {
|
||||||
|
background-color: #000;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 .5v7L12 4zM0 4l4 3.5v-7z' fill='%23FFF' fillRule='nonzero'/%3E%3C/svg%3E");
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
height: $range-thumb-size;
|
||||||
|
width: $range-thumb-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-moz-focus-outer {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
:focus,
|
||||||
|
button:focus,
|
||||||
|
.btn:focus,
|
||||||
|
.btn-sm:focus {
|
||||||
|
outline: 2px solid rgba(#0070F4, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.a-links {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accept-tnc {
|
||||||
|
color: white;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.see-tnc {
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hamburger button
|
||||||
|
.hamburger {
|
||||||
|
|
||||||
|
svg > * {
|
||||||
|
|
||||||
|
&:nth-child(1),
|
||||||
|
&:nth-child(2),
|
||||||
|
&:nth-child(3) {
|
||||||
|
transform-origin: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(1) {
|
||||||
|
transition: y 0.1s 0.25s ease-in, transform 0.22s cubic-bezier(0.55, 0.055, 0.675, 0.19), opacity 0.1s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
transition: transform 0.22s cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
transition: y 0.1s 0.25s ease-in, transform 0.22s cubic-bezier(0.55, 0.055, 0.675, 0.19), width 0.1s 0.25s ease-in;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
|
||||||
|
svg > * {
|
||||||
|
|
||||||
|
&:nth-child(1) {
|
||||||
|
opacity: 0;
|
||||||
|
y: 11;
|
||||||
|
transform: rotate(225deg);
|
||||||
|
transition: y 0.1s ease-out, transform 0.22s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1), opacity 0.1s 0.12s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
transform: rotate(225deg);
|
||||||
|
transition: transform 0.22s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
y: 11;
|
||||||
|
transform: rotate(135deg);
|
||||||
|
transition: y 0.1s ease-out, transform 0.22s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1), width 0.1s ease-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur {
|
||||||
|
backdrop-filter: blur(3px);
|
||||||
|
-webkit-backdrop-filter: blur(3px);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pulsing animation
|
||||||
|
@keyframes pulseLoop {
|
||||||
|
0% { opacity: .15; transform: scale(1) translateZ(0); }
|
||||||
|
30% { opacity: .15; }
|
||||||
|
60% { opacity: 0; }
|
||||||
|
80% { opacity: 0; transform: scale(1.8) translateZ(0); }
|
||||||
|
}
|
||||||
|
@keyframes pulseMiniLoop {
|
||||||
|
0% { opacity: 0; transform: scale(1) translateZ(0); }
|
||||||
|
30% { opacity: .3; }
|
||||||
|
50% { opacity: .3; }
|
||||||
|
80% { opacity: 0; transform: scale(3) translateZ(0); }
|
||||||
|
}
|
||||||
|
.pulse {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 0;
|
||||||
|
transform-origin: center;
|
||||||
|
animation: pulseLoop 10000ms linear infinite;
|
||||||
|
}
|
||||||
|
.pulse-mini {
|
||||||
|
animation: pulseMiniLoop 6000ms linear infinite;
|
||||||
|
}
|
||||||
|
.pulse-1 {
|
||||||
|
animation-delay: -3000ms;
|
||||||
|
}
|
||||||
|
.pulse-2 {
|
||||||
|
animation-delay: -6000ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animations delay
|
||||||
|
.animation-delay-500 {
|
||||||
|
animation-delay: 500ms !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animation-delay-1000 {
|
||||||
|
animation-delay: 1000ms !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.translate-z-0 {
|
||||||
|
transform: translateZ(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom AOS animations
|
||||||
|
[data-aos="zoom-y-out"] {
|
||||||
|
transform: scaleX(1.03);
|
||||||
|
opacity: 0;
|
||||||
|
transition-property: transform, opacity;
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Switch element
|
||||||
|
.form-switch {
|
||||||
|
|
||||||
|
@apply relative select-none;
|
||||||
|
width: 68px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
@apply block overflow-hidden cursor-pointer rounded;
|
||||||
|
height: 38px;
|
||||||
|
|
||||||
|
> span:first-child {
|
||||||
|
@apply absolute block rounded shadow;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
top: 4px;
|
||||||
|
left: 4px;
|
||||||
|
right: 50%;
|
||||||
|
transition: all .15s ease-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
|
||||||
|
&:checked {
|
||||||
|
|
||||||
|
+ label {
|
||||||
|
@apply bg-blue-600;
|
||||||
|
|
||||||
|
> span:first-child {
|
||||||
|
left: 34px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Typography
|
||||||
|
.h1 {
|
||||||
|
@apply text-4xl font-extrabold leading-tight tracking-tighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h2 {
|
||||||
|
@apply text-3xl font-extrabold leading-tight tracking-tighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h3 {
|
||||||
|
@apply text-3xl font-bold leading-tight;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h4 {
|
||||||
|
@apply text-2xl font-bold leading-snug tracking-tight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@screen md {
|
||||||
|
.h1 {
|
||||||
|
@apply text-5xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h2 {
|
||||||
|
@apply text-4xl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
.btn,
|
||||||
|
.btn-sm {
|
||||||
|
@apply font-medium inline-flex items-center justify-center border border-transparent rounded leading-snug transition duration-150 ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
@apply px-8 py-3 shadow-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-sm {
|
||||||
|
@apply px-4 py-2 shadow;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;800;900&display=fallback');
|
||||||
|
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
|
||||||
|
// Additional styles
|
||||||
|
@import 'additional-styles/utility-patterns.scss';
|
||||||
|
@import 'additional-styles/range-slider.scss';
|
||||||
|
@import 'additional-styles/toggle-switch.scss';
|
||||||
|
@import 'additional-styles/theme.scss';
|
||||||
|
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
// Additional Tailwind directives: https://tailwindcss.com/docs/functions-and-directives/#responsive
|
||||||
|
@responsive {
|
||||||
|
.rtl {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See Alpine.js: https://github.com/alpinejs/alpine#x-cloak
|
||||||
|
[x-cloak] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AOS styles
|
||||||
|
$aos-distance: 10px;
|
||||||
|
@import 'node_modules/aos/src/sass/aos.scss';
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,19 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import { BrowserRouter as Router } from "react-router-dom";
|
||||||
|
import App from './App';
|
||||||
|
import * as serviceWorker from './serviceWorker';
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<Router>
|
||||||
|
<App />
|
||||||
|
</Router>
|
||||||
|
</React.StrictMode>,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
|
||||||
|
// If you want your app to work offline and load faster, you can change
|
||||||
|
// unregister() to register() below. Note this comes with some pitfalls.
|
||||||
|
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||||
|
serviceWorker.unregister();
|
|
@ -0,0 +1,30 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Header from '../partials/Header';
|
||||||
|
import HeroHome from '../partials/HeroHome';
|
||||||
|
import FormTemplate from '../partials/FormTemplate';
|
||||||
|
import Footer from '../partials/Footer';
|
||||||
|
|
||||||
|
function Home() {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col min-h-screen overflow-hidden">
|
||||||
|
|
||||||
|
{/* Site header */}
|
||||||
|
<Header />
|
||||||
|
|
||||||
|
{/* Page content */}
|
||||||
|
<main className="flex-grow">
|
||||||
|
|
||||||
|
{/* Page sections */}
|
||||||
|
<HeroHome />
|
||||||
|
<FormTemplate/>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{/* Site footer */}
|
||||||
|
<Footer />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Home;
|
|
@ -0,0 +1,104 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
function Footer() {
|
||||||
|
return (
|
||||||
|
<footer>
|
||||||
|
<div className="max-w-6xl mx-auto px-4 sm:px-6">
|
||||||
|
|
||||||
|
{/* Top area: Blocks */}
|
||||||
|
<div className="grid sm:grid-cols-12 gap-8 py-8 md:py-12 border-t border-gray-200">
|
||||||
|
|
||||||
|
{/* 1st block */}
|
||||||
|
<div className="sm:col-span-12 lg:col-span-3">
|
||||||
|
<div className="mb-2">
|
||||||
|
{/* Logo */}
|
||||||
|
<Link to="/" className="inline-block" aria-label="Cruip">
|
||||||
|
<svg width="40" height="40" viewBox="0 0 140 144" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fillRule="evenodd" clipRule="evenodd" d="M69.9259 0C31.3068 0 0 31.3405 0 70C0 108.66 31.3068 140 69.9259 140C108.545 140 139.852 108.66 139.852 70C139.852 31.3405 108.545 0 69.9259 0Z" fill="#4360DF"/>
|
||||||
|
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="140" height="140">
|
||||||
|
<path fillRule="evenodd" clipRule="evenodd" d="M69.9259 0C31.3068 0 0 31.3405 0 70C0 108.66 31.3068 140 69.9259 140C108.545 140 139.852 108.66 139.852 70C139.852 31.3405 108.545 0 69.9259 0Z" fill="white"/>
|
||||||
|
</mask>
|
||||||
|
<g mask="url(#mask0)">
|
||||||
|
<path fillRule="evenodd" clipRule="evenodd" d="M72.2742 66.9318C75.7855 67.2978 79.2968 67.6635 83.6137 67.4228C95.3098 66.77 102.395 60.7605 101.892 51.7778C101.38 42.6383 91.9539 37.0075 82.5228 37.534C67.1534 38.3913 55.8514 51.8993 54.5785 67.3383C56.6657 66.8488 58.8627 66.5565 60.9345 66.441C65.2516 66.2003 68.7629 66.566 72.2742 66.9318ZM42.1449 86.912C42.6299 95.29 51.5596 100.452 60.4947 99.9688C75.055 99.1828 85.7627 86.8005 86.9681 72.648C84.9907 73.0968 82.9097 73.365 80.9468 73.4708C76.8568 73.6915 73.5301 73.3563 70.2034 73.0208C66.8769 72.6855 63.5502 72.3503 59.4605 72.571C48.3805 73.1693 41.6679 78.6778 42.1449 86.912Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm text-gray-600">
|
||||||
|
<Link to="#" className="text-gray-600 hover:text-gray-900 hover:underline transition duration-150 ease-in-out">Terms</Link> · <Link to="#" className="text-gray-600 hover:text-gray-900 hover:underline transition duration-150 ease-in-out">Privacy Policy</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 2nd block */}
|
||||||
|
<div className="sm:col-span-6 md:col-span-3 lg:col-span-2">
|
||||||
|
<h6 className="text-gray-800 font-medium mb-2">STATUS NETWORK</h6>
|
||||||
|
<ul className="text-sm">
|
||||||
|
<li className="mb-2">
|
||||||
|
<Link to="#" className="text-gray-600 hover:text-gray-900 transition duration-150 ease-in-out">Status</Link>
|
||||||
|
</li>
|
||||||
|
<li className="mb-2">
|
||||||
|
<Link to="#" className="text-gray-600 hover:text-gray-900 transition duration-150 ease-in-out">Keycard</Link>
|
||||||
|
</li>
|
||||||
|
<li className="mb-2">
|
||||||
|
<Link to="#" className="text-gray-600 hover:text-gray-900 transition duration-150 ease-in-out">dap.ps</Link>
|
||||||
|
</li>
|
||||||
|
<li className="mb-2">
|
||||||
|
<Link to="#" className="text-gray-600 hover:text-gray-900 transition duration-150 ease-in-out">Assemble</Link>
|
||||||
|
</li>
|
||||||
|
<li className="mb-2">
|
||||||
|
<Link to="#" className="text-gray-600 hover:text-gray-900 transition duration-150 ease-in-out">Embark</Link>
|
||||||
|
</li>
|
||||||
|
<li className="mb-2">
|
||||||
|
<Link to="#" className="text-gray-600 hover:text-gray-900 transition duration-150 ease-in-out">Subspace</Link>
|
||||||
|
</li>
|
||||||
|
<li className="mb-2">
|
||||||
|
<Link to="#" className="text-gray-600 hover:text-gray-900 transition duration-150 ease-in-out">Vac</Link>
|
||||||
|
</li>
|
||||||
|
<li className="mb-2">
|
||||||
|
<Link to="#" className="text-gray-600 hover:text-gray-900 transition duration-150 ease-in-out">Nimbus</Link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom area */}
|
||||||
|
<div className="md:flex md:items-center md:justify-between py-4 md:py-8 border-t border-gray-200">
|
||||||
|
|
||||||
|
{/* Social links */}
|
||||||
|
<ul className="flex mb-4 md:order-1 md:ml-4 md:mb-0">
|
||||||
|
<li>
|
||||||
|
<Link to="#" className="flex justify-center items-center text-gray-600 hover:text-gray-900 bg-white hover:bg-white-100 rounded-full shadow transition duration-150 ease-in-out" aria-label="Twitter">
|
||||||
|
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M24 11.5c-.6.3-1.2.4-1.9.5.7-.4 1.2-1 1.4-1.8-.6.4-1.3.6-2.1.8-.6-.6-1.5-1-2.4-1-1.7 0-3.2 1.5-3.2 3.3 0 .3 0 .5.1.7-2.7-.1-5.2-1.4-6.8-3.4-.3.5-.4 1-.4 1.7 0 1.1.6 2.1 1.5 2.7-.5 0-1-.2-1.5-.4 0 1.6 1.1 2.9 2.6 3.2-.3.1-.6.1-.9.1-.2 0-.4 0-.6-.1.4 1.3 1.6 2.3 3.1 2.3-1.1.9-2.5 1.4-4.1 1.4H8c1.5.9 3.2 1.5 5 1.5 6 0 9.3-5 9.3-9.3v-.4c.7-.5 1.3-1.1 1.7-1.8z" />
|
||||||
|
</svg>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li className="ml-4">
|
||||||
|
<Link to="#" className="flex justify-center items-center text-gray-600 hover:text-gray-900 bg-white hover:bg-white-100 rounded-full shadow transition duration-150 ease-in-out" aria-label="Github">
|
||||||
|
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M16 8.2c-4.4 0-8 3.6-8 8 0 3.5 2.3 6.5 5.5 7.6.4.1.5-.2.5-.4V22c-2.2.5-2.7-1-2.7-1-.4-.9-.9-1.2-.9-1.2-.7-.5.1-.5.1-.5.8.1 1.2.8 1.2.8.7 1.3 1.9.9 2.3.7.1-.5.3-.9.5-1.1-1.8-.2-3.6-.9-3.6-4 0-.9.3-1.6.8-2.1-.1-.2-.4-1 .1-2.1 0 0 .7-.2 2.2.8.6-.2 1.3-.3 2-.3s1.4.1 2 .3c1.5-1 2.2-.8 2.2-.8.4 1.1.2 1.9.1 2.1.5.6.8 1.3.8 2.1 0 3.1-1.9 3.7-3.7 3.9.3.4.6.9.6 1.6v2.2c0 .2.1.5.6.4 3.2-1.1 5.5-4.1 5.5-7.6-.1-4.4-3.7-8-8.1-8z" />
|
||||||
|
</svg>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li className="ml-4">
|
||||||
|
<Link to="#" className="flex justify-center items-center text-gray-600 hover:text-gray-900 bg-white hover:bg-white-100 rounded-full shadow transition duration-150 ease-in-out" aria-label="Facebook">
|
||||||
|
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M14.023 24L14 17h-3v-3h3v-2c0-2.7 1.672-4 4.08-4 1.153 0 2.144.086 2.433.124v2.821h-1.67c-1.31 0-1.563.623-1.563 1.536V14H21l-1 3h-2.72v7h-3.257z" />
|
||||||
|
</svg>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* Copyrights note */}
|
||||||
|
<div className="text-sm text-gray-600 mr-4">The Status Network</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Footer;
|
|
@ -0,0 +1,147 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Formik, Field, Form } from 'formik';
|
||||||
|
|
||||||
|
const FormTemplate = () => {
|
||||||
|
|
||||||
|
const validate = (values) => {
|
||||||
|
const errors = {};
|
||||||
|
if (values.firstName !== '' && !values.firstName) {
|
||||||
|
errors.firstName = 'Required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values.lastName !== '' && !values.lastName) {
|
||||||
|
errors.lastName = 'Required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values.email !== '' && !values.email) {
|
||||||
|
errors.email = 'Required';
|
||||||
|
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
|
||||||
|
errors.email = 'Invalid email address';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values.emailConfirm !== '' && values.email !== values.emailConfirm) {
|
||||||
|
errors.emailConfirm = 'Please confirm your email address';
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<div className="max-w-6xl mx-auto px-4 sm:px-6">
|
||||||
|
<div className="pb-12 md:pb-20">
|
||||||
|
|
||||||
|
{/* CTA box */}
|
||||||
|
<div className="relative bg-gray-900 rounded py-10 px-8 md:py-16 md:px-12 shadow-2xl overflow-hidden" data-aos="zoom-y-out">
|
||||||
|
|
||||||
|
{/* Background illustration */}
|
||||||
|
<div className="absolute right-0 bottom-0 pointer-events-none hidden lg:block" aria-hidden="true">
|
||||||
|
<svg width="428" height="328" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<radialGradient cx="35.542%" cy="34.553%" fx="35.542%" fy="34.553%" r="96.031%" id="ni-a">
|
||||||
|
<stop stopColor="#DFDFDF" offset="0%" />
|
||||||
|
<stop stopColor="#4C4C4C" offset="44.317%" />
|
||||||
|
<stop stopColor="#333" offset="100%" />
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative flex flex-col lg:flex-row justify-between items-center" style={{ justifyContent: 'center' }}>
|
||||||
|
|
||||||
|
{/* CTA content */}
|
||||||
|
<div className="text-center lg:text-left lg:max-w-xl">
|
||||||
|
<h3 className="h3 text-white mb-2">Something</h3>
|
||||||
|
<p className="text-gray-300 text-lg mb-6">Something</p>
|
||||||
|
|
||||||
|
{/* CTA form */}
|
||||||
|
<div className="w-full lg:w-auto">
|
||||||
|
|
||||||
|
<div className="flex flex-col sm:flex-row justify-center max-w-xs mx-auto sm:max-w-md lg:mx-0">
|
||||||
|
|
||||||
|
<Formik
|
||||||
|
initialValues={{
|
||||||
|
firstName: '',
|
||||||
|
lastName: '',
|
||||||
|
email: '',
|
||||||
|
emailConfirm: '',
|
||||||
|
checked: null,
|
||||||
|
}}
|
||||||
|
onSubmit={values => {
|
||||||
|
// same shape as initial values
|
||||||
|
console.log(values);
|
||||||
|
}}
|
||||||
|
validate={validate}
|
||||||
|
>
|
||||||
|
{({ errors, touched, isValidating }) => (
|
||||||
|
<Form>
|
||||||
|
{/* <label htmlFor="firstName">First Name</label> */}
|
||||||
|
<Field
|
||||||
|
id="firstName"
|
||||||
|
name="firstName"
|
||||||
|
placeholder="First Name"
|
||||||
|
className="w-full appearance-none bg-gray-800 border border-gray-700 focus:border-gray-600 rounded-sm px-4 py-3 sm:mr-2 text-white placeholder-gray-500"
|
||||||
|
/>
|
||||||
|
{errors.firstName && <div style={{ color: 'white' }}>{errors.firstName}</div>}
|
||||||
|
|
||||||
|
{/* <label htmlFor="lastName">Last Name</label> */}
|
||||||
|
<Field
|
||||||
|
id="lastName"
|
||||||
|
name="lastName"
|
||||||
|
placeholder="Last Name"
|
||||||
|
className="w-full appearance-none bg-gray-800 border border-gray-700 focus:border-gray-600 rounded-sm px-4 py-3 mt-6 sm:mr-2 text-white placeholder-gray-500"
|
||||||
|
/>
|
||||||
|
{errors.lastName && <div style={{ color: 'white' }}>{errors.lastName}</div>}
|
||||||
|
|
||||||
|
{/* <label htmlFor="email">Email Address</label> */}
|
||||||
|
<Field
|
||||||
|
id="email"
|
||||||
|
name="email"
|
||||||
|
placeholder="Email Address"
|
||||||
|
type="email"
|
||||||
|
className="w-full appearance-none bg-gray-800 border border-gray-700 focus:border-gray-600 rounded-sm px-4 py-3 mt-6 sm:mr-2 text-white placeholder-gray-500"
|
||||||
|
/>
|
||||||
|
{errors.email && touched.email && <div style={{ color: 'white' }}>{errors.email}</div>}
|
||||||
|
|
||||||
|
{/* <label htmlFor="emailConfirm">Confirm Email Address</label> */}
|
||||||
|
<Field
|
||||||
|
id="emailConfirm"
|
||||||
|
name="emailConfirm"
|
||||||
|
placeholder="Confirm Email Address"
|
||||||
|
type="email"
|
||||||
|
className="w-full appearance-none bg-gray-800 border border-gray-700 focus:border-gray-600 rounded-sm px-4 py-3 mt-6 sm:mr-2 text-white placeholder-gray-500"
|
||||||
|
/>
|
||||||
|
{errors.emailConfirm && <div style={{ color: 'white' }}>{errors.emailConfirm}</div>}
|
||||||
|
|
||||||
|
<Field
|
||||||
|
type="checkbox"
|
||||||
|
name="checked"
|
||||||
|
className="form-checkbox h-4 w-4 text-indigo-600 transition duration-150 ease-in-out"
|
||||||
|
value="Agreed"
|
||||||
|
/>
|
||||||
|
<p className="mt-6 mb-2 accept-tnc">Accept Terms & Conditions</p>
|
||||||
|
|
||||||
|
<button className="see-tnc">See Terms & Conditions</button>
|
||||||
|
|
||||||
|
<p className="text-sm text-gray-400 mt-3">
|
||||||
|
By clicking Accept Terms & Conditions you agree to
|
||||||
|
<a className="a-links" href="#"> Status' Terms of Service</a>,
|
||||||
|
the<a className="a-links" href="#"> Affiliate Program Terms of Service</a>,
|
||||||
|
and the <a className="a-links" href="#">Privacy Policy</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<button type="submit" className="btn text-white bg-blue-600 hover:bg-blue-700 shadow mt-12">Submit</button>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FormTemplate;
|
|
@ -0,0 +1,64 @@
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
function Header() {
|
||||||
|
|
||||||
|
const [top, setTop] = useState(true);
|
||||||
|
|
||||||
|
// detect whether user has scrolled the page down by 10px
|
||||||
|
useEffect(() => {
|
||||||
|
const scrollHandler = () => {
|
||||||
|
window.pageYOffset > 10 ? setTop(false) : setTop(true)
|
||||||
|
};
|
||||||
|
window.addEventListener('scroll', scrollHandler);
|
||||||
|
return () => window.removeEventListener('scroll', scrollHandler);
|
||||||
|
}, [top]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header className={`fixed w-full z-30 md:bg-opacity-90 transition duration-300 ease-in-out ${!top && 'bg-white blur shadow-lg'}`}>
|
||||||
|
<div className="max-w-6xl mx-auto px-5 sm:px-6">
|
||||||
|
<div className="flex items-center justify-between h-16 md:h-20">
|
||||||
|
|
||||||
|
{/* Site branding */}
|
||||||
|
<div className="flex-shrink-0 mr-4">
|
||||||
|
{/* Logo */}
|
||||||
|
<Link to="/" className="block" aria-label="Cruip">
|
||||||
|
<svg width="118" height="45" viewBox="0 0 118 45" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fillRule="evenodd" clipRule="evenodd" d="M22.4762 0C10.0629 0 0 10.0737 0 22.5C0 34.9264 10.0629 45 22.4762 45C34.8895 45 44.9524 34.9264 44.9524 22.5C44.9524 10.0737 34.8895 0 22.4762 0Z" fill="#4360DF"/>
|
||||||
|
<path fillRule="evenodd" clipRule="evenodd" d="M23.2309 21.5138C24.3595 21.6314 25.4882 21.749 26.8757 21.6716C30.6352 21.4618 32.9125 19.5302 32.7509 16.6428C32.5862 13.7052 29.5565 11.8953 26.5251 12.0645C21.5849 12.34 17.9521 16.6819 17.543 21.6444C18.2139 21.4871 18.9201 21.3932 19.586 21.356C20.9737 21.2787 22.1023 21.3962 23.2309 21.5138ZM13.5465 27.936C13.7024 30.6289 16.5727 32.288 19.4446 32.1328C24.1247 31.8802 27.5665 27.9002 27.954 23.3511C27.3184 23.4954 26.6495 23.5816 26.0185 23.6156C24.7039 23.6866 23.6346 23.5788 22.5653 23.471C21.4961 23.3632 20.4268 23.2554 19.1122 23.3264C15.5508 23.5187 13.3932 25.2893 13.5465 27.936Z" fill="white"/>
|
||||||
|
<path d="M53.6992 26.2361H56.9481C56.9481 26.7871 57.1033 27.1825 57.4137 27.4227C57.7241 27.6628 58.1228 27.7828 58.6096 27.7828C59.0117 27.7828 59.3398 27.7087 59.5938 27.5604C59.8548 27.405 59.9853 27.1543 59.9853 26.8082C59.9853 26.6034 59.9289 26.4374 59.816 26.3103C59.7102 26.1761 59.5444 26.0596 59.3187 25.9607C59.0929 25.8547 58.8036 25.7488 58.4508 25.6428C58.0981 25.5369 57.6748 25.4027 57.1809 25.2403C56.7365 25.0991 56.3167 24.9543 55.9216 24.8059C55.5335 24.6506 55.1914 24.4599 54.895 24.2339C54.5987 24.0079 54.366 23.7324 54.1966 23.4076C54.0344 23.0827 53.9532 22.6801 53.9532 22.1999C53.9532 21.6489 54.0625 21.1723 54.2813 20.7697C54.4999 20.3671 54.8069 20.0351 55.202 19.7738C55.597 19.5125 56.0697 19.3183 56.6201 19.1911C57.1703 19.0569 57.7771 18.9898 58.4402 18.9898C59.2516 18.9898 59.9501 19.0817 60.5357 19.2653C61.1213 19.4489 61.601 19.6996 61.975 20.0174C62.3489 20.3353 62.624 20.7096 62.8004 21.1404C62.9838 21.5712 63.0755 22.0338 63.0755 22.5283H59.8054C59.8054 22.0974 59.6926 21.7619 59.4668 21.5218C59.2481 21.2817 58.913 21.1617 58.4614 21.1617C58.1157 21.1617 57.8194 21.2394 57.5725 21.3947C57.3256 21.543 57.2021 21.769 57.2021 22.0727C57.2021 22.2775 57.2586 22.4435 57.3714 22.5706C57.4914 22.6907 57.6642 22.8001 57.89 22.8991C58.1157 22.9979 58.3944 23.1003 58.726 23.2063C59.0576 23.3052 59.4386 23.4252 59.8689 23.5664C60.3346 23.6936 60.7685 23.8348 61.1706 23.9902C61.5728 24.1456 61.9255 24.3363 62.2289 24.5623C62.5393 24.7813 62.7827 25.0602 62.9591 25.3992C63.1425 25.7312 63.2343 26.1549 63.2343 26.6705C63.2343 27.2779 63.1073 27.797 62.8533 28.2278C62.5993 28.6516 62.2571 28.9976 61.8268 29.266C61.4034 29.5344 60.9096 29.7251 60.3452 29.8381C59.7808 29.9581 59.1881 30.0182 58.5672 30.0182C57.0222 30.0182 55.8228 29.6969 54.9691 29.0541C54.1225 28.4044 53.6992 27.465 53.6992 26.2361Z" fill="black"/>
|
||||||
|
<path d="M64.0598 21.7443V19.2759H65.7002V16.1719H69.002V19.2759H71.3831V21.7443H69.002V25.484C69.002 25.8724 69.0372 26.1832 69.1078 26.4162C69.1784 26.6423 69.2771 26.8223 69.4041 26.9565C69.5381 27.0837 69.6969 27.1684 69.8803 27.2108C70.0708 27.2461 70.2825 27.2637 70.5153 27.2637C70.6564 27.2637 70.8363 27.2602 71.055 27.2531C71.2737 27.2391 71.4642 27.2178 71.6265 27.1896V29.7321C71.3796 29.7745 71.0692 29.8134 70.6952 29.8487C70.3283 29.884 69.8945 29.9016 69.3936 29.9016C69.0055 29.9016 68.5963 29.8734 68.166 29.8169C67.7356 29.7604 67.3369 29.6121 66.9701 29.372C66.6032 29.1318 66.2999 28.7646 66.06 28.2702C65.8201 27.7687 65.7002 27.0837 65.7002 26.2149V21.7443H64.0598Z" fill="black"/>
|
||||||
|
<path fillRule="evenodd" clipRule="evenodd" d="M72.9492 22.3164C72.7023 22.9873 72.5789 23.7148 72.5789 24.4987C72.5789 25.2827 72.7023 26.0102 72.9492 26.6811C73.2032 27.352 73.5525 27.9312 73.9969 28.4185C74.4485 28.9058 74.9741 29.2907 75.5738 29.5732C76.1805 29.8557 76.8296 29.997 77.5211 29.997C78.3253 29.997 79.0167 29.8275 79.5952 29.4885C80.1737 29.1495 80.5932 28.7398 80.8549 28.2596V29.7321H84.1669V19.2759H80.8549V20.7697C80.5651 20.2612 80.1314 19.8409 79.5529 19.5089C78.9814 19.177 78.3041 19.0111 77.5211 19.0111C76.8225 19.0111 76.1734 19.1523 75.5738 19.4348C74.9741 19.7173 74.4485 20.1022 73.9969 20.5896C73.5525 21.0698 73.2032 21.6454 72.9492 22.3164ZM76.05 25.5369C75.9301 25.205 75.8701 24.8589 75.8701 24.4987C75.8701 24.1386 75.9301 23.7995 76.05 23.4817C76.177 23.1639 76.3463 22.8814 76.5579 22.6342C76.7767 22.387 77.0377 22.1928 77.3411 22.0515C77.6445 21.9103 77.9831 21.8396 78.3571 21.8396C78.7381 21.8396 79.0802 21.9103 79.3836 22.0515C79.687 22.1928 79.9445 22.387 80.1561 22.6342C80.3749 22.8814 80.5443 23.1639 80.6639 23.4817C80.7907 23.7995 80.8549 24.1386 80.8549 24.4987C80.8549 24.866 80.7907 25.2121 80.6639 25.5369C80.5443 25.8618 80.3749 26.1444 80.1561 26.3845C79.9445 26.6175 79.6834 26.8082 79.373 26.9565C79.0697 27.0978 78.731 27.1684 78.3571 27.1684C77.9831 27.1684 77.6445 27.0978 77.3411 26.9565C77.0377 26.8082 76.7767 26.6175 76.5579 26.3845C76.3463 26.1444 76.177 25.8618 76.05 25.5369Z" fill="black"/>
|
||||||
|
<path d="M85.9448 21.7443V19.2759H87.5848V16.1719H90.8872V19.2759H93.268V21.7443H90.8872V25.484C90.8872 25.8724 90.9225 26.1832 90.9923 26.4162C91.063 26.6423 91.1617 26.8223 91.2893 26.9565C91.4234 27.0837 91.5815 27.1684 91.7654 27.2108C91.9556 27.2461 92.1675 27.2637 92.4003 27.2637C92.5416 27.2637 92.7214 27.2602 92.9397 27.2531C93.1589 27.2391 93.3491 27.2178 93.5113 27.1896V29.7321C93.2648 29.7745 92.9542 29.8134 92.5801 29.8487C92.2133 29.884 91.779 29.9016 91.2781 29.9016C90.8904 29.9016 90.481 29.8734 90.0507 29.8169C89.6205 29.7604 89.2215 29.6121 88.8547 29.372C88.4878 29.1318 88.1844 28.7646 87.9452 28.2702C87.7052 27.7687 87.5848 27.0837 87.5848 26.2149V21.7443H85.9448Z" fill="black"/>
|
||||||
|
<path d="M95.1521 25.484V19.2759H98.4433V24.6365C98.4433 25.3851 98.5773 25.996 98.8454 26.4692C99.1135 26.9353 99.5928 27.1684 100.285 27.1684C100.976 27.1684 101.484 26.9318 101.808 26.4586C102.14 25.9783 102.306 25.3321 102.306 24.5199V19.2759H105.618V29.7321H102.306V28.2384C102.016 28.7893 101.575 29.2201 100.983 29.5308C100.39 29.8416 99.6811 29.997 98.8559 29.997C98.1358 29.997 97.5434 29.884 97.0778 29.658C96.6195 29.432 96.2454 29.1459 95.9564 28.7998C95.6241 28.3973 95.4058 27.9312 95.2998 27.4015C95.2011 26.8717 95.1521 26.2326 95.1521 25.484Z" fill="black"/>
|
||||||
|
<path d="M107.756 26.2361H111.005C111.005 26.7871 111.16 27.1825 111.471 27.4227C111.78 27.6628 112.179 27.7828 112.666 27.7828C113.068 27.7828 113.396 27.7087 113.651 27.5604C113.912 27.405 114.042 27.1543 114.042 26.8082C114.042 26.6034 113.986 26.4374 113.872 26.3103C113.767 26.1761 113.601 26.0596 113.375 25.9607C113.15 25.8547 112.86 25.7488 112.508 25.6428C112.155 25.5369 111.731 25.4027 111.238 25.2403C110.793 25.0991 110.373 24.9543 109.978 24.8059C109.59 24.6506 109.248 24.4599 108.952 24.2339C108.655 24.0079 108.423 23.7324 108.253 23.4076C108.091 23.0827 108.01 22.6801 108.01 22.1999C108.01 21.6489 108.119 21.1723 108.338 20.7697C108.557 20.3671 108.863 20.0351 109.258 19.7738C109.654 19.5125 110.126 19.3183 110.677 19.1911C111.227 19.0569 111.833 18.9898 112.497 18.9898C113.308 18.9898 114.006 19.0817 114.592 19.2653C115.178 19.4489 115.658 19.6996 116.032 20.0174C116.406 20.3353 116.68 20.7096 116.857 21.1404C117.041 21.5712 117.132 22.0338 117.132 22.5283H113.862C113.862 22.0974 113.75 21.7619 113.523 21.5218C113.305 21.2817 112.969 21.1617 112.518 21.1617C112.172 21.1617 111.876 21.2394 111.629 21.3947C111.382 21.543 111.259 21.769 111.259 22.0727C111.259 22.2775 111.315 22.4435 111.428 22.5706C111.548 22.6907 111.721 22.8001 111.947 22.8991C112.172 22.9979 112.451 23.1003 112.782 23.2063C113.115 23.3052 113.495 23.4252 113.925 23.5664C114.391 23.6936 114.825 23.8348 115.227 23.9902C115.63 24.1456 115.982 24.3363 116.285 24.5623C116.596 24.7813 116.839 25.0602 117.016 25.3992C117.199 25.7312 117.291 26.1549 117.291 26.6705C117.291 27.2779 117.164 27.797 116.91 28.2278C116.656 28.6516 116.313 28.9976 115.883 29.266C115.46 29.5344 114.966 29.7251 114.402 29.8381C113.837 29.9581 113.245 30.0182 112.624 30.0182C111.079 30.0182 109.88 29.6969 109.026 29.0541C108.179 28.4044 107.756 27.465 107.756 26.2361Z" fill="black"/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Site navigation */}
|
||||||
|
<nav className="flex flex-grow">
|
||||||
|
<ul className="flex flex-grow justify-end flex-wrap items-center">
|
||||||
|
{/* <li>
|
||||||
|
<Link to="/signin" className="font-medium text-gray-600 hover:text-gray-900 px-5 py-3 flex items-center transition duration-150 ease-in-out">Sign in</Link>
|
||||||
|
</li> */}
|
||||||
|
<li>
|
||||||
|
<Link to="/signup" className="btn-sm text-gray-200 bg-gray-900 hover:bg-gray-800 ml-3">
|
||||||
|
<span>Get Status</span>
|
||||||
|
<svg className="w-3 h-3 fill-current text-gray-400 flex-shrink-0 ml-2 -mr-1" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M11.707 5.293L7 .586 5.586 2l3 3H0v2h8.586l-3 3L7 11.414l4.707-4.707a1 1 0 000-1.414z" fillRule="nonzero" />
|
||||||
|
</svg>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Header;
|
|
@ -0,0 +1,50 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import Modal from '../utils/Modal';
|
||||||
|
|
||||||
|
function HeroHome() {
|
||||||
|
|
||||||
|
const [videoModalOpen, setVideoModalOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="relative">
|
||||||
|
|
||||||
|
{/* Illustration behind hero content */}
|
||||||
|
<div className="absolute left-1/2 transform -translate-x-1/2 bottom-0 pointer-events-none" aria-hidden="true">
|
||||||
|
<svg width="1360" height="578" viewBox="0 0 1360 578" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="illustration-01">
|
||||||
|
<stop stopColor="#FFF" offset="0%" />
|
||||||
|
<stop stopColor="#EAEAEA" offset="77.402%" />
|
||||||
|
<stop stopColor="#DFDFDF" offset="100%" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<g fill="url(#illustration-01)" fillRule="evenodd">
|
||||||
|
<circle cx="1232" cy="128" r="128" />
|
||||||
|
<circle cx="155" cy="443" r="64" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="max-w-6xl mx-auto px-4 sm:px-6">
|
||||||
|
|
||||||
|
{/* Hero content */}
|
||||||
|
<div className="pt-32 pb-12 md:pt-40 md:pb-20">
|
||||||
|
|
||||||
|
{/* Section header */}
|
||||||
|
<div className="text-center pb-12 md:pb-16">
|
||||||
|
<h1 className="text-5xl md:text-6xl font-extrabold leading-tighter tracking-tighter mb-4" data-aos="zoom-y-out">Status <span className="bg-clip-text text-transparent bg-gradient-to-r from-blue-500 to-teal-400">Affiliate</span></h1>
|
||||||
|
<div className="max-w-3xl mx-auto">
|
||||||
|
<p className="text-xl text-gray-600 mb-8" data-aos="zoom-y-out" data-aos-delay="150">Something</p>
|
||||||
|
<div className="max-w-xs mx-auto sm:max-w-none sm:flex sm:justify-center" data-aos="zoom-y-out" data-aos-delay="300">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HeroHome;
|
|
@ -0,0 +1,141 @@
|
||||||
|
// This optional code is used to register a service worker.
|
||||||
|
// register() is not called by default.
|
||||||
|
|
||||||
|
// This lets the app load faster on subsequent visits in production, and gives
|
||||||
|
// it offline capabilities. However, it also means that developers (and users)
|
||||||
|
// will only see deployed updates on subsequent visits to a page, after all the
|
||||||
|
// existing tabs open on the page have been closed, since previously cached
|
||||||
|
// resources are updated in the background.
|
||||||
|
|
||||||
|
// To learn more about the benefits of this model and instructions on how to
|
||||||
|
// opt-in, read https://bit.ly/CRA-PWA
|
||||||
|
|
||||||
|
const isLocalhost = Boolean(
|
||||||
|
window.location.hostname === 'localhost' ||
|
||||||
|
// [::1] is the IPv6 localhost address.
|
||||||
|
window.location.hostname === '[::1]' ||
|
||||||
|
// 127.0.0.0/8 are considered localhost for IPv4.
|
||||||
|
window.location.hostname.match(
|
||||||
|
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
export function register(config) {
|
||||||
|
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||||
|
// The URL constructor is available in all browsers that support SW.
|
||||||
|
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||||
|
if (publicUrl.origin !== window.location.origin) {
|
||||||
|
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||||
|
// from what our page is served on. This might happen if a CDN is used to
|
||||||
|
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||||
|
|
||||||
|
if (isLocalhost) {
|
||||||
|
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||||
|
checkValidServiceWorker(swUrl, config);
|
||||||
|
|
||||||
|
// Add some additional logging to localhost, pointing developers to the
|
||||||
|
// service worker/PWA documentation.
|
||||||
|
navigator.serviceWorker.ready.then(() => {
|
||||||
|
console.log(
|
||||||
|
'This web app is being served cache-first by a service ' +
|
||||||
|
'worker. To learn more, visit https://bit.ly/CRA-PWA'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Is not localhost. Just register service worker
|
||||||
|
registerValidSW(swUrl, config);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerValidSW(swUrl, config) {
|
||||||
|
navigator.serviceWorker
|
||||||
|
.register(swUrl)
|
||||||
|
.then(registration => {
|
||||||
|
registration.onupdatefound = () => {
|
||||||
|
const installingWorker = registration.installing;
|
||||||
|
if (installingWorker == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
installingWorker.onstatechange = () => {
|
||||||
|
if (installingWorker.state === 'installed') {
|
||||||
|
if (navigator.serviceWorker.controller) {
|
||||||
|
// At this point, the updated precached content has been fetched,
|
||||||
|
// but the previous service worker will still serve the older
|
||||||
|
// content until all client tabs are closed.
|
||||||
|
console.log(
|
||||||
|
'New content is available and will be used when all ' +
|
||||||
|
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Execute callback
|
||||||
|
if (config && config.onUpdate) {
|
||||||
|
config.onUpdate(registration);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// At this point, everything has been precached.
|
||||||
|
// It's the perfect time to display a
|
||||||
|
// "Content is cached for offline use." message.
|
||||||
|
console.log('Content is cached for offline use.');
|
||||||
|
|
||||||
|
// Execute callback
|
||||||
|
if (config && config.onSuccess) {
|
||||||
|
config.onSuccess(registration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error during service worker registration:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkValidServiceWorker(swUrl, config) {
|
||||||
|
// Check if the service worker can be found. If it can't reload the page.
|
||||||
|
fetch(swUrl, {
|
||||||
|
headers: { 'Service-Worker': 'script' },
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
// Ensure service worker exists, and that we really are getting a JS file.
|
||||||
|
const contentType = response.headers.get('content-type');
|
||||||
|
if (
|
||||||
|
response.status === 404 ||
|
||||||
|
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||||
|
) {
|
||||||
|
// No service worker found. Probably a different app. Reload the page.
|
||||||
|
navigator.serviceWorker.ready.then(registration => {
|
||||||
|
registration.unregister().then(() => {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Service worker found. Proceed as normal.
|
||||||
|
registerValidSW(swUrl, config);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
console.log(
|
||||||
|
'No internet connection found. App is running in offline mode.'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unregister() {
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
navigator.serviceWorker.ready
|
||||||
|
.then(registration => {
|
||||||
|
registration.unregister();
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||||
|
// allows you to do things like:
|
||||||
|
// expect(element).toHaveTextContent(/react/i)
|
||||||
|
// learn more: https://github.com/testing-library/jest-dom
|
||||||
|
import '@testing-library/jest-dom/extend-expect';
|
|
@ -0,0 +1,57 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Transition from '../utils/Transition.js';
|
||||||
|
|
||||||
|
function Dropdown({
|
||||||
|
children,
|
||||||
|
title
|
||||||
|
}) {
|
||||||
|
|
||||||
|
const [dropdownOpen, setDropdownOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
className="relative"
|
||||||
|
onMouseEnter={() => setDropdownOpen(true)}
|
||||||
|
onMouseLeave={() => setDropdownOpen(false)}
|
||||||
|
onFocus={() => setDropdownOpen(true)}
|
||||||
|
onBlur={() => setDropdownOpen(false)}
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
className="text-gray-600 hover:text-gray-900 px-3 lg:px-5 py-2 flex items-center transition duration-150 ease-in-out"
|
||||||
|
href="#0"
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded={dropdownOpen}
|
||||||
|
onClick={(e) => e.preventDefault()}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
<svg className="w-3 h-3 fill-current text-gray-500 cursor-pointer ml-1 flex-shrink-0" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M10.28 4.305L5.989 8.598 1.695 4.305A1 1 0 00.28 5.72l5 5a1 1 0 001.414 0l5-5a1 1 0 10-1.414-1.414z" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<Transition
|
||||||
|
show={dropdownOpen}
|
||||||
|
tag="ul"
|
||||||
|
className="origin-top-right absolute top-full right-0 w-40 bg-white py-2 ml-4 rounded shadow-lg"
|
||||||
|
enter="transition ease-out duration-200 transform"
|
||||||
|
enterStart="opacity-0 -translate-y-2"
|
||||||
|
enterEnd="opacity-100 translate-y-0"
|
||||||
|
leave="transition ease-out duration-200"
|
||||||
|
leaveStart="opacity-100"
|
||||||
|
leaveEnd="opacity-0"
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Transition>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Dropdown;
|
||||||
|
|
||||||
|
Dropdown.propTypes = {
|
||||||
|
children: PropTypes.oneOfType([
|
||||||
|
PropTypes.arrayOf(PropTypes.element),
|
||||||
|
PropTypes.element.isRequired
|
||||||
|
]),
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
};
|
|
@ -0,0 +1,85 @@
|
||||||
|
import React, { useEffect, useRef } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Transition from '../utils/Transition.js';
|
||||||
|
|
||||||
|
function Modal({
|
||||||
|
children,
|
||||||
|
id,
|
||||||
|
ariaLabel,
|
||||||
|
show,
|
||||||
|
handleClose
|
||||||
|
}) {
|
||||||
|
|
||||||
|
const modalContent = useRef(null);
|
||||||
|
|
||||||
|
// close the modal on click outside
|
||||||
|
useEffect(() => {
|
||||||
|
const clickHandler = ({ target }) => {
|
||||||
|
if (!show || modalContent.current.contains(target)) return;
|
||||||
|
handleClose();
|
||||||
|
};
|
||||||
|
document.addEventListener('click', clickHandler);
|
||||||
|
return () => document.removeEventListener('click', clickHandler);
|
||||||
|
});
|
||||||
|
|
||||||
|
// close the modal if the esc key is pressed
|
||||||
|
useEffect(() => {
|
||||||
|
const keyHandler = ({ keyCode }) => {
|
||||||
|
if (keyCode !== 27) return;
|
||||||
|
handleClose();
|
||||||
|
};
|
||||||
|
document.addEventListener('keydown', keyHandler);
|
||||||
|
|
||||||
|
return () => document.removeEventListener('keydown', keyHandler);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Modal backdrop */}
|
||||||
|
<Transition
|
||||||
|
className="fixed inset-0 z-50 bg-white bg-opacity-75 transition-opacity blur"
|
||||||
|
show={show}
|
||||||
|
enter="transition ease-out duration-200"
|
||||||
|
enterStart="opacity-0"
|
||||||
|
enterEnd="opacity-100"
|
||||||
|
leave="transition ease-out duration-100"
|
||||||
|
leaveStart="opacity-100"
|
||||||
|
leaveEnd="opacity-0"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Modal dialog */}
|
||||||
|
<Transition
|
||||||
|
id={id}
|
||||||
|
className="fixed inset-0 z-50 overflow-hidden flex items-center justify-center transform px-4 sm:px-6"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby={ariaLabel}
|
||||||
|
show={show}
|
||||||
|
enter="transition ease-out duration-200"
|
||||||
|
enterStart="opacity-0 scale-95"
|
||||||
|
enterEnd="opacity-100 scale-100"
|
||||||
|
leave="transition ease-out duration-200"
|
||||||
|
leaveStart="opacity-100 scale-100"
|
||||||
|
leaveEnd="opacity-0 scale-95"
|
||||||
|
>
|
||||||
|
<div className="bg-white overflow-auto max-w-6xl w-full max-h-full" ref={modalContent}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Modal;
|
||||||
|
|
||||||
|
Modal.propTypes = {
|
||||||
|
children: PropTypes.oneOfType([
|
||||||
|
PropTypes.arrayOf(PropTypes.element),
|
||||||
|
PropTypes.element.isRequired
|
||||||
|
]),
|
||||||
|
id: PropTypes.string,
|
||||||
|
ariaLabel: PropTypes.string,
|
||||||
|
show: PropTypes.bool.isRequired,
|
||||||
|
handleClose: PropTypes.func.isRequired
|
||||||
|
};
|
|
@ -0,0 +1,116 @@
|
||||||
|
import React, { useRef, useEffect, useContext } from 'react';
|
||||||
|
import { CSSTransition as ReactCSSTransition } from 'react-transition-group';
|
||||||
|
|
||||||
|
const TransitionContext = React.createContext({
|
||||||
|
parent: {},
|
||||||
|
})
|
||||||
|
|
||||||
|
function useIsInitialRender() {
|
||||||
|
const isInitialRender = useRef(true);
|
||||||
|
useEffect(() => {
|
||||||
|
isInitialRender.current = false;
|
||||||
|
}, [])
|
||||||
|
return isInitialRender.current;
|
||||||
|
}
|
||||||
|
|
||||||
|
function CSSTransition({
|
||||||
|
show,
|
||||||
|
enter = '',
|
||||||
|
enterStart = '',
|
||||||
|
enterEnd = '',
|
||||||
|
leave = '',
|
||||||
|
leaveStart = '',
|
||||||
|
leaveEnd = '',
|
||||||
|
appear,
|
||||||
|
unmountOnExit,
|
||||||
|
tag = 'div',
|
||||||
|
children,
|
||||||
|
...rest
|
||||||
|
}) {
|
||||||
|
const enterClasses = enter.split(' ').filter((s) => s.length);
|
||||||
|
const enterStartClasses = enterStart.split(' ').filter((s) => s.length);
|
||||||
|
const enterEndClasses = enterEnd.split(' ').filter((s) => s.length);
|
||||||
|
const leaveClasses = leave.split(' ').filter((s) => s.length);
|
||||||
|
const leaveStartClasses = leaveStart.split(' ').filter((s) => s.length);
|
||||||
|
const leaveEndClasses = leaveEnd.split(' ').filter((s) => s.length);
|
||||||
|
const removeFromDom = unmountOnExit;
|
||||||
|
|
||||||
|
function addClasses(node, classes) {
|
||||||
|
classes.length && node.classList.add(...classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeClasses(node, classes) {
|
||||||
|
classes.length && node.classList.remove(...classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodeRef = React.useRef(null);
|
||||||
|
const Component = tag;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReactCSSTransition
|
||||||
|
appear={appear}
|
||||||
|
nodeRef={nodeRef}
|
||||||
|
unmountOnExit={removeFromDom}
|
||||||
|
in={show}
|
||||||
|
addEndListener={(done) => {
|
||||||
|
nodeRef.current.addEventListener('transitionend', done, false)
|
||||||
|
}}
|
||||||
|
onEnter={() => {
|
||||||
|
if (!removeFromDom) nodeRef.current.style.display = null;
|
||||||
|
addClasses(nodeRef.current, [...enterClasses, ...enterStartClasses])
|
||||||
|
}}
|
||||||
|
onEntering={() => {
|
||||||
|
removeClasses(nodeRef.current, enterStartClasses)
|
||||||
|
addClasses(nodeRef.current, enterEndClasses)
|
||||||
|
}}
|
||||||
|
onEntered={() => {
|
||||||
|
removeClasses(nodeRef.current, [...enterEndClasses, ...enterClasses])
|
||||||
|
}}
|
||||||
|
onExit={() => {
|
||||||
|
addClasses(nodeRef.current, [...leaveClasses, ...leaveStartClasses])
|
||||||
|
}}
|
||||||
|
onExiting={() => {
|
||||||
|
removeClasses(nodeRef.current, leaveStartClasses)
|
||||||
|
addClasses(nodeRef.current, leaveEndClasses)
|
||||||
|
}}
|
||||||
|
onExited={() => {
|
||||||
|
removeClasses(nodeRef.current, [...leaveEndClasses, ...leaveClasses])
|
||||||
|
if (!removeFromDom) nodeRef.current.style.display = 'none';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Component ref={nodeRef} {...rest} style={{ display: !removeFromDom ? 'none': null }}>{children}</Component>
|
||||||
|
</ReactCSSTransition>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Transition({ show, appear, ...rest }) {
|
||||||
|
const { parent } = useContext(TransitionContext);
|
||||||
|
const isInitialRender = useIsInitialRender();
|
||||||
|
const isChild = show === undefined;
|
||||||
|
|
||||||
|
if (isChild) {
|
||||||
|
return (
|
||||||
|
<CSSTransition
|
||||||
|
appear={parent.appear || !parent.isInitialRender}
|
||||||
|
show={parent.show}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TransitionContext.Provider
|
||||||
|
value={{
|
||||||
|
parent: {
|
||||||
|
show,
|
||||||
|
isInitialRender,
|
||||||
|
appear,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CSSTransition appear={appear} show={show} {...rest} />
|
||||||
|
</TransitionContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Transition;
|
|
@ -0,0 +1,162 @@
|
||||||
|
module.exports = {
|
||||||
|
purge: [
|
||||||
|
'public/index.html',
|
||||||
|
'src/**/*.js',
|
||||||
|
'src/**/*.jsx',
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
gray: {
|
||||||
|
100: '#FBFBFB',
|
||||||
|
200: '#EAEAEA',
|
||||||
|
300: '#DFDFDF',
|
||||||
|
400: '#999999',
|
||||||
|
500: '#7F7F7F',
|
||||||
|
600: '#666666',
|
||||||
|
700: '#4C4C4C',
|
||||||
|
800: '#333333',
|
||||||
|
900: '#191919',
|
||||||
|
},
|
||||||
|
blue: {
|
||||||
|
100: '#E6F0FD',
|
||||||
|
200: '#CCE2FC',
|
||||||
|
300: '#99C5FA',
|
||||||
|
400: '#66A9F7',
|
||||||
|
500: '#338CF5',
|
||||||
|
600: '#0070F4',
|
||||||
|
700: '#0064DA',
|
||||||
|
800: '#0059C2',
|
||||||
|
900: '#004391',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
boxShadow: {
|
||||||
|
xs: '0 0 0 1px rgba(0, 0, 0, 0.16)',
|
||||||
|
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.16)',
|
||||||
|
default: '0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 2px 0 rgba(0, 0, 0, 0.03)',
|
||||||
|
md: '0 4px 6px -1px rgba(0, 0, 0, 0.04), 0 2px 4px -1px rgba(0, 0, 0, 0.03)',
|
||||||
|
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.04), 0 4px 6px -2px rgba(0, 0, 0, 0.02)',
|
||||||
|
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.12), 0 10px 10px -5px rgba(0, 0, 0, 0.02)',
|
||||||
|
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.15)',
|
||||||
|
inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.04)',
|
||||||
|
outline: '0 0 0 3px rgba(66, 153, 225, 0.5)',
|
||||||
|
none: 'none',
|
||||||
|
},
|
||||||
|
spacing: {
|
||||||
|
'9/16': '56.25%',
|
||||||
|
'3/4': '75%',
|
||||||
|
'1/1': '100%',
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
inter: ['Inter', 'sans-serif']
|
||||||
|
},
|
||||||
|
fontSize: {
|
||||||
|
xs: '0.75rem',
|
||||||
|
sm: '0.875rem',
|
||||||
|
base: '1rem',
|
||||||
|
lg: '1.125rem',
|
||||||
|
xl: '1.25rem',
|
||||||
|
'2xl': '1.5rem',
|
||||||
|
'3xl': '2rem',
|
||||||
|
'4xl': '2.625rem',
|
||||||
|
'5xl': '3.25rem',
|
||||||
|
'6xl': '5.5rem',
|
||||||
|
},
|
||||||
|
inset: {
|
||||||
|
'1/2': '50%',
|
||||||
|
'full': '100%',
|
||||||
|
},
|
||||||
|
letterSpacing: {
|
||||||
|
tighter: '-0.02em',
|
||||||
|
tight: '-0.01em',
|
||||||
|
normal: '0',
|
||||||
|
wide: '0.01em',
|
||||||
|
wider: '0.02em',
|
||||||
|
widest: '0.4em',
|
||||||
|
},
|
||||||
|
lineHeight: {
|
||||||
|
none: '1',
|
||||||
|
tighter: '1.125',
|
||||||
|
tight: '1.25',
|
||||||
|
snug: '1.375',
|
||||||
|
normal: '1.5',
|
||||||
|
relaxed: '1.625',
|
||||||
|
loose: '2',
|
||||||
|
'3': '.75rem',
|
||||||
|
'4': '1rem',
|
||||||
|
'5': '1.2rem',
|
||||||
|
'6': '1.5rem',
|
||||||
|
'7': '1.75rem',
|
||||||
|
'8': '2rem',
|
||||||
|
'9': '2.25rem',
|
||||||
|
'10': '2.5rem',
|
||||||
|
},
|
||||||
|
minWidth: {
|
||||||
|
'10': '2.5rem',
|
||||||
|
'48': '12rem',
|
||||||
|
},
|
||||||
|
opacity: {
|
||||||
|
'90': '0.9',
|
||||||
|
},
|
||||||
|
scale: {
|
||||||
|
'98': '.98'
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
float: 'float 3s ease-in-out infinite',
|
||||||
|
},
|
||||||
|
keyframes: {
|
||||||
|
float: {
|
||||||
|
'0%, 100%': { transform: 'translateY(0)', },
|
||||||
|
'50%': { transform: 'translateY(-5%)', },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
customForms: theme => ({
|
||||||
|
default: {
|
||||||
|
'input, textarea, multiselect, select, checkbox, radio': {
|
||||||
|
backgroundColor: theme('colors.white'),
|
||||||
|
borderColor: theme('colors.gray.300'),
|
||||||
|
borderRadius: theme('borderRadius.default'),
|
||||||
|
'&:focus': {
|
||||||
|
outline: undefined,
|
||||||
|
boxShadow: undefined,
|
||||||
|
borderColor: theme('colors.gray.500'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'input, textarea, multiselect, select': {
|
||||||
|
backgroundColor: theme('colors.white'),
|
||||||
|
fontSize: undefined,
|
||||||
|
lineHeight: undefined,
|
||||||
|
paddingTop: theme('spacing.3'),
|
||||||
|
paddingRight: theme('spacing.4'),
|
||||||
|
paddingBottom: theme('spacing.3'),
|
||||||
|
paddingLeft: theme('spacing.4'),
|
||||||
|
},
|
||||||
|
'input, textarea': {
|
||||||
|
'&::placeholder': {
|
||||||
|
color: theme('colors.gray.500'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
paddingRight: theme('spacing.10'),
|
||||||
|
iconColor: theme('colors.gray.400'),
|
||||||
|
},
|
||||||
|
'checkbox, radio': {
|
||||||
|
color: theme('colors.gray.800'),
|
||||||
|
backgroundColor: theme('colors.white'),
|
||||||
|
borderRadius: theme('borderRadius.sm'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
variants: {
|
||||||
|
backgroundColor: ['responsive', 'hover', 'focus', 'group-hover'],
|
||||||
|
textColor: ['responsive', 'hover', 'focus', 'group-hover'],
|
||||||
|
translate: ['responsive', 'hover', 'focus', 'group-hover'],
|
||||||
|
boxShadow: ['responsive', 'hover', 'focus', 'focus-within'],
|
||||||
|
opacity: ['responsive', 'hover', 'focus', 'group-hover'],
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
require('@tailwindcss/custom-forms'),
|
||||||
|
],
|
||||||
|
};
|
Loading…
Reference in New Issue