From 9eaea7aeb77bc23fba7e9611ba03d4fcbca6babd Mon Sep 17 00:00:00 2001 From: painterpuppets Date: Wed, 1 Nov 2023 12:18:52 +0800 Subject: [PATCH 1/3] feat: implement magickbase homepage --- packages/magickbase/.eslintrc.cjs | 27 + packages/magickbase/next.config.js | 62 +- packages/magickbase/package.json | 5 + packages/magickbase/postcss.config.js | 6 + .../magickbase/public/perlin-noise/index.html | 271 ++++++++ .../magickbase/public/perlin-noise/script.js | 172 +++++ .../magickbase/public/perlin-noise/style.css | 50 ++ packages/magickbase/src/app/globals.css | 13 +- packages/magickbase/src/app/page.module.css | 8 + .../magickbase/src/components/About/index.tsx | 77 +++ .../src/components/About/styles.module.scss | 48 ++ .../src/components/Branding/index.tsx | 18 + .../src/components/ContactUs/index.tsx | 8 + .../src/components/Contacts/discord.svg | 3 + .../src/components/Contacts/github.svg | 3 + .../src/components/Contacts/index.module.scss | 5 + .../src/components/Contacts/index.tsx | 27 + .../src/components/Contacts/twitter.svg | 3 + .../src/components/Footer/full-logo.svg | 7 + .../src/components/Footer/index.module.scss | 123 ++++ .../src/components/Footer/index.tsx | 64 ++ .../src/components/Header/close.svg | 4 + .../src/components/Header/github.svg | 3 + .../src/components/Header/index.module.scss | 231 +++++++ .../src/components/Header/index.tsx | 140 ++++ .../magickbase/src/components/Header/logo.svg | 6 + .../magickbase/src/components/Header/menu.svg | 5 + .../src/components/Services/index.tsx | 8 + .../UpsideDownEffect/index.module.scss | 80 +++ .../src/components/UpsideDownEffect/index.tsx | 88 +++ packages/magickbase/src/hooks/index.ts | 186 +++++ .../hooks/useHighPrecisionScrollbarWidth.tsx | 50 ++ .../magickbase/src/hooks/useMemoizedFn.ts | 29 + packages/magickbase/src/pages/_app.tsx | 9 + packages/magickbase/src/pages/_document.tsx | 25 + packages/magickbase/src/pages/favicon.ico | Bin 0 -> 25931 bytes packages/magickbase/src/pages/globals.css | 106 +++ packages/magickbase/src/pages/index.tsx | 23 + packages/magickbase/src/pages/page.module.css | 279 ++++++++ packages/magickbase/src/styles/globals.scss | 44 ++ .../magickbase/src/styles/presets.module.scss | 41 ++ .../src/styles/variables.module.scss | 5 + packages/magickbase/src/utils/array.ts | 11 + packages/magickbase/src/utils/const.ts | 4 + packages/magickbase/src/utils/env.ts | 5 + packages/magickbase/src/utils/i18n.ts | 6 + packages/magickbase/src/utils/index.ts | 28 + packages/magickbase/src/utils/number.ts | 15 + packages/magickbase/src/utils/time.ts | 1 + packages/magickbase/tailwind.config.ts | 14 + yarn.lock | 653 +++++++++++++++++- 51 files changed, 3064 insertions(+), 35 deletions(-) create mode 100644 packages/magickbase/.eslintrc.cjs create mode 100644 packages/magickbase/postcss.config.js create mode 100755 packages/magickbase/public/perlin-noise/index.html create mode 100755 packages/magickbase/public/perlin-noise/script.js create mode 100755 packages/magickbase/public/perlin-noise/style.css create mode 100644 packages/magickbase/src/components/About/index.tsx create mode 100644 packages/magickbase/src/components/About/styles.module.scss create mode 100644 packages/magickbase/src/components/Branding/index.tsx create mode 100644 packages/magickbase/src/components/ContactUs/index.tsx create mode 100644 packages/magickbase/src/components/Contacts/discord.svg create mode 100644 packages/magickbase/src/components/Contacts/github.svg create mode 100644 packages/magickbase/src/components/Contacts/index.module.scss create mode 100644 packages/magickbase/src/components/Contacts/index.tsx create mode 100644 packages/magickbase/src/components/Contacts/twitter.svg create mode 100644 packages/magickbase/src/components/Footer/full-logo.svg create mode 100644 packages/magickbase/src/components/Footer/index.module.scss create mode 100644 packages/magickbase/src/components/Footer/index.tsx create mode 100644 packages/magickbase/src/components/Header/close.svg create mode 100644 packages/magickbase/src/components/Header/github.svg create mode 100644 packages/magickbase/src/components/Header/index.module.scss create mode 100644 packages/magickbase/src/components/Header/index.tsx create mode 100644 packages/magickbase/src/components/Header/logo.svg create mode 100644 packages/magickbase/src/components/Header/menu.svg create mode 100644 packages/magickbase/src/components/Services/index.tsx create mode 100644 packages/magickbase/src/components/UpsideDownEffect/index.module.scss create mode 100644 packages/magickbase/src/components/UpsideDownEffect/index.tsx create mode 100644 packages/magickbase/src/hooks/index.ts create mode 100644 packages/magickbase/src/hooks/useHighPrecisionScrollbarWidth.tsx create mode 100644 packages/magickbase/src/hooks/useMemoizedFn.ts create mode 100644 packages/magickbase/src/pages/_app.tsx create mode 100644 packages/magickbase/src/pages/_document.tsx create mode 100644 packages/magickbase/src/pages/favicon.ico create mode 100644 packages/magickbase/src/pages/globals.css create mode 100644 packages/magickbase/src/pages/index.tsx create mode 100644 packages/magickbase/src/pages/page.module.css create mode 100644 packages/magickbase/src/styles/globals.scss create mode 100644 packages/magickbase/src/styles/presets.module.scss create mode 100644 packages/magickbase/src/styles/variables.module.scss create mode 100644 packages/magickbase/src/utils/array.ts create mode 100644 packages/magickbase/src/utils/const.ts create mode 100644 packages/magickbase/src/utils/env.ts create mode 100644 packages/magickbase/src/utils/i18n.ts create mode 100644 packages/magickbase/src/utils/index.ts create mode 100644 packages/magickbase/src/utils/number.ts create mode 100644 packages/magickbase/src/utils/time.ts create mode 100644 packages/magickbase/tailwind.config.ts diff --git a/packages/magickbase/.eslintrc.cjs b/packages/magickbase/.eslintrc.cjs new file mode 100644 index 00000000..00cf30a4 --- /dev/null +++ b/packages/magickbase/.eslintrc.cjs @@ -0,0 +1,27 @@ +/** @type {import("eslint").Linter.Config} */ +const config = { + overrides: [ + { + extends: ['plugin:@typescript-eslint/recommended-requiring-type-checking'], + files: ['*.ts', '*.tsx'], + parserOptions: { + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, + }, + ], + parser: '@typescript-eslint/parser', + parserOptions: { + tsconfigRootDir: __dirname, + }, + plugins: ['@typescript-eslint'], + extends: ['next/core-web-vitals', 'prettier', 'plugin:@typescript-eslint/recommended'], + rules: { + 'import/order': ['error', { groups: [['builtin', 'external', 'internal']] }], + 'import/newline-after-import': 'error', + }, + // This is because `next.config.mjs` is excluded from tsconfig. + ignorePatterns: ['next.config.mjs', 'next-i18next.config.js'], +} + +module.exports = config diff --git a/packages/magickbase/next.config.js b/packages/magickbase/next.config.js index dafb0c88..21bd152d 100644 --- a/packages/magickbase/next.config.js +++ b/packages/magickbase/next.config.js @@ -1,8 +1,66 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - experimental: { - appDir: true, + webpack(config) { + config.module.rules.push({ + test: /\.svg$/i, + issuer: /\.[jt]sx?$/, + use: [ + { + loader: '@svgr/webpack', + options: { + svgoConfig: { + plugins: [ + { + name: 'preset-default', + params: { + overrides: { + removeViewBox: false, + }, + }, + }, + ], + }, + }, + }, + ], + }) + + // https://dhanrajsp.me/snippets/customize-css-loader-options-in-nextjs + const oneOf = config.module.rules.find(rule => typeof rule.oneOf === 'object') + if (oneOf) { + const moduleSassRule = oneOf.oneOf.find(rule => regexEqual(rule.test, /\.module\.(scss|sass)$/)) + if (moduleSassRule) { + // Get the config object for css-loader plugin + const cssLoader = moduleSassRule.use.find(({ loader }) => loader.includes('css-loader')) + if (cssLoader) { + cssLoader.options = { + ...cssLoader.options, + modules: { + ...cssLoader.options.modules, + mode: 'local', + }, + } + } + } + } + + return config }, } +/** + * Stolen from https://stackoverflow.com/questions/10776600/testing-for-equality-of-regular-expressions + */ +function regexEqual(x, y) { + return ( + x instanceof RegExp && + y instanceof RegExp && + x.source === y.source && + x.global === y.global && + x.ignoreCase === y.ignoreCase && + x.multiline === y.multiline + ) +} + + module.exports = nextConfig diff --git a/packages/magickbase/package.json b/packages/magickbase/package.json index 44d49a86..fc1f9f78 100644 --- a/packages/magickbase/package.json +++ b/packages/magickbase/package.json @@ -9,14 +9,19 @@ "lint": "next lint" }, "dependencies": { + "@splinetool/react-spline": "2.2.6", + "@splinetool/runtime": "0.9.490", "@types/node": "20.8.6", "@types/react": "18.2.28", "@types/react-dom": "18.2.13", + "classnames": "2.3.2", "eslint": "8.51.0", "eslint-config-next": "13.5.4", "next": "13.5.4", "react": "18.2.0", "react-dom": "18.2.0", + "react-use": "17.4.0", + "tailwindcss": "3.3.5", "typescript": "5.2.2" } } diff --git a/packages/magickbase/postcss.config.js b/packages/magickbase/postcss.config.js new file mode 100644 index 00000000..33ad091d --- /dev/null +++ b/packages/magickbase/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/packages/magickbase/public/perlin-noise/index.html b/packages/magickbase/public/perlin-noise/index.html new file mode 100755 index 00000000..5ef8f0dd --- /dev/null +++ b/packages/magickbase/public/perlin-noise/index.html @@ -0,0 +1,271 @@ + + + + + Perlin Noise + + + + + + + +Perlin noise | Fireball explosion + +
+ + + + + + + + + + diff --git a/packages/magickbase/public/perlin-noise/script.js b/packages/magickbase/public/perlin-noise/script.js new file mode 100755 index 00000000..465e9106 --- /dev/null +++ b/packages/magickbase/public/perlin-noise/script.js @@ -0,0 +1,172 @@ +// Three JS + +window.addEventListener('load', init, false); + +function init() { + createWorld(); + createPrimitive(); + // createGUI(); + //--- + animation(); +} + +var Theme = {_darkred: 0x000000} + +//-------------------------------------------------------------------- + +var scene, camera, renderer, container; +var start = Date.now(); +var _width, _height; +function createWorld() { + _width = window.innerWidth; + _height= window.innerHeight; + //--- + scene = new THREE.Scene(); + //scene.fog = new THREE.Fog(Theme._darkred, 8, 20); + scene.background = new THREE.Color(Theme._darkred); + //--- + camera = new THREE.PerspectiveCamera(55, _width/_height, 1, 1000); + camera.position.z = 5; + //--- + renderer = new THREE.WebGLRenderer({antialias:true, alpha:false}); + renderer.setSize(_width, _height); + //--- + container = document.getElementById("container"); + container.appendChild(renderer.domElement); + //--- + window.addEventListener('resize', onWindowResize, false); +} + +function onWindowResize() { + _width = window.innerWidth; + _height = window.innerHeight; + renderer.setSize(_width, _height); + camera.aspect = _width / _height; + camera.updateProjectionMatrix(); + console.log('- resize -'); +} + +//-------------------------------------------------------------------- + +var mat; +var primitiveElement = function() { + this.mesh = new THREE.Object3D(); + mat = new THREE.ShaderMaterial( { + wireframe: false, + //fog: true, + uniforms: { + time: { + type: "f", + value: 0.0 + }, + pointscale: { + type: "f", + value: 0.0 + }, + decay: { + type: "f", + value: 0.0 + }, + complex: { + type: "f", + value: 0.0 + }, + waves: { + type: "f", + value: 0.0 + }, + eqcolor: { + type: "f", + value: 0.0 + }, + fragment: { + type: "i", + value: true + }, + redhell: { + type: "i", + value: true + } + }, + vertexShader: document.getElementById( 'vertexShader' ).textContent, + fragmentShader: document.getElementById( 'fragmentShader' ).textContent + }); + var geo = new THREE.IcosahedronBufferGeometry(3, 7); + var mesh = new THREE.Points(geo, mat); + + //--- + this.mesh.add(mesh); +} + +var _primitive; +function createPrimitive() { + _primitive = new primitiveElement(); + scene.add(_primitive.mesh); +} + +//-------------------------------------------------------------------- + +var options = { + perlin: { + vel: 0.001, + speed: 0.0000, + perlins: 1.0, + decay: 0.14, + complex: 0.30, + waves: 20.0, + eqcolor: 9.0, + fragment: false, + redhell: true + }, + spin: { + sinVel: 0.0, + ampVel: 80.0, + } +} + +function createGUI() { + var gui = new dat.GUI(); + var camGUI = gui.addFolder('Camera'); + //cam.add(, 'speed', 0.0, 30.00).listen(); + camGUI.add(camera.position, 'z', 3, 20).name('Zoom').listen(); + camGUI.add(options.perlin, 'vel', 0.000, 0.02).name('Velocity').listen(); + //camGUI.open(); + + var mathGUI = gui.addFolder('Math Options'); + mathGUI.add(options.spin, 'sinVel', 0.0, 0.50).name('Sine').listen(); + mathGUI.add(options.spin, 'ampVel', 0.0, 90.00).name('Amplitude').listen(); + //mathGUI.open(); + + var perlinGUI = gui.addFolder('Setup Perlin Noise'); + perlinGUI.add(options.perlin, 'perlins', 1.0, 5.0).name('Size').step(1); + perlinGUI.add(options.perlin, 'speed', 0.00000, 0.00050).name('Speed').listen(); + perlinGUI.add(options.perlin, 'decay', 0.0, 1.00).name('Decay').listen(); + perlinGUI.add(options.perlin, 'waves', 0.0, 20.00).name('Waves').listen(); + perlinGUI.add(options.perlin, 'fragment', true).name('Fragment'); + perlinGUI.add(options.perlin, 'complex', 0.1, 1.00).name('Complex').listen(); + perlinGUI.add(options.perlin, 'redhell', true).name('Electroflow'); + perlinGUI.add(options.perlin, 'eqcolor', 0.0, 15.0).name('Hue').listen(); + perlinGUI.open(); +} + +//-------------------------------------------------------------------- + +function animation() { + requestAnimationFrame(animation); + var performance = Date.now() * 0.003; + + _primitive.mesh.rotation.y += options.perlin.vel; + _primitive.mesh.rotation.x = (Math.sin(performance * options.spin.sinVel) * options.spin.ampVel )* Math.PI / 180; + //--- + mat.uniforms['time'].value = options.perlin.speed * (Date.now() - start); + mat.uniforms['pointscale'].value = options.perlin.perlins; + mat.uniforms['decay'].value = options.perlin.decay; + mat.uniforms['complex'].value = options.perlin.complex; + mat.uniforms['waves'].value = options.perlin.waves; + mat.uniforms['eqcolor'].value = options.perlin.eqcolor; + mat.uniforms['fragment'].value = options.perlin.fragment; + mat.uniforms['redhell'].value = options.perlin.redhell; + //--- + camera.lookAt(scene.position); + renderer.render(scene, camera); +} diff --git a/packages/magickbase/public/perlin-noise/style.css b/packages/magickbase/public/perlin-noise/style.css new file mode 100755 index 00000000..8344addc --- /dev/null +++ b/packages/magickbase/public/perlin-noise/style.css @@ -0,0 +1,50 @@ +body { + color: white; + margin: 0; + text-align: center; + background-color: black; +} +canvas { + display: block; + width: 100%; + height: 100%; +} +p { + /*font-size: 15px;*/ +} +.header { + top: 45%; +} +.footer { + bottom:3%; +} +.description { + color: gray; + padding-top: 50px; +} +a, a:hover, a:visited { + color: white; + text-decoration: none; +} +.disable-selection { + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* Internet Explorer */ + -khtml-user-select: none; /* KHTML browsers (e.g. Konqueror) */ + -webkit-user-select: none; /* Chrome, Safari, and Opera */ + -webkit-touch-callout: none; /* Disable Android and iOS callouts*/ +} +h1::after { + content: ' Three JS'; + font-size: 12px; + position:absolute; + top: 3px; + padding-left: 5px; + font-weight: 400; +} +h2::after { + content: '2'; + font-size: 12px; + position:absolute; + top: 14px; + padding-left: 5px; +} \ No newline at end of file diff --git a/packages/magickbase/src/app/globals.css b/packages/magickbase/src/app/globals.css index d4f491e1..2e4ad3f0 100644 --- a/packages/magickbase/src/app/globals.css +++ b/packages/magickbase/src/app/globals.css @@ -1,3 +1,7 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + :root { --max-width: 1100px; --border-radius: 12px; @@ -86,13 +90,8 @@ body { } body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); + color: #fff; + background: #000 } a { diff --git a/packages/magickbase/src/app/page.module.css b/packages/magickbase/src/app/page.module.css index 4732b55f..b4ca5e9d 100644 --- a/packages/magickbase/src/app/page.module.css +++ b/packages/magickbase/src/app/page.module.css @@ -269,3 +269,11 @@ transform: rotate(0deg); } } + +.separate { + clip-path: polygon(0 70%, 100% 0, 100% 100%, 0% 100%); + background: linear-gradient(180deg, #131313, #000000); + height: 248px; + margin-top: -176px; + +} diff --git a/packages/magickbase/src/components/About/index.tsx b/packages/magickbase/src/components/About/index.tsx new file mode 100644 index 00000000..b5b54088 --- /dev/null +++ b/packages/magickbase/src/components/About/index.tsx @@ -0,0 +1,77 @@ +import type { FC } from 'react' +import classnames from 'classnames' +import Spline from '@splinetool/react-spline' +import styles from './styles.module.scss' + +const timelineItms = [ + { + title: 'Vision', + description: ( +

+ Support the permissionless blockchains and to express the importance of non-permission to the community. From + the beginning, we knew that the success of the decentralized revolution depended on making it accessible to + everyone, and we set out to build the tools and infrastructure needed to make this a reality. +

+ ), + }, + { + title: 'Mission', + description: ( + <> +

+ Build a robust set of products that make it easier than ever for developers to build on the Nervos network. +

+

+ Our desktop wallet, Neuron, has become the solution of choice for experienced investors and developers. Our + development frameworks, including CKB Explorer, Godwoken Explorer, Axon Explorer, Lumos and Nexus, provide + developers with the tools they need to build high-performance decentralized applications. accessible to + everyone, and we set out to build the tools and infrastructure needed to make this a reality. +

+ + ), + }, + { + title: 'Future', + description: ( + <> +

+ We know that the decentralized revolution is just beginning, and we're committed to playing a key role in + shaping its direction. With a focus on openness, transparency, and innovation, we believe that we can build a + brighter, more decentralized future for everyone. +

+

+ At Magickbase, we believe in the power of community, collaboration, and inclusivity. We're a team of + passionate developers who are committed to making a difference in the world, and we're always looking for ways + to learn from each other and grow together. +

+ + ), + }, +] + +export const AboutUs: FC = () => ( +
+

About us

+
+
+ {timelineItms.map((item, index) => ( +
+
{(index + 1).toString().padStart(2, "0")}
+

{item.title}

+ {item.description} +
+ ))} +
+ +
+ { + console.log(app) + }} + /> +
+
+
+) diff --git a/packages/magickbase/src/components/About/styles.module.scss b/packages/magickbase/src/components/About/styles.module.scss new file mode 100644 index 00000000..78f95a8b --- /dev/null +++ b/packages/magickbase/src/components/About/styles.module.scss @@ -0,0 +1,48 @@ +.timeline { + position: relative; + &::after { + content: " "; + position: absolute; + width: 1px; + left: 0; + top: 8px; + bottom: 0; + background-color: #fff; + } + + .item { + padding-left: 24px; + padding-bottom: 64px; + position: relative; + &::after { + content: " "; + width: 12px; + height: 12px; + position: absolute; + top: 5px; + left: -6px; + border-radius: 999px; + background-color: #fff; + } + .index { + font-size: 20px; + line-height: 20px; + margin-bottom: 24px; + } + h1 { + font-size: 24px; + margin-bottom: 12px; + font-weight: 600; + } + p { + font-size: 16px; + line-height: 32px; + margin-bottom: 32px; + } + } + +} + +.splineWrapper { + pointer-events: none; +} diff --git a/packages/magickbase/src/components/Branding/index.tsx b/packages/magickbase/src/components/Branding/index.tsx new file mode 100644 index 00000000..c42c7d4c --- /dev/null +++ b/packages/magickbase/src/components/Branding/index.tsx @@ -0,0 +1,18 @@ +import type { FC } from 'react' +import classnames from 'classnames' + +export const Branding: FC = () => ( +
+
+

Building a future

+

without permission

+

With a range of services such as Neuron Wallet, CKB Browser,

+

Godwoken Browser, Axon Browser and Kuai, we can easily participate in the Nervos network ecosystem.

+
+
+