Skip to content

Commit

Permalink
Redesign homepage (KusionStack#179)
Browse files Browse the repository at this point in the history
* refresh homepage: header, features, who-using

* remove unused files

* minor fix: fix quick start link

* remove unused class

* remove unused class

* minor class fix

* add codify examples into homepage

* Update index.tsx
  • Loading branch information
ldxdl authored Nov 2, 2022
1 parent 2d08f67 commit 4dabe36
Show file tree
Hide file tree
Showing 13 changed files with 1,013 additions and 2 deletions.
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"react-dom": "^17.0.1",
"remark-math": "^3.0.1",
"trim": "0.0.3",
"url-loader": "^4.1.1"
"url-loader": "^4.1.1",
"throttle-debounce": "3.0.1"
},
"browserslist": {
"production": [
Expand Down
231 changes: 231 additions & 0 deletions src/components/ExampleScroller/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
import React, { useCallback, useEffect, useState } from "react"
import useWindowWidth from "@theme/useWindowWidth"
import clsx from "clsx"
import Highlight from "../Highlight"
import Chevron from "@theme/Chevron"
import seCss from "../../css/section.module.css"
import shCss from "../../css/index/showcase.module.css"

const S = [3, 5, 19, 31]
const M = [3, 5, 19, 31]
const L = [4, 5, 19, 31]

const getTopByIndex = (m: number[], index: 1 | 2 | 3 | 4): number => {
const scale = {
1: 20 * (m[0] ?? 0),
2: -25 * (m[1] ?? 0),
3: -25 * (m[2] ?? 0),
4: -25 * (m[3] ?? 0),
}

return scale[index] ?? 0
}

const configExample = `import base.pkg.kusion_models.kube.frontend
appConfiguration: frontend.Server {
image = "howieyuen/gocity:latest"
}`

const schemaExample = `schema Server:
"""Server is the abstraction of Deployment and StatefulSet.
image: str, default is Undefined, required.
Image name. More info: https://kubernetes.io/docs/concepts/containers/images.
replicas: int, default is 1, required.
Number of desired pods. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1.
labels: {str:str}, default is Undefined, optional.
Labels is a map of string keys and values that can be used to organize and categorize (scope and select) objects.
"""
image: str
replicas: int = option("replicas") or 1
labels?: {str:str}
`

const LambdaExample = `import base.pkg.kusion_models.kube.frontend
genLocalityLabels = lambda az: str, cell: str, cluster: str, app: str -> {str:str} {
{
"aws/az" = az
"aws/cell" = cell
"cluster.x-k8s.io/cluster-name" = cluster
"app.kubernetes.io/name" = app
}
}
appConfiguration: frontend.Server {
labels: genLocalityLabels("us-west-1a", "us-west-2-lax-1a", "my-cluster", "gocity")
}
`

const ruleExample = `import regex
rule ServerRule for Server:
1 <= replicas < 20, "replica should be in range [1, 20)"
regex.match(image, r"^([a-z0-9\.\:]+)\.([a-z]+)\:([a-z0-9]+)\/([a-z0-9\.]+)\/([a-z0-9-_.:]+)$"), "image name should satisfy the \`REPOSITORY:TAG\` form"
ServerRule()
`

type Index = 1 | 2 | 3 | 4

export const ExampleScroller = () => {
const [top, setTop] = useState(S)
const [index, setIndex] = useState<Index>(1)
const windowWidth = useWindowWidth()
const handleClick1 = useCallback(() => {
setIndex(1)
}, [])
const handleClick2 = useCallback(() => {
setIndex(2)
}, [])
const handleClick3 = useCallback(() => {
setIndex(3)
}, [])
const handleClick4 = useCallback(() => {
setIndex(4)
}, [])
const handleUpClick = useCallback(() => {
setIndex(Math.max(index - 1, 1) as Index)
}, [index])
const handleDownClick = useCallback(() => {
setIndex(Math.min(index + 1, 4) as Index)
}, [index])

useEffect(() => {
if (windowWidth != null && windowWidth < 622) {
setTop(S)
return
}

if (windowWidth != null && windowWidth < 800) {
setTop(M)
return
}

setTop(L)
}, [windowWidth])

return (
<section
className={clsx(
seCss.section,
seCss["section--inner"],
seCss["section--center"],
seCss["section--showcase"],
)}
>
<h2
className={clsx(
seCss.section__title,
seCss["section__title--wide"],
"text--center",
)}
>
Codify Your Modern Delivery
</h2>

<p
className={clsx(
"text--center",
)}
>
With configs, models, functions and rules
</p>

<div className={shCss.showcase}>
<div className={shCss.showcase__inner}>
<div
className={clsx(shCss.showcase__chevron)}
onClick={handleUpClick}
style={{ visibility: index === 1 ? "hidden" : "visible" }}
>
<Chevron />
</div>
<div className={clsx(shCss.showcase__left)}>
<div
className={clsx(
shCss.showcase__offset,
shCss[`showcase__${index}`],
)}
style={{ top: getTopByIndex(top, index) }}
>
<Highlight code={configExample} />
<Highlight code={`-- Config\n${configExample}`} />
<Highlight code={schemaExample} />
<Highlight code={`-- Schema\n${schemaExample}`} />
<Highlight code={LambdaExample} />
<Highlight code={`-- Lambda\n${LambdaExample}`} />
<Highlight code={ruleExample} />
<Highlight code={`-- Rule\n${ruleExample}`} />
</div>
</div>
<div
className={clsx(
shCss.showcase__chevron,
shCss["showcase__chevron--bottom"],
)}
onClick={handleDownClick}
style={{ visibility: index === 4 ? "hidden" : "visible" }}
>
<Chevron />
</div>
<div className={shCss.showcase__right}>
<div
className={clsx(shCss.showcase__button, {
[shCss["showcase__button--active"]]: index === 1,
})}
onClick={handleClick1}
>
<h3 className={shCss.showcase__header}>
Config
</h3>
<p className={shCss.showcase__description}>
Start your cloud-native journey with scalable config
</p>
</div>

<div
className={clsx(shCss.showcase__button, {
[shCss["showcase__button--active"]]: index === 2,
})}
onClick={handleClick2}
>
<h3 className={shCss.showcase__header}>
Schema
</h3>
<p className={shCss.showcase__description}>
Abstract your schema-centric model with static typing
</p>
</div>

<div
className={clsx(shCss.showcase__button, {
[shCss["showcase__button--active"]]: index === 3,
})}
onClick={handleClick3}
>
<h3 className={shCss.showcase__header}>
Lambda
</h3>
<p className={shCss.showcase__description}>
Define and reuse your config and logic through small function fragments
</p>
</div>
<div
className={clsx(shCss.showcase__button, {
[shCss["showcase__button--active"]]: index === 4,
})}
onClick={handleClick4}
>
<h3 className={shCss.showcase__header}>
Rule
</h3>
<p className={shCss.showcase__description}>
Define your environmental rules to ensure consistency and stability
</p>
</div>
</div>
</div>
</div>
</section>
)
}
42 changes: 42 additions & 0 deletions src/components/Highlight/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from "react"

import Prism, { defaultProps } from "prism-react-renderer"

import DarkTheme from "../../internals/prism-dracula"
import LightTheme from "../../internals/prism-github"

const themes = {
light: LightTheme,
dark: DarkTheme,
}

const Highlight = ({
code,
theme = "dark",
}: {
code: string
theme?: "light" | "dark"
}) => (
<div>
<Prism
{...defaultProps}
language="python"
code={code}
theme={themes[theme]}
>
{({ className, style, tokens, getLineProps, getTokenProps }) => (
<pre className={className} style={style}>
{tokens.map((line, i) => (
<div key={i} {...getLineProps({ line, key: i })}>
{line.map((token, key) => (
<span key={key} {...getTokenProps({ token, key })} />
))}
</div>
))}
</pre>
)}
</Prism>
</div>
)

export default Highlight
33 changes: 33 additions & 0 deletions src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,39 @@
*/

:root {
--palette-charade: #21222c;
--palette-gray: #32343e;
--palette-green: #66bb6a;
--palette-midnight: #141725;
--palette-pale-blue: #b1b5d3;
--palette-pink: #d14671;
--palette-pink-darker: #be2f5b;
--palette-rock: rgb(var(--palette-rock-raw));
--palette-rock-raw: 38, 40, 51;
--palette-sky: #81d3f9;
--palette-turquoise: #0cc0df;
--palette-black-10: rgba(0, 0, 0, 0.1);
--palette-white: #fff;
--palette-white-03: rgba(255, 255, 255, 0.03);
--palette-white-05: rgba(255, 255, 255, 0.05);
--palette-white-10: rgba(255, 255, 255, 0.1);
--palette-white-20: rgba(255, 255, 255, 0.2);
--palette-white-30: rgba(255, 255, 255, 0.3);
--palette-white-40: rgba(255, 255, 255, 0.4);
--palette-white-60: rgba(255, 255, 255, 0.6);
--palette-white-darker: #d9d9d9;
--palette-yellow: #ffd54f;
--image-shadow: 0 15px 61px 5px rgba(20, 23, 37, 0.94);

--font-size-small: 15px;
--font-size-normal: 16px;
--font-size-large: 17px;
--font-size-big-1: 22px;
--font-size-big-2: 24px;
--font-size-big-3: 32px;
--font-size-big-4: 46px;
--font-size-big-5: 64px;

/*
See css var + hsl color palette technique:
https://blog.maximeheckel.com/posts/the-power-of-composition-with-css-variables/
Expand Down
Loading

0 comments on commit 4dabe36

Please sign in to comment.