1
0
Fork 0

feat: Created home page

This commit is contained in:
joostdecock 2025-03-08 16:32:02 +01:00
parent a4bdc3a2da
commit 88e06ce70e
23 changed files with 815 additions and 147 deletions

1
.gitignore vendored
View file

@ -53,6 +53,7 @@ sites/org/authors.json
sites/org/showcase-tags.mjs
sites/org/design-examples.mjs
sites/org/docs/designs/*.mdx
sites/org/recent-blog-posts.mjs
# sde auto-generated content
sites/sde/public/android-chrome-192x192.png

View file

@ -101,6 +101,7 @@ packageJson:
"./components/Null": "./components/Null/index.mjs"
"./components/Number": "./components/Number/index.mjs"
"./components/Pattern": "./components/Pattern/index.mjs"
"./components/Patrons": "./components/Patrons/index.mjs"
"./components/Popout": "./components/Popout/index.mjs"
"./components/Role": "./components/Role/index.mjs"
"./components/SignIn": "./components/SignIn/index.mjs"

View file

@ -55,12 +55,27 @@ export const SuccessLink = ({
</a>
)
export const CardLink = ({ href, title, Icon, children, Link }) => {
export const CardLink = ({
href,
title,
icon,
children,
Link,
className = 'tw-bg-base-200 tw-text-base-content',
}) => {
if (!Link) Link = BaseLink
return (
<Link className="">
{title}
<Link
href={href}
className={`tw-px-8 tw-py-10 tw-rounded-lg tw-block ${className}
hover:tw-bg-secondary hover:tw-bg-opacity-10 tw-shadow-lg
tw-transition-color tw-duration-300 grow hover:tw-no-underline hover:tw-text-base-content`}
>
<h2 className="tw-mb-4 tw-text-inherit tw-flex tw-flex-row tw-gap-4 tw-justify-between tw-items-center">
{title}
<span className="tw-shrink-0">{icon}</span>
</h2>
{children}
</Link>
)

File diff suppressed because one or more lines are too long

View file

@ -26,7 +26,7 @@ import { EmailInput } from '@freesewing/react/components/Input'
import { IconButton } from '@freesewing/react/components/Button'
//import { Robot } from 'shared/components/robot/index.mjs'
export const SignUp = () => {
export const SignUp = ({ embed = false }) => {
// State
const [email, setEmail] = useState('')
const [emailValid, setEmailValid] = useState(false)
@ -56,22 +56,22 @@ export const SignUp = () => {
if (status === 201 && body.result === 'created') setResult('success')
else {
setModal(
<ModalWrapper bg="base-100 lg:bg-base-300">
<div className="bg-base-100 rounded-lg p-4 lg:px-8 max-w-xl lg:shadow-lg">
<ModalWrapper bg="tw-base-100 lg:tw-bg-base-300">
<div className="tw-bg-base-100 tw-rounded-lg tw-p-4 lg:tw-px-8 tw-max-w-xl lg:tw-shadow-lg">
<h3>An error occured while trying to process your request</h3>
<p className="text-lg">
<p className="tw-text-lg">
Unfortunately, we cannot recover from this error, we need a human being to look into
this.
</p>
<p className="text-lg">
<p className="tw-text-lg">
Feel free to try again, or reach out to support so we can assist you.
</p>
<div className="flex flex-row gap-4 items-center justify-center p-8 flex-wrap">
<div className="tw-flex tw-flex-row tw-gap-4 tw-items-center tw-justify-center tw-p-8 tw-flex-wrap">
<IconButton onClick={() => setResult(false)}>
<LeftIcon />
Back
</IconButton>
<IconButton href="/support" className="daisy-btn-outline">
<IconButton href="/support" className="tw-daisy-btn-outline">
<HelpIcon />
Contact support
</IconButton>
@ -90,10 +90,13 @@ export const SignUp = () => {
window.location.href = result.data.authUrl
}
}
const Heading = embed
? ({ children }) => <h2 className="tw-text-inherit">{children}</h2>
: ({ children }) => <h1 className="tw-text-inherit">{children}</h1>
return (
<div className="w-full">
<h1 className="text-inherit">
<div className="tw-w-full">
<Heading className="tw-text-inherit">
{result ? (
result === 'success' ? (
<span>Now check your inbox</span>
@ -103,23 +106,23 @@ export const SignUp = () => {
) : (
<span>Create a FreeSewing account</span>
)}
</h1>
</Heading>
{result ? (
result === 'success' ? (
<>
<p className="text-inherit text-lg">
<p className="tw-text-inherit tw-text-lg">
Go check your inbox for an email from <b>FreeSewing.org</b>
</p>
<p className="text-inherit text-lg">
<p className="tw-text-inherit tw-text-lg">
Click your personal signup link in that email to create your FreeSewing account.
</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-2">
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-2">
<IconButton onClick={() => setResult(false)}>
<LeftIcon />
Back
</IconButton>
<IconButton href="/support" className="daisy-btn-outline">
<IconButton href="/support" className="tw-daisy-btn-outline">
<HelpIcon />
Contact support
</IconButton>
@ -128,18 +131,18 @@ export const SignUp = () => {
) : (
<>
robot here
<p className="text-inherit text-lg">
<p className="tw-text-inherit tw-text-lg">
Unfortunately, we cannot recover from this error, we need a human being to look into
this.
</p>
<p className="text-inherit text-lg">
<p className="tw-text-inherit tw-text-lg">
Feel free to try again, or reach out to support so we can assist you.
</p>
<div className="flex flex-row gap-4 items-center justify-center p-8">
<button className="btn btn-ghost" onClick={() => setResult(false)}>
<div className="tw-flex tw-flex-row tw-gap-4 tw-items-center tw-justify-center tw-p-8">
<button className="tw-daisy-btn tw-daisy-btn-ghost" onClick={() => setResult(false)}>
Back
</button>
<Link href="/support" className="btn btn-ghost">
<Link href="/support" className="tw-daisy-btn tw-daisy-btn-ghost">
Contact support
</Link>
</div>
@ -147,7 +150,7 @@ export const SignUp = () => {
)
) : (
<>
<p className="text-inherit">To receive a sign-up link, enter your email address</p>
<p className="tw-text-inherit">To receive a sign-up link, enter your email address</p>
<form onSubmit={signupHandler}>
<EmailInput
id="signup-email"
@ -161,7 +164,7 @@ export const SignUp = () => {
<IconButton
onClick={signupHandler}
btnProps={{ type: 'submit' }}
className="lg:w-full grow"
className="lg:tw-w-full tw-grow tw-mt-2"
>
<EmailIcon />
Email me a sign-up link
@ -169,7 +172,7 @@ export const SignUp = () => {
</form>
{showAll ? (
<>
<div className="grid grid-cols-1 md:grid-cols-2 gap-1 items-center">
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-1 tw-items-center tw-mt-1">
{['Google', 'GitHub'].map((provider) => (
<IconButton
key={provider}
@ -182,22 +185,22 @@ export const SignUp = () => {
</IconButton>
))}
</div>
<IconButton color="neutral" href="/signin" className="daisy-btn-lg">
<span className="hidden md:block">
<KeyIcon className="h-10 w-10" />
<IconButton color="neutral" href="/signin" className="tw-daisy-btn-lg tw-mt-1">
<span className="tw-hidden md:tw-block">
<KeyIcon className="tw-h-10 tw-w-10" />
</span>
Sign in here
</IconButton>
<div className="flex flex-row justify-center mt-2">
<div className="tw-flex tw-flex-row tw-justify-center tw-mt-2">
<IconButton color="ghost" onClick={() => setShowAll(false)}>
<DownIcon className="w-6 h-6 rotate-180" />
<DownIcon className="tw-w-6 tw-h-6 tw-rotate-180" />
Fewer options
<DownIcon className="w-6 h-6 rotate-180" />
<DownIcon className="tw-w-6 tw-h-6 tw-rotate-180" />
</IconButton>
</div>
</>
) : (
<div className="flex flex-row justify-center mt-2">
<div className="tw-flex tw-flex-row tw-justify-center tw-mt-2">
<IconButton color="ghost" onClick={() => setShowAll(true)}>
<DownIcon />
More options

View file

@ -54,6 +54,7 @@
"./components/Null": "./components/Null/index.mjs",
"./components/Number": "./components/Number/index.mjs",
"./components/Pattern": "./components/Pattern/index.mjs",
"./components/Patrons": "./components/Patrons/index.mjs",
"./components/Popout": "./components/Popout/index.mjs",
"./components/Role": "./components/Role/index.mjs",
"./components/SignIn": "./components/SignIn/index.mjs",

View file

@ -268,65 +268,41 @@ const config = {
{ to: '/showcase/', label: '📷 Showcase', position: 'left' },
{ to: '/blog/', label: '📰 Blog', position: 'left' },
{ to: '/new/', label: ' New...', position: 'right' },
{ to: '/account/', label: '📰 Account', position: 'right' },
{ to: '/account/', label: '🔒 Account', position: 'right' },
],
},
footer: {
style: 'light',
links: [
{
title: 'Docs',
title: 'Sections',
items: [
{ label: 'FreeSewing designs', to: '/docs/designs/' },
{ label: 'About FreeSewing', to: '/docs/about/' },
{ label: 'Measurements we use', to: '/docs/measurements/' },
{ label: 'Sewing terminology', to: '/docs/sewing/' },
{ label: 'FreeSewing Designs', to: '/designs/' },
{ label: 'FreeSewing Showcase', to: '/showcase/' },
{ label: 'FreeSewing Blog', to: '/blog/' },
{ label: 'FreeSewing Editor', to: '/editor/' },
],
},
{
title: 'Help & Support',
items: [
{
label: 'Discord',
href: 'https://discord.freesewing.org/',
},
{
label: 'GitHub Issues',
href: 'https://github.com/freesewing/freesewing/issues',
},
{
label: 'GitHub Discussions',
href: 'https://github.com/freesewing/freesewing/discussions',
},
{
label: 'All Support Options',
href: 'https://freesewing.org/support',
},
{ label: 'About FreeSewing', to: '/docs/about/' },
{ label: 'Getting Started', to: '/docs/about/guide/' },
{ label: 'Frequently Asked Questions', href: '/docs/about/faq/' },
{ label: 'Need Help?', href: '/support' },
],
},
{
title: 'More',
items: [
{
label: 'FreeSewing.org',
to: 'https://freesewing.org/',
},
{
label: 'Blog',
to: 'https://freesewing.org/blog/',
},
{
label: 'Showcase',
to: 'https://freesewing.org/showccase/',
},
{
label: 'Code on GitHub',
href: 'https://github.com/freesewing/freesewing',
},
{ label: 'FreeSewing.dev', to: 'https://freesewing.dev/' },
{ label: 'FreeSewing.social', to: 'https://freesewing.social/' },
{ label: 'Code on GitHub', to: 'https://github.com/freesewing/freesewing' },
{ label: 'FreeSewing Revenue Pledge 💜', href: '/docs/about/pledge/' },
],
},
],
copyright: `<a href="https://freesewing.org/">FreeSewing</a> is brought to you by <a href="https://github.com/joostdecock">Joost De Cock</a> and <a href="https://github.com/freesewing/freesewing/blob/develop/CONTRIBUTORS.md">contributors</a> with the financial support of <a href="https://freesewing.org/patrons/join">our patrons</a>`,
copyright: `<a href="https://freesewing.org/">FreeSewing</a> is brought to you by <a href="https://github.com/joostdecock">Joost De Cock</a> and <a href="https://github.com/freesewing/freesewing/blob/develop/CONTRIBUTORS.md">contributors</a> with the financial support of <a href="/patrons/join">our patrons</a>`,
},
prism: {
theme: prismThemes.dracula,

View file

@ -1,6 +1,7 @@
import fs from 'fs'
import { glob } from 'glob'
import matter from 'gray-matter'
import { orderBy } from '../../../packages/utils/src/index.mjs'
const loadExamplesTagsAndAuthors = async () => {
const lists = {
@ -12,6 +13,7 @@ const loadExamplesTagsAndAuthors = async () => {
const tags = []
const authors = []
const examples = {}
const recentBlogPosts = []
for (const type of Object.keys(lists)) {
for (const file of lists[type]) {
const content = await fs.readFileSync(file, 'utf-8')
@ -32,7 +34,12 @@ const loadExamplesTagsAndAuthors = async () => {
if (typeof examples[tag] === 'undefined') examples[tag] = []
examples[tag].push({ title: data.data.title, id: file.split('/')[1] })
}
}
} else if (type === 'blog')
recentBlogPosts.push({
title: data.data.title,
slug: file.split('/')[1],
date: new Date(data.data.date).getTime(),
})
}
}
@ -40,6 +47,7 @@ const loadExamplesTagsAndAuthors = async () => {
authors: [...new Set(authors.sort())], // Make them unique
tags: [...new Set(tags.sort())], // Make them unique
examples,
recentBlogPosts: orderBy(recentBlogPosts, 'date', 'desc').slice(0, 2),
}
}
@ -69,7 +77,7 @@ const loadUser = async (id) => {
async function prebuild() {
const all = {}
const { authors, examples, tags } = await loadExamplesTagsAndAuthors()
const { authors, examples, tags, recentBlogPosts } = await loadExamplesTagsAndAuthors()
for (const author of authors) {
const user = await loadUser(author)
if (user.profile.id) all[user.profile.id] = userAsAuthor(user)
@ -80,6 +88,10 @@ async function prebuild() {
`export const tags = ${JSON.stringify([...new Set(tags.sort())])}`
)
fs.writeFileSync(`./design-examples.mjs`, `export const examples = ${JSON.stringify(examples)}`)
fs.writeFileSync(
`./recent-blog-posts.mjs`,
`export const recentBlogPosts = ${JSON.stringify(recentBlogPosts, 0, 2)}`
)
}
prebuild()

View file

@ -1,84 +1,386 @@
// Dependencies
import { recentBlogPosts } from '@site/recent-blog-posts.mjs'
// Hooks
import { useState, useEffect } from 'react'
// Components
import Link from '@docusaurus/Link'
import { DocusaurusPage } from '@freesewing/react/components/Docusaurus'
import Layout from '@theme/Layout'
import MDXContent from '@theme/MDXContent'
import {
ChatIcon,
DesignIcon,
DocsIcon,
FreeSewingIcon,
HelpIcon,
NewsletterIcon,
NoIcon,
OkIcon,
ShowcaseIcon,
} from '@freesewing/react/components/Icon'
import { SignUp } from '@freesewing/react/components/SignUp'
import {
HortensiaFront,
HiFront,
TeaganFront,
AaronFront,
AlbertFront,
BruceBack,
BruceFront,
SimonBack,
SimonFront,
WahidBack,
WahidFront,
} from '@freesewing/react/components/LineDrawing'
import { BlogPostTeaser } from '@site/src/theme/BlogPostItems/index.js'
import { CardLink } from '@freesewing/react/components/Link'
import { PleaseSubscribe } from '@freesewing/react/components/Patrons'
const styles = {
top: {
margin: 'auto',
textAlign: 'center',
paddingTop: '2rem',
},
logo: {
maxWidth: '140px',
},
cards: {
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
maxWidth: '1600px',
margin: 'auto',
padding: '1rem',
gap: '1.5rem',
justifyContent: 'center',
marginBottom: '3rem',
},
card: {
width: '100%',
maxWidth: '600px',
boxShadow: '1px 1px 5px #0004',
borderRadius: '0.5rem',
padding: '1rem 1.5rem',
backgroundColor: 'var(--ifm-footer-background-color)',
},
cardheading: {
display: 'flex',
flexDirection: 'row',
width: '100%',
justifyContent: 'space-between',
alignItems: 'center',
},
cardicon: {
fontSize: '2rem',
},
cardp: {
fontSize: '1.15rem',
},
}
const Card = ({ title, icon, children, href }) => (
<a style={styles.card} href={href}>
<h3 style={styles.cardheading}>
<span>{title}</span>
<span style={styles.cardicon}>{icon}</span>
</h3>
const Card = ({ title, children, icon }) => (
<div className={`tw-px-8 tw-bg-primary/5 tw-py-10 tw-rounded-lg tw-block tw-shadow-lg tw-grow`}>
<h2 className="tw-mb-4 tw-text-inherit tw-flex tw-flex-row tw-gap-4 tw-justify-between tw-items-center tw-font-medium">
{title}
{icon}
</h2>
{children}
</a>
</div>
)
const meta = {
title: 'Free Bespoke Sewing Patterns',
description:
'FreeSewing is open source software to generate bespoke sewing ' +
'patterns, loved by home sewers and fashion entrepreneurs alike.',
}
export default function Home() {
return (
<Layout
title={`FreeSewing documentation for developers and contributors`}
description="FreeSewing is an open source Javascript library for parametric sewing patterns"
>
<MDXContent>
<div style={styles.top}>
<h1>Fixme: Build home page</h1>
<DocusaurusPage DocusaurusLayout={Layout} {...meta} Layout={false}>
<div className="tw-max-w-7xl tw-mx-auto tw-my-12 tw-px-4">
<div className="tw-text-center">
<FreeSewingIcon className="tw-w-48 tw-h-48 tw-mx-auto tw-pr-3" />
<h1 className="tw-font-black tw-text-5xl lg:tw-text-7xl tw-tracking-tighter tw-mb-0 tw-pb-0">
FreeSewing
</h1>
<h2 className="tw-text-xl lg:tw-text-3xl tw-font-medium tw-tracking-tighter tw-mt-0 tw-pt-0">
Free Bespoke Sewing Patterns
</h2>
</div>
<div style={styles.cards}>
<Card title="FreeSewing Designs" icon="🤓" href="/docs/designs/">
<p style={styles.cardp}>Documentation for all our designs.</p>
<div className="tw-flex tw-flex-col tw-gap-8 md:tw-grid md:tw-grid-cols-2 md:tw-gap-4 tw-mt-12 md:tw-mt-20 md:tw-px-4">
<Card
title="What is FreeSewing?"
icon={<OkIcon className="tw-w-12 tw-h-12 tw-text-success" stroke={4} />}
>
<p className="tw-font-medium tw-text-lg tw-mb-4">
FreeSewing is open source software to generate bespoke sewing patterns, loved by home
sewers and fashion entrepreneurs alike.
</p>
<p className="tw-font-medium tw-text-lg tw-mb-4">
Industry sizing is a bunch of lies. Join the slow fashion revolution and enjoy clothes
that fit you.
</p>
<p className="tw-font-medium tw-text-lg">
Speaking of revolution, we do not tolerate nazis here.
</p>
</Card>
<Card title="About FreeSewing" icon="👕" href="/docs/about/">
<p style={styles.cardp}>Documentation about FreeSewing.org and how to use it.</p>
</Card>
<Card title="Measurements we use" icon="🚀" href="/docs/measurements/">
<p style={styles.cardp}>Documentation for all the measurements we use.</p>
</Card>
<Card title="Sewing terminology" icon="🧑‍🤝‍🧑" href="/docs/sewing/">
<p style={styles.cardp}>Documentation for various terms that are used in sewing.</p>
<Card
title="What is FreeSewing not?"
icon={<NoIcon className="tw-w-12 tw-h-12 tw-text-error" stroke={3} />}
>
<p className="tw-font-medium tw-text-lg tw-mb-4">
FreeSewing is not a company. We do not sell anything. We do not have staff or
employees. We do not have an office. We do not get paid.
</p>
<p className="tw-font-medium tw-text-lg">
Our website does not contain any advertising. We do not track you. We do not sell your
personal data, or use it to train AI algorithms. We do not violate your privacy.
</p>
</Card>
</div>
</MDXContent>
</Layout>
<div className="tw-text-center tw-mt-20 md:tw-mt-20">
<HowDoesItWorkAnimation />
</div>
<div className="tw-p-1 tw--mx-4 tw-bg-primary tw-bg-opacity-10 tw-mt-12 tw-rounded-none md:tw-rounded-lg lg:tw-rounded-xl md:tw-shadow-lg md:tw-mx-4 tw-p-8 lg:tw-px-12 md:tw-py-0">
<div className="tw-flex tw-flex-col md:tw-gap-8 lg:tw-gap-12 md:tw-flex md:tw-flex-row tw-m-auto">
<div className="tw--mx-4 md:tw-mx-0 md:tw-pt-8 tw-pb-8 lg:tw-py-12 tw-grow tw-m-auto tw-max-w-prose">
<SignUp embed />
</div>
<div className="tw--mx-4 md:tw-mx-0 md:tw-mt-0 tw-pt-0 md:tw-pt-8 tw-pb-8 lg:tw-py-12 tw-max-w-prose tw-m-auto tw-m-auto">
<h2 className="tw-text-inherit tw-mb-4 tw-hidden md:tw-block">Reasons to join</h2>
<ul>
{[0, 1, 2, 3].map((i) => (
<li className="tw-flex tw-flex-row tw-gap-2 tw-my-2" key={i}>
<OkIcon stroke={4} /> {reasonsToJoin[i]}
</li>
))}
</ul>
</div>
</div>
</div>
<div className="tw-grid tw-grid-cols-1 tw-gap-2 lg:tw-grid-cols-2 tw-max-w-7xl tw-my-16">
{recentBlogPosts.map((post) => (
<BlogPostTeaser
key={post.slug}
post={{
content: {
metadata: {
permalink: `/blog/${post.slug}`,
title: post.title,
},
},
}}
/>
))}
</div>
<div className="tw-flex tw-flex-col md:tw-grid md:tw-grid-cols-2 tw-gap-4 tw-max-w-7xl tw-m-auto tw-mb-24">
<CardLink
Link={Link}
href="/designs"
title="Designs"
icon={<DesignIcon className="tw-w-12 tw-h-12 tw-shrink-0" />}
>
<p className="tw-font-medium tw-text-inherit tw-italic tw-text-lg">
Browse our collection of designs, and turn them into sewing patterns that are
made-to-measure just for you.
</p>
</CardLink>
<CardLink
Link={Link}
href="/showcase"
title="Showcase"
icon={<ShowcaseIcon className="tw-w-12 tw-h-12 tw-shrink-0" />}
>
<p className="tw-font-medium tw-text-inherit tw-italic tw-text-lg">
Get inspiration from the FreeSewing community, and see how others have applied their
creativity to our designs.
</p>
</CardLink>
<CardLink
Link={Link}
href="/docs/about/guide"
title="Getting Started"
icon={<DocsIcon className="tw-w-12 tw-h-12 tw-shrink-0" />}
>
<p className="tw-font-medium tw-text-inherit tw-italic tw-text-lg">
FreeSewing.org is unlike any sewing pattern website you know. Read this short guide to
get the most our of our platform.
</p>
</CardLink>
<CardLink
Link={Link}
href="/docs/about/faq"
title="Frequently Asked Questions"
icon={<HelpIcon className="tw-w-12 tw-h-12 tw-shrink-0" />}
>
<p className="tw-font-medium tw-text-inherit tw-italic tw-text-lg">
Some of the questions that come up often when people discover our platform are
answered here.
</p>
</CardLink>
</div>
<div className="lg:px-4 max-w-7xl mx-auto">
<PleaseSubscribe />
</div>
<div className="tw-flex tw-flex-col md:tw-grid md:tw-grid-cols-2 tw-gap-4 tw-max-w-7xl tw-m-auto tw-mb-24">
<CardLink
href="/newsletter"
title="FreeSewing Newsletter"
icon={<NewsletterIcon className="tw-w-12 tw-h-12 tw-shrink-0" />}
>
<p className="tw-font-medium tw-text-inherit tw-italic tw-text-lg">
Subscribe to our newsletter and once every 3 months you'll receive an email from us
with honest wholesome content. No tracking, no ads, no nonsense.
</p>
</CardLink>
<CardLink
href="/support"
title="Need Help?"
icon={<ChatIcon className="tw-w-12 tw-h-12 tw-shrink-0" />}
>
<p className="tw-font-medium tw-text-inherit tw-italic tw-text-lg">
While we are all volunteers, we have a good track record of helping people. So don't
be shy to reach out.
</p>
</CardLink>
</div>
</div>
</DocusaurusPage>
)
}
const HowDoesItWorkAnimation = () => {
const [step, setStep] = useState(0)
const [halfStep, setHalfStep] = useState(0)
useEffect(() => {
setTimeout(() => {
if (step > 6) setStep(0)
else setStep(step + 1)
if (halfStep > 7) setHalfStep(0)
else setHalfStep(halfStep + 0.5)
}, 800)
}, [step])
return (
<div className="tw-flex tw-flex-col md:tw-grid md:tw-grid-cols-3 tw-my-12">
<div className="tw-relative tw-w-full">
<div className="tw-relative tw-h-72 md:tw-h-96 tw-overflow-hidden">
{slides.map((i) => (
<div
key={i}
className={`tw-duration-700 tw-ease-in-out tw-transition-all ${
step === i ? 'tw-opacity-1' : 'tw-opacity-0'
} tw-absolute tw-top-0 tw-text-center tw-w-full`}
>
<div className="tw-w-full tw-flex tw-flex-row tw-items-center tw-h-72 md:tw-h-96 tw-w-full tw-justify-center">
{lineDrawings[i]}
</div>
</div>
))}
</div>
<Nr nr={1} />
<Title txt="Pick Any Design" />
</div>
<div className="tw-relative tw-w-full">
<div className="tw-relative tw-h-72 md:tw-h-96 tw-overflow-hidden">
{slides.map((i) => (
<div
key={i}
className={`tw-duration-700 tw-ease-in-out tw-transition-all ${
Math.floor(halfStep) === i ? 'tw-opacity-1' : 'tw-opacity-0'
} tw-absolute tw-top-0 tw-text-center tw-w-full`}
>
<div className="tw-w-full tw-flex tw-flex-row tw-items-center tw-h-72 md:tw-h-96 tw-w-full tw-justify-center">
<img
src={`/img/models/model-${i}.png`}
className="tw-h-72 md:tw-h-96 tw-shrink-0 tw-px-8"
/>
</div>
</div>
))}
<Nr nr={2} />
<Title txt="Add a set of measurements" />
</div>
</div>
<div className="tw-relative tw-w-full">
<div className="tw-relative tw-h-96 tw-overflow-hidden">
<div className="tw-w-full tw-flex tw-flex-row tw-items-center tw-h-72 md:tw-h-96 tw-w-full tw-justify-center">
<Pattern key={step} i={step} />
</div>
<Nr nr={3} />
<Title txt="Customize your pattern" />
</div>
</div>
</div>
)
}
const reasonsToJoin = [
'Generate bespoke sewing patterns.',
'Store your patterns & measurements sets.',
'Share your creations with the community.',
'Open source. No ads. No nonsense.',
]
const lineDrawings = [
<AaronFront key={1} className="tw-h-72 md:tw-h-96" />,
<HiFront key={2} className="tw-h-72 md:tw-h-96" />,
<TeaganFront key={3} className="tw-h-72 md:tw-h-96" />,
<WahidFront key={4} className="tw-h-72 md:tw-h-96" />,
<AlbertFront key={5} className="tw-h-72 md:tw-h-96" />,
<BruceFront key={6} className="tw-h-72 md:tw-h-96" />,
<SimonFront key={7} className="tw-h-72 md:tw-h-96" />,
<HortensiaFront key={8} className="tw-h-72 md:tw-h-96" />,
]
const patternTweaks = [
<path
key={1}
d="M 0,121.4 L 0,705.1 L 253.46,705.1 C 253.46,474.02 281.12,307.05 281.12,307.05 C 187.15,307.05 128.12,163.24 163.07,19.43 L 119.46,8.83 C 92.11,121.4 92.11,121.4 0,121.4 z"
/>,
<path
key={2}
d="M 0,121.4 L 0,705.1 L 253.46,705.1 C 253.46,481 279.96,321 279.96,321 C 184.87,321 126.42,170.22 163.07,19.43 L 119.46,8.83 C 92.11,121.4 92.11,121.4 0,121.4 z"
/>,
<path
key={3}
d="M 0,121.4 L 0,705.1 L 253.46,705.1 C 253.46,481 273.47,321 273.47,321 C 181.62,321 126.42,170.22 163.07,19.43 L 119.46,8.83 C 92.11,121.4 92.11,121.4 0,121.4 z"
/>,
<path
key={4}
d="M 0,121.4 L 0,742.92 L 253.46,742.92 C 253.46,481 273.47,321 273.47,321 C 181.62,321 126.42,170.22 163.07,19.43 L 119.46,8.83 C 92.11,121.4 92.11,121.4 0,121.4 z"
/>,
<path
key={5}
d="M 0,121.4 L 0,742.92 L 253.46,742.92 C 253.46,481 273.47,321 273.47,321 C 181.62,321 126.42,170.22 163.07,19.43 L 119.46,8.83 C 95.69,106.65 80.04,121.4 0,121.4 z"
/>,
<path
key={6}
d="M 0,152.02 L 0,742.92 L 253.46,742.92 C 253.46,481 273.47,321 273.47,321 C 181.62,321 126.42,170.22 163.07,19.43 L 119.46,8.83 C 89.22,133.26 73.57,152.02 0,152.02 z"
/>,
<path
key={7}
d="M 0,152.02 L 0,742.92 L 253.46,742.92 C 253.46,481 273.47,321 273.47,321 C 183.55,321 130.16,170.66 166.7,20.31 L 123.1,9.71 C 93.04,133.38 76.92,152.02 0,152.02 z"
/>,
<path
key={8}
d="M 0,152.02 L 0,742.92 L 253.46,742.92 C 253.46,481 273.47,321 273.47,321 C 181.55,321 126.27,170.2 162.92,19.39 L 126.88,10.63 C 97.02,133.5 80.4,152.02 0,152.02 z"
/>,
]
const Pattern = ({ i }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="-300 -20 850 850"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
className="tw-fill-primary tw-h-72 md:tw-h-96"
strokeWidth="4"
fillOpacity="0.25"
>
{patternTweaks[i]}
</svg>
)
const Nr = ({ nr }) => (
<div className="tw-absolute tw-top-8 tw-w-full tw--ml-20">
<span className="tw-bg-primary tw-text-primary-content tw-font-bold tw-rounded-full tw-w-12 tw-h-12 tw-flex tw-items-center tw-justify-center tw-align-center tw-m-auto tw-text-3xl">
{nr}
</span>
</div>
)
const Title = ({ txt }) => {
const shadow = `var(--ifm-background-color)`
return (
<div className="tw-absolute tw-top-28 tw-left-0 tw-w-full">
<h3
className="tw-text-2xl tw--rotate-12 tw-w-48 tw-text-center tw-m-auto"
style={{
textShadow: `1px 1px 1px ${shadow}, -1px -1px 1px ${shadow}, -1px 1px 1px ${shadow}, 1px -1px 1px ${shadow}`,
}}
>
{txt}
</h3>
</div>
)
}
const slides = [0, 1, 2, 3, 4, 5, 6, 7]
const RecentBlogPosts = () => (
<div>
{recentBlogPosts.map((post) => (
<p key={post.slug}>{post.title}</p>
))}
</div>
)

View file

@ -0,0 +1,24 @@
// Components
import Layout from '@theme/Layout'
import { DocusaurusPage } from '@freesewing/react/components/Docusaurus'
import { PleaseSubscribe } from '@freesewing/react/components/Patrons'
const meta = {
title: 'Join the FreeSewing Patrons',
description:
'If you think FreeSewing is worthwhile, and if you can spare ' +
'a few coins each month without hardship, please support our work.',
}
export default function PatronsPage() {
return (
<DocusaurusPage DocusaurusLayout={Layout} {...meta} Layout={false}>
<div className="tw-max-w-7xl tw-mx-auto tw-my-12 tw-px-4">
<h1>Join the FreeSewing Patrons</h1>
<div className="tw--mx-4">
<PleaseSubscribe />
</div>
</div>
</DocusaurusPage>
)
}

View file

@ -0,0 +1,24 @@
// Components
import Layout from '@theme/Layout'
import { DocusaurusPage } from '@freesewing/react/components/Docusaurus'
import { PleaseSubscribe } from '@freesewing/react/components/Patrons'
const meta = {
title: 'Join the FreeSewing Patrons',
description:
'If you think FreeSewing is worthwhile, and if you can spare ' +
'a few coins each month without hardship, please support our work.',
}
export default function PatronsPage() {
return (
<DocusaurusPage DocusaurusLayout={Layout} {...meta} Layout={false}>
<div className="tw-max-w-7xl tw-mx-auto tw-my-12 tw-px-4">
<h1>Join the FreeSewing Patrons</h1>
<div className="tw--mx-4">
<PleaseSubscribe />
</div>
</div>
</DocusaurusPage>
)
}

View file

@ -38,7 +38,7 @@ const BlogPostHeader = ({ type }) => {
]}
/>
<h1>
<span className="block text-sm capitalize">{type}:</span>
<span className="tw-block tw-text-sm tw-capitalize">{type}:</span>
{metadata.title}
</h1>
<BlogPostItemHeaderInfo />

View file

@ -13,9 +13,9 @@ const textShadow = {
const teaserClasses = `tw-absolute tw-bottom-4 tw-right-0 tw-ml-3
tw-rounded-l md:tw-rounded-l-lg tw-bg-neutral tw-bg-opacity-80 tw-p-1 tw-px-4 tw-font-medium
tw-text-neutral-content tw-text-right tw-text-sm md:tw-text-lg`
tw-text-neutral-content tw-text-right tw-text-sm md:tw-text-lg lg:tw-text-xl`
const BlogPostTeaser = ({ post }) => (
export const BlogPostTeaser = ({ post }) => (
<Link
className="tw-aspect-video tw-relative tw-shadow tw-rounded-lg"
href={post.content.metadata.permalink}

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB