Use mantine for docs homepage (#356)

This commit is contained in:
Erik Vroon
2023-11-27 17:27:30 +01:00
committed by GitHub
parent 5a50a0c130
commit 2f27eb6396
14 changed files with 9684 additions and 205 deletions

View File

@@ -58,6 +58,8 @@ const config = {
],
],
plugins: [require.resolve('docusaurus-lunr-search')],
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
@@ -66,7 +68,7 @@ const config = {
navbar: {
title: 'Bracket',
logo: {
alt: 'My Site Logo',
alt: 'Bracket Logo',
src: 'img/logo.svg',
},
items: [
@@ -83,6 +85,11 @@ const config = {
},
],
},
colorMode: {
defaultMode: 'dark',
respectPrefersColorScheme: false,
disableSwitch: true
},
footer: {
style: 'dark',
links: [
@@ -90,34 +97,25 @@ const config = {
title: 'Docs',
items: [
{
label: 'Docs',
label: 'Introduction',
to: '/docs/intro',
},
{
label: 'Configuration',
to: '/docs/getting-started/configuration',
},
],
},
// {
// title: 'Community',
// items: [
// {
// label: 'Stack Overflow',
// href: 'https://stackoverflow.com/questions/tagged/docusaurus',
// },
// {
// label: 'Discord',
// href: 'https://discordapp.com/invite/docusaurus',
// },
// {
// label: 'Twitter',
// href: 'https://twitter.com/docusaurus',
// },
// ],
// },
{
title: 'More',
items: [
{
label: 'GitHub',
href: 'https://github.com/facebook/docusaurus',
href: 'https://github.com/evroon/bracket',
},
{
label: 'Changelog',
href: 'https://github.com/evroon/bracket/releases',
},
],
},

View File

@@ -14,16 +14,29 @@
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "2.4.0",
"@docusaurus/preset-classic": "2.4.0",
"@docusaurus/core": "^3.0.0",
"@docusaurus/preset-classic": "^3.0.0",
"@emotion/react": "^11.10.6",
"@emotion/server": "^11.10.0",
"@mantine/carousel": "^7.2.2",
"@mantine/core": "^7.2.2",
"@mantine/hooks": "^7.2.2",
"@mantine/spotlight": "^7.2.2",
"@mantinex/dev-icons": "^1.0.2",
"@mdx-js/react": "^1.6.22",
"@tabler/icons-react": "^2.17.0",
"clsx": "^1.2.1",
"docusaurus-lunr-search": "^3.3.0",
"embla-carousel-react": "^7.1.0",
"prism-react-renderer": "^1.3.5",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "2.4.0"
"@docusaurus/module-type-aliases": "^3.0.0",
"postcss": "^8.4.31",
"postcss-preset-mantine": "^1.11.0",
"postcss-simple-vars": "^7.0.1"
},
"browserslist": {
"production": [

14
docs/postcss.config.cjs Normal file
View File

@@ -0,0 +1,14 @@
module.exports = {
plugins: {
'postcss-preset-mantine': {},
'postcss-simple-vars': {
variables: {
'mantine-breakpoint-xs': '36em',
'mantine-breakpoint-sm': '48em',
'mantine-breakpoint-md': '62em',
'mantine-breakpoint-lg': '75em',
'mantine-breakpoint-xl': '88em',
},
},
},
};

View File

@@ -0,0 +1,48 @@
import { Container, Text, Button, Group } from '@mantine/core';
import { GithubIcon } from '@mantinex/dev-icons';
import classes from './styles.module.css';
import React from 'react';
export function HeroTitle() {
return (
<div className={classes.wrapper}>
<Container maxSize={'400px'} className={classes.inner}>
<h1 className={classes.title}>
Free and open source
<br/>
<Text component="span" variant="gradient" gradient={{ from: 'indigo', to: '#674ad6' }} inherit>
tournament scheduling
</Text>{' '}
system
</h1>
<Text className={classes.description} color="dimmed">
Build tournament setups, add teams, schedule matches, keep track of scores and present ranking live to the public.
</Text>
<Group className={classes.controls}>
<Button
size="xl"
className={classes.control}
variant="gradient"
gradient={{ from: 'indigo', to: '#674ad6' }}
onClick={() => {open('/bracket/docs/intro', '_self')}}
>
Get started
</Button>
<Button
component="a"
href="https://github.com/evroon/bracket"
size="xl"
variant="default"
className={classes.control}
leftSection={<GithubIcon size={20} />}
>
GitHub
</Button>
</Group>
</Container>
</div>
);
}

View File

@@ -0,0 +1,61 @@
.wrapper {
position: relative;
box-sizing: border-box;
background-color: light-dark(var(--mantine-color-white), var(--mantine-color-dark-8));
}
.inner {
position: relative;
padding-top: rem(200px);
padding-bottom: rem(120px);
@media (max-width: $mantine-breakpoint-sm) {
padding-bottom: rem(80px);
padding-top: rem(80px);
}
}
.title {
font-family: Greycliff CF, var(--mantine-font-family);
font-size: rem(62px);
font-weight: 900;
line-height: 1.1;
margin: 0;
padding: 0;
color: light-dark(var(--mantine-color-black), var(--mantine-color-white));
@media (max-width: $mantine-breakpoint-sm) {
font-size: rem(42px);
line-height: 1.2;
}
}
.description {
margin-top: var(--mantine-spacing-xl);
font-size: rem(24px);
@media (max-width: $mantine-breakpoint-sm) {
font-size: rem(18px);
}
}
.controls {
margin-top: calc(var(--mantine-spacing-xl) * 2);
@media (max-width: $mantine-breakpoint-sm) {
margin-top: var(--mantine-spacing-xl);
}
}
.control {
height: rem(54px);
padding-left: rem(38px);
padding-right: rem(38px);
@media (max-width: $mantine-breakpoint-sm) {
height: rem(54px);
padding-left: rem(18px);
padding-right: rem(18px);
flex: 1;
}
}

View File

@@ -0,0 +1,25 @@
import {Center, Image} from '@mantine/core';
import React from 'react';
import {Carousel} from "@mantine/carousel";
export function HomeCarousel() {
return (
<Center>
<Carousel
withIndicators
height={380}
slideSize="50%"
slideGap="md"
loop
align="center"
slidesToScroll={2}
>
<Carousel.Slide><Image src={require('@site/static/img/builder_preview.png').default} /></Carousel.Slide>
<Carousel.Slide><Image src={require('@site/static/img/planning_preview.png').default} /></Carousel.Slide>
<Carousel.Slide><Image src={require('@site/static/img/schedule_preview.png').default} /></Carousel.Slide>
<Carousel.Slide><Image src={require('@site/static/img/courts_preview.png').default} /></Carousel.Slide>
<Carousel.Slide><Image src={require('@site/static/img/standings_preview.png').default} /></Carousel.Slide>
</Carousel>
</Center>
);
}

View File

@@ -0,0 +1,2 @@
.wrapper {
}

View File

@@ -1,82 +0,0 @@
import React from 'react';
import clsx from 'clsx';
import styles from './styles.module.css';
const FeatureList = [
{
title: 'Open-source and free',
Svg: require('@site/static/img/availability-svgrepo-com.svg').default,
description: (
<>
Bracket is fully open source and free to use, licensed under the MIT license.
</>
),
},
{
title: 'Flexible',
Svg: require('@site/static/img/system-settings-svgrepo-com.svg').default,
description: (
<>
Bracket supports the standard tournament types, teams can be added/changed
during the tournament and new matches can be scheduled dynamically.
</>
),
},
{
title: 'Easy to use',
Svg: require('@site/static/img/interface-control-svgrepo-com.svg').default,
description: (
<>
The UI is meant to be easy to use while providing maximum flexibility.
</>
),
},
{
title: 'Selfhosted',
Svg: require('@site/static/img/host-record-svgrepo-com.svg').default,
description: (
<>
You are free to host it yourself. Setup is easy; either run it in Docker or run it the
natively on the host. The only external dependency is a PostgreSQL database.
</>
),
},
{
title: 'Modern codebase',
Svg: require('@site/static/img/multiple-defenses-svgrepo-com.svg').default,
description: (
<>
Bracket has a frontend build with Next.js and Mantine. The backend is written in async
Python using FastAPI.
</>
),
}
];
function Feature({Svg, title, description}) {
return (
<div className={clsx('col col--4')}>
<div className="text--center">
<Svg className={styles.featureSvg} role="img" />
</div>
<div className="text--center padding-horiz--md">
<h3>{title}</h3>
<p>{description}</p>
</div>
</div>
);
}
export default function HomepageFeatures() {
return (
<section className={styles.features}>
<div className="container">
<div className="row" style={{justifyContent: "center"}}>
{FeatureList.map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
</div>
</section>
);
}

View File

@@ -1,11 +0,0 @@
.features {
display: flex;
align-items: center;
padding: 2rem 0;
width: 100%;
}
.featureSvg {
height: 200px;
width: 200px;
}

View File

@@ -0,0 +1,60 @@
import {Card, Container, rem, SimpleGrid, Text, useMantineTheme,} from '@mantine/core';
import {IconBrandOpenSource, IconCloud, IconTool, IconUser} from '@tabler/icons-react';
import classes from '../pages/index.module.css';
import React from 'react';
const mockdata = [
{
title: 'Open-source and free',
description:
'Bracket is fully open source and free to use, licensed under the MIT license.',
icon: IconBrandOpenSource,
},
{
title: 'Flexible',
description:
'Bracket supports the standard tournament types, teams can be added/changed\n' +
' during the tournament and new matches can be scheduled dynamically.',
icon: IconTool,
},
{
title: 'Easy to use',
description:
'The UI is meant to be easy to use while providing maximum flexibility.',
icon: IconUser,
},
{
title: 'Self-hosted',
description:
'You are free to host it yourself. Setup is easy; either run it in Docker or run it the\n' +
' natively on the host. The only external dependency is a PostgreSQL database.',
icon: IconCloud,
},
];
export default function FeaturesCards() {
const theme = useMantineTheme();
const features = mockdata.map((feature) => (
<Card key={feature.title} shadow="md" radius="md" className={classes.card} padding="xl">
<feature.icon
style={{ width: rem(50), height: rem(50) }}
stroke={2}
color={'#674ad6'}
/>
<Text fz="lg" fw={500} className={classes.cardTitle} mt="md">
{feature.title}
</Text>
<Text fz="sm" c="dimmed" mt="sm">
{feature.description}
</Text>
</Card>
));
return (
<Container size="lg" py="xl">
<SimpleGrid cols={{ base: 1, md: 3 }} spacing="xl" mt={0}>
{features}
</SimpleGrid>
</Container>
);
}

View File

@@ -19,12 +19,16 @@
/* For readability concerns, you should choose a lighter palette in dark mode. */
[data-theme='dark'] {
--ifm-color-primary: #25c2a0;
--ifm-color-primary-dark: #21af90;
--ifm-color-primary-darker: #1fa588;
--ifm-color-primary-darkest: #1a8870;
--ifm-color-primary-light: #29d5b0;
--ifm-color-primary-lighter: #32d8b4;
--ifm-color-primary-lightest: #4fddbf;
--ifm-color-primary: #bcafed;
--ifm-color-primary-dark: #a08de5;
--ifm-color-primary-darker: #927de2;
--ifm-color-primary-darkest: #674ad6;
--ifm-color-primary-light: #d8d1f5;
--ifm-color-primary-lighter: #e6e1f8;
--ifm-color-primary-lightest: #ffffff;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
}
.footer {
background-color: light-dark(var(--mantine-color-dark-8), var(--mantine-color-dark-8));
}

View File

@@ -1,52 +1,39 @@
import React from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Layout from '@theme/Layout';
import HomepageFeatures from '@site/src/components/HomepageFeatures';
import {Container, createTheme, MantineProvider, Title} from "@mantine/core";
import '@mantine/core/styles.css';
import '@mantine/carousel/styles.css';
import {HeroTitle} from "../components/HeroTitle";
import {HomeCarousel} from "../components/HomeCarousel";
import classes from "./index.module.css";
import FeaturesCards from "../components/feature_cards";
import styles from './index.module.css';
function HomepageHeader() {
const {siteConfig} = useDocusaurusContext();
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<div className={styles.heroRow}>
<div className={clsx(styles.heroColumn, styles.heroColumn4)}>
<h1 className="hero__title">{siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="/docs/intro">
Get Started
</Link>
</div>
</div>
<div className={clsx(styles.heroColumn, styles.heroColumn6)}>
<div className="text--center">
<img alt="Preview of the web interface"
src={require('@site/static/img/schedule_preview.png').default}
width="100%"/>
</div>
</div>
</div>
</div>
</header>
);
}
const theme = createTheme({});
export default function Home() {
const {siteConfig} = useDocusaurusContext();
return (
<Layout
title={''}
description="Description will go into a meta tag in <head />">
<HomepageHeader />
<main>
<HomepageFeatures />
</main>
</Layout>
<MantineProvider theme={theme} defaultColorScheme="dark">
<Layout
title={''}
description="Description will go into a meta tag in <head />">
<HeroTitle/>
<main>
<Title order={2} className={classes.title} ta="center" mt="lg">
Features
</Title>
<FeaturesCards/>
<Container size='50%' mt="lg">
<Title order={2} className={classes.title} ta="center" my="lg">
Preview
</Title>
<HomeCarousel/>
</Container>
</main>
</Layout>
</MantineProvider>
);
}

View File

@@ -3,49 +3,42 @@
* and scoped locally.
*/
.heroBanner {
padding: 4rem 0;
text-align: center;
position: relative;
overflow: hidden;
background-color: #3c4a67;
}
.title {
font-size: rem(34px);
font-weight: 900;
@media screen and (max-width: 996px) {
.heroBanner {
padding: 2rem;
@media (max-width: $mantine-breakpoint-sm) {
font-size: rem(24px);
}
}
.buttons {
display: flex;
align-items: center;
justify-content: center;
}
.description {
max-width: rem(600px);
margin: auto;
/* Create two equal columns that floats next to each other */
.heroColumn {
float: left;
color: white;
padding: 1rem;
}
.heroColumn4 {
width: 40%;
}
.heroColumn6 {
width: 60%;
}
/* Clear floats after the columns */
.heroRow:after {
content: "";
display: table;
clear: both;
}
/* Responsive layout - makes the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 900px) {
.heroColumn {
width: 100%;
&::after {
content: '';
display: block;
background-color: #674ad6;
width: rem(45px);
height: rem(2px);
margin-top: var(--mantine-spacing-sm);
margin-left: auto;
margin-right: auto;
}
}
.card {
border: rem(1px) solid light-dark(var(--mantine-color-gray-1), var(--mantine-color-dark-5));
}
.cardTitle {
&::after {
content: '';
display: block;
background-color: #674ad6;
width: rem(45px);
height: rem(2px);
margin-top: var(--mantine-spacing-sm);
}
}

9367
docs/yarn.lock Normal file
View File

File diff suppressed because it is too large Load Diff