mirror of
https://github.com/evroon/bracket.git
synced 2026-04-26 02:07:13 -04:00
Use mantine for docs homepage (#356)
This commit is contained in:
@@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -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
14
docs/postcss.config.cjs
Normal 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',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
48
docs/src/components/HeroTitle/index.js
Normal file
48
docs/src/components/HeroTitle/index.js
Normal 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>
|
||||
);
|
||||
}
|
||||
61
docs/src/components/HeroTitle/styles.module.css
Normal file
61
docs/src/components/HeroTitle/styles.module.css
Normal 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;
|
||||
}
|
||||
}
|
||||
25
docs/src/components/HomeCarousel/index.js
Normal file
25
docs/src/components/HomeCarousel/index.js
Normal 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>
|
||||
);
|
||||
}
|
||||
2
docs/src/components/HomeCarousel/styles.module.css
Normal file
2
docs/src/components/HomeCarousel/styles.module.css
Normal file
@@ -0,0 +1,2 @@
|
||||
.wrapper {
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
.features {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2rem 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.featureSvg {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
}
|
||||
60
docs/src/components/feature_cards.js
Normal file
60
docs/src/components/feature_cards.js
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
9367
docs/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user