From 50e929e5335f41c1d0dbe7d04da1ec6d3857a8b5 Mon Sep 17 00:00:00 2001 From: chenchongqiang Date: Sun, 14 May 2023 22:51:40 +0800 Subject: [PATCH] refactor(doc): refactor home page ui --- .eslintrc.js | 2 +- apps/doc/docusaurus.config.js | 16 ++-- apps/doc/package.json | 1 + .../src/components/HomepageFeatures/index.tsx | 93 ++++++++++++++---- .../HomepageFeatures/styles.module.css | 19 ++-- apps/doc/src/constants/sol.ts | 4 + apps/doc/src/hooks/use-width.ts | 22 +++++ apps/doc/src/pages/index.module.css | 13 ++- apps/doc/src/pages/index.tsx | 96 ++++++++++--------- pnpm-lock.yaml | 5 +- 10 files changed, 178 insertions(+), 93 deletions(-) create mode 100644 apps/doc/src/constants/sol.ts create mode 100644 apps/doc/src/hooks/use-width.ts diff --git a/.eslintrc.js b/.eslintrc.js index 6c5df1b..fb157e3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -91,7 +91,7 @@ module.exports = { 'import/no-unresolved': [ 'error', { - ignore: ['^@theme-original', '^@docusaurus', '^@theme-init'], + ignore: ['^@theme-original', '^@docusaurus', '^@theme-init', '^@theme'], }, ], diff --git a/apps/doc/docusaurus.config.js b/apps/doc/docusaurus.config.js index c7fa1a2..e9d6682 100644 --- a/apps/doc/docusaurus.config.js +++ b/apps/doc/docusaurus.config.js @@ -31,8 +31,8 @@ const SECTIONS = [ /** @type {import('@docusaurus/types').Config} */ const config = { - title: "SoLive", - tagline: "Online playground for Solidity", + title: "Solive", + tagline: "Solive is a platform for creating and managing Solidity smart contracts with a React component that works on mobile browsers and can be embedded into websites.", favicon: "img/favicon.ico", // Set the production url of your site here @@ -43,8 +43,8 @@ const config = { // GitHub pages deployment config. // If you aren't using GitHub pages, you don't need these. - organizationName: "SoLive", // Usually your GitHub org/user name. - projectName: "SoLive", // Usually your repo name. + organizationName: "Solive", // Usually your GitHub org/user name. + projectName: "Solive", // Usually your repo name. onBrokenLinks: "throw", onBrokenMarkdownLinks: "warn", @@ -95,12 +95,12 @@ const config = { defaultMode: 'dark', disableSwitch: false, respectPrefersColorScheme: false, - }, + }, image: "img/docusaurus-social-card.jpg", navbar: { - title: "SoLive", + title: "Solive", logo: { - alt: "SoLive", + alt: "Solive", src: "img/logo_300x300.png", }, items: [ @@ -117,7 +117,7 @@ const config = { }, { type: 'localeDropdown', - }, + }, ], }, footer: { diff --git a/apps/doc/package.json b/apps/doc/package.json index 0f483a8..9c0834a 100644 --- a/apps/doc/package.json +++ b/apps/doc/package.json @@ -22,6 +22,7 @@ "ahooks": "^3.7.4", "axios": "^1.3.1", "clsx": "^1.2.1", + "solive-core": "workspace:*", "lodash": "^4.17.21", "prism-react-renderer": "^1.3.5", "react": "^18.0.0", diff --git a/apps/doc/src/components/HomepageFeatures/index.tsx b/apps/doc/src/components/HomepageFeatures/index.tsx index 5c6c95b..1bd662d 100644 --- a/apps/doc/src/components/HomepageFeatures/index.tsx +++ b/apps/doc/src/components/HomepageFeatures/index.tsx @@ -1,4 +1,8 @@ import React from 'react'; + +import Editor from 'solive-core'; +import { BallotSol, OwnerSol } from '@site/src/constants/sol'; + import styles from './styles.module.css'; type FeatureItem = { @@ -31,14 +35,13 @@ const FeatureList: FeatureItem[] = [ imgUrl: require('@site/static/img/home_feature_item3.png').default, description: ( <> - better solidity ABI to UI design. + better solidity ABI to UI design. ), }, ]; - -function Feature({title, imgUrl, description}: FeatureItem) { +function Feature({ title, imgUrl, description }: FeatureItem) { return (
@@ -52,11 +55,32 @@ export default function HomepageFeatures(): JSX.Element { return (
-
-

Say hi to SoLive 🤟

-
-

SoLive is a flexible online playground for Solidity smart contracts, inspired by remix-IDE and react-live. SoLive enables you to edit, compile, deploy, and interact with solidity smart contracts in one React component. You can embed SoLive into your website/tutorials and let users run solidity code in the browser. SoLive is also compatible with mobile browsers.

-
+ =0.7.0 <0.9.0;\n\n/**\n * @title Storage\n * ' + + '@dev Store & retrieve value in a variable\n * @custom:dev-run-script ./scripts/deploy_with_ethers.ts\n */\ncontract ' + + 'Storage {\n\n uint256 number;\n\n /**\n * @dev Store value in variable\n ' + + '* @param num value to store\n */\n function store(uint256 num) public {\n ' + + "number = num;\n }\n\n /**\n * @dev Return value \n * @return value of 'number'\n " + + ' */\n function retrieve() public view returns (uint256){\n return number;\n }\n}', + language: 'solidity' as any, + }, + { + filename: '_Owner.sol', + value: JSON.parse(OwnerSol), + language: 'solidity' as any, + }, + { + filename: '_Ballot.sol', + value: JSON.parse(BallotSol), + language: 'solidity' as any, + }, + ]} + height="500px" + />
What's next:
@@ -68,21 +92,50 @@ export default function HomepageFeatures(): JSX.Element { ); } - function StarknetLogo() { return ( - - - - - - - + + + + + + + - + @@ -92,8 +145,10 @@ function StarknetLogo() { function LinkIcon() { return ( - + ); } - diff --git a/apps/doc/src/components/HomepageFeatures/styles.module.css b/apps/doc/src/components/HomepageFeatures/styles.module.css index fa2da10..c0cf437 100644 --- a/apps/doc/src/components/HomepageFeatures/styles.module.css +++ b/apps/doc/src/components/HomepageFeatures/styles.module.css @@ -14,12 +14,14 @@ .overview{ display: flex; - max-width: 1000px; + width: 50%; padding: 30px 40px; border-radius: 6px; border: 0.5px solid #CECECE; box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.1); margin-bottom: 80px; + flex-direction: column; + justify-content: center; } .overviewLogo{ @@ -27,11 +29,6 @@ height: 92px; } - -.overviewText{ - padding-left: 40px; -} - .overviewTextTitle{ font-family: 'Inter'; font-size: 32px; @@ -180,9 +177,9 @@ } @media (max-width: 996px){ - .overview{ - flex-direction: column; - justify-content: center; + .overview { + width: 100%; + padding: 8px; } .overviewLogo{ @@ -191,7 +188,7 @@ margin: 0 auto; margin-bottom: 30px; } - + .overviewLogo svg{ width: 100%; height: 100%; @@ -212,4 +209,4 @@ .featureItem{ width: 100%; } -} \ No newline at end of file +} diff --git a/apps/doc/src/constants/sol.ts b/apps/doc/src/constants/sol.ts new file mode 100644 index 0000000..1643db2 --- /dev/null +++ b/apps/doc/src/constants/sol.ts @@ -0,0 +1,4 @@ +// eslint-disable-next-line max-len +export const OwnerSol = '"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.7.0 <0.9.0;\\n\\n/**\\n * @title Owner\\n * @dev Set & change owner\\n */\\ncontract Owner {\\n\\n address private owner;\\n\\n // event for EVM logging\\n event OwnerSet(address indexed oldOwner, address indexed newOwner);\\n\\n // modifier to check if caller is owner\\n modifier isOwner() {\\n // If the first argument of \'require\' evaluates to \'false\', execution terminates and all\\n // changes to the state and to Ether balances are reverted.\\n // This used to consume all gas in old EVM versions, but not anymore.\\n // It is often a good idea to use \'require\' to check if functions are called correctly.\\n // As a second argument, you can also provide an explanation about what went wrong.\\n require(msg.sender == owner, \\"Caller is not owner\\");\\n _;\\n }\\n\\n /**\\n * @dev Set contract deployer as owner\\n */\\n constructor() {\\n owner = msg.sender; // \'msg.sender\' is sender of current call, contract deployer for a constructor\\n emit OwnerSet(address(0), owner);\\n }\\n\\n /**\\n * @dev Change owner\\n * @param newOwner address of new owner\\n */\\n function changeOwner(address newOwner) public isOwner {\\n emit OwnerSet(owner, newOwner);\\n owner = newOwner;\\n }\\n\\n /**\\n * @dev Return owner address \\n * @return address of owner\\n */\\n function getOwner() external view returns (address) {\\n return owner;\\n }\\n} "'; +// eslint-disable-next-line max-len +export const BallotSol = '"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.7.0 <0.9.0;\\n\\n/** \\n * @title Ballot\\n * @dev Implements voting process along with vote delegation\\n */\\ncontract Ballot {\\n\\n struct Voter {\\n uint weight; // weight is accumulated by delegation\\n bool voted; // if true, that person already voted\\n address delegate; // person delegated to\\n uint vote; // index of the voted proposal\\n }\\n\\n struct Proposal {\\n // If you can limit the length to a certain number of bytes, \\n // always use one of bytes1 to bytes32 because they are much cheaper\\n bytes32 name; // short name (up to 32 bytes)\\n uint voteCount; // number of accumulated votes\\n }\\n\\n address public chairperson;\\n\\n mapping(address => Voter) public voters;\\n\\n Proposal[] public proposals;\\n\\n /** \\n * @dev Create a new ballot to choose one of \'proposalNames\'.\\n * @param proposalNames names of proposals\\n */\\n constructor(bytes32[] memory proposalNames) {\\n chairperson = msg.sender;\\n voters[chairperson].weight = 1;\\n\\n for (uint i = 0; i < proposalNames.length; i++) {\\n // \'Proposal({...})\' creates a temporary\\n // Proposal object and \'proposals.push(...)\'\\n // appends it to the end of \'proposals\'.\\n proposals.push(Proposal({\\n name: proposalNames[i],\\n voteCount: 0\\n }));\\n }\\n }\\n\\n /** \\n * @dev Give \'voter\' the right to vote on this ballot. May only be called by \'chairperson\'.\\n * @param voter address of voter\\n */\\n function giveRightToVote(address voter) public {\\n require(\\n msg.sender == chairperson,\\n \\"Only chairperson can give right to vote.\\"\\n );\\n require(\\n !voters[voter].voted,\\n \\"The voter already voted.\\"\\n );\\n require(voters[voter].weight == 0);\\n voters[voter].weight = 1;\\n }\\n\\n /**\\n * @dev Delegate your vote to the voter \'to\'.\\n * @param to address to which vote is delegated\\n */\\n function delegate(address to) public {\\n Voter storage sender = voters[msg.sender];\\n require(!sender.voted, \\"You already voted.\\");\\n require(to != msg.sender, \\"Self-delegation is disallowed.\\");\\n\\n while (voters[to].delegate != address(0)) {\\n to = voters[to].delegate;\\n\\n // We found a loop in the delegation, not allowed.\\n require(to != msg.sender, \\"Found loop in delegation.\\");\\n }\\n sender.voted = true;\\n sender.delegate = to;\\n Voter storage delegate_ = voters[to];\\n if (delegate_.voted) {\\n // If the delegate already voted,\\n // directly add to the number of votes\\n proposals[delegate_.vote].voteCount += sender.weight;\\n } else {\\n // If the delegate did not vote yet,\\n // add to her weight.\\n delegate_.weight += sender.weight;\\n }\\n }\\n\\n /**\\n * @dev Give your vote (including votes delegated to you) to proposal \'proposals[proposal].name\'.\\n * @param proposal index of proposal in the proposals array\\n */\\n function vote(uint proposal) public {\\n Voter storage sender = voters[msg.sender];\\n require(sender.weight != 0, \\"Has no right to vote\\");\\n require(!sender.voted, \\"Already voted.\\");\\n sender.voted = true;\\n sender.vote = proposal;\\n\\n // If \'proposal\' is out of the range of the array,\\n // this will throw automatically and revert all\\n // changes.\\n proposals[proposal].voteCount += sender.weight;\\n }\\n\\n /** \\n * @dev Computes the winning proposal taking all previous votes into account.\\n * @return winningProposal_ index of winning proposal in the proposals array\\n */\\n function winningProposal() public view\\n returns (uint winningProposal_)\\n {\\n uint winningVoteCount = 0;\\n for (uint p = 0; p < proposals.length; p++) {\\n if (proposals[p].voteCount > winningVoteCount) {\\n winningVoteCount = proposals[p].voteCount;\\n winningProposal_ = p;\\n }\\n }\\n }\\n\\n /** \\n * @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then\\n * @return winnerName_ the name of the winner\\n */\\n function winnerName() public view\\n returns (bytes32 winnerName_)\\n {\\n winnerName_ = proposals[winningProposal()].name;\\n }\\n}"'; diff --git a/apps/doc/src/hooks/use-width.ts b/apps/doc/src/hooks/use-width.ts new file mode 100644 index 0000000..4ce504b --- /dev/null +++ b/apps/doc/src/hooks/use-width.ts @@ -0,0 +1,22 @@ +// An highlighted block +import { useState, useEffect } from 'react'; + +export const useWidth = () => { + // 第一步:声明能够体现视口大小变化的状态 + const [windowSize, setWindowSize] = useState({ + width: window.innerWidth, + height: window.innerHeight, + }); + + // 第二步:通过生命周期 Hook 声明回调的绑定和解绑逻辑 + useEffect(() => { + const updateSize = () => setWindowSize({ + width: window.innerWidth, + height: window.innerHeight, + }); + window.addEventListener('resize', updateSize); + return () => window.removeEventListener('resize', updateSize); + }, []); + + return windowSize; +}; diff --git a/apps/doc/src/pages/index.module.css b/apps/doc/src/pages/index.module.css index fc6fdde..2a7cf40 100644 --- a/apps/doc/src/pages/index.module.css +++ b/apps/doc/src/pages/index.module.css @@ -45,7 +45,7 @@ a:hover{ position: relative; font-family: 'Inter'; font-weight: 700; - font-size: 48px; + font-size: 60px; line-height: 1.2; margin-top: 75px; padding: 0 20px; @@ -56,9 +56,10 @@ a:hover{ font-family: 'Inter'; font-weight: 400; font-size: 24px; - line-height: 1.2; - margin-top: 32px; + line-height: 1.5; padding: 0 20px; + max-width: 60%; + margin: 32px auto 0; } .buttons { @@ -105,4 +106,8 @@ a:hover{ .heroBannerTitle{ font-size: 42px; } -} \ No newline at end of file + .heroBannerSubTitle{ + font-size: 20px; + max-width: 90%; + } +} diff --git a/apps/doc/src/pages/index.tsx b/apps/doc/src/pages/index.tsx index 1c23f84..0bda33e 100644 --- a/apps/doc/src/pages/index.tsx +++ b/apps/doc/src/pages/index.tsx @@ -1,9 +1,10 @@ import React from 'react'; + import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Layout from '@theme/Layout'; -import HomepageFeatures from "@site/src/components/HomepageFeatures"; +import HomepageFeatures from '@site/src/components/HomepageFeatures'; -import styles from "./index.module.css"; +import styles from './index.module.css'; function HomepageHeader() { const { siteConfig } = useDocusaurusContext(); @@ -11,10 +12,10 @@ function HomepageHeader() {
- +
- +

{siteConfig.title}

{siteConfig.tagline}

@@ -24,70 +25,71 @@ function HomepageHeader() { } export default function Home(): JSX.Element { - const {siteConfig} = useDocusaurusContext(); + const { siteConfig } = useDocusaurusContext(); - return ( - - -
- -
-
- ); + return ( + + +
+ +
+
+ ); } -function HeroBannerLeftStar(){ +function HeroBannerLeftStar() { return ( - - - - - - - - - + + + + + + + + + - + - + - ) + ); } -function HeroBannerRightStar(){ +function HeroBannerRightStar() { return ( - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - ) + ); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index db16739..081bc2a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -179,6 +179,7 @@ importers: react-hot-toast: ^2.4.0 react-jazzicon: ^1.0.4 react-scripts: 5.0.1 + solive-core: workspace:* solive-docusaurus-theme-code: workspace:* typescript: ^4.7.4 dependencies: @@ -196,6 +197,7 @@ importers: react-hot-toast: 2.4.0_biqbaboplfbrettd7655fr4n2y react-jazzicon: 1.0.4_biqbaboplfbrettd7655fr4n2y react-scripts: 5.0.1_j5ip3o3v6sktjzl5cxtjyfbuo4 + solive-core: link:../../packages/core solive-docusaurus-theme-code: link:../../packages/docusaurus-plugin devDependencies: '@docusaurus/module-type-aliases': 2.3.0_biqbaboplfbrettd7655fr4n2y @@ -220,7 +222,6 @@ importers: solive-core: workspace:* tailwindcss: 3.3.1 typescript: 5.0.4 - webpack-node-externals: ^3.0.0 dependencies: '@headlessui/react': 1.7.13_biqbaboplfbrettd7655fr4n2y '@heroicons/react': 2.0.17_react@18.2.0 @@ -237,8 +238,6 @@ importers: solive-core: link:../../packages/core tailwindcss: 3.3.1_postcss@8.4.21 typescript: 5.0.4 - devDependencies: - webpack-node-externals: r2.cnpmjs.org/webpack-node-externals/3.0.0 packages/compiler-utils: specifiers: