Redo homepage to @franknoirot 's new designs

Not finished but enough for a mvp
designs; https://www.figma.com/file/VUh53RdncjZ7NuFYj0RGB9/CadHub?node-id=1652%3A4224
This commit is contained in:
Kurt Hutten
2021-09-10 18:26:35 +10:00
parent 12ab456446
commit b8fa22eede
15 changed files with 42187 additions and 78 deletions

View File

@@ -34,6 +34,7 @@ module.exports = {
450: '#671BC6',
500: '#8732F2',
600: '#A663FA',
200: '#C99DFF',
},
'ch-purple-gray': {
200: '#DBDBEC',
@@ -41,8 +42,11 @@ module.exports = {
'ch-blue': {
700: '#08466F',
650: '#0958BA',
500: '5098F1',
640: '#0A57B5',
630: '#3285EB',
500: '#5098F1',
400: '#79B2F8',
300: '#9BC8FF',
},
'ch-pink': {
800: '#93064F',

41442
app/web/public/coffee-lid.stl Normal file

File diff suppressed because it is too large Load Diff

BIN
app/web/public/hinge.stl Normal file

Binary file not shown.

View File

@@ -35,6 +35,7 @@ const Routes = () => {
)
return (
<Router>
<Route path="/projects" page={ProjectsPage} name="projects" />
<Route path="/dev-ide/{cadPackage}" page={DevIdePage} name="devIde" />
<Route path="/policies/privacy-policy" page={PrivacyPolicyPage} name="privacyPolicy" />
<Route path="/policies/code-of-conduct" page={CodeOfConductPage} name="codeOfConduct" />
@@ -59,7 +60,7 @@ const Routes = () => {
<Private unauthenticated="home" role="admin">
<Route path="/admin/users" page={UsersPage} name="users" />
<Route path="/admin/projects" page={AdminProjectsPage} name="projects" />
<Route path="/admin/projects" page={AdminProjectsPage} name="adminProjects" />
<Route path="/admin/subject-access-requests/{id}/edit" page={EditSubjectAccessRequestPage} name="editSubjectAccessRequest" />
<Route path="/admin/subject-access-requests/{id}" page={SubjectAccessRequestPage} name="subjectAccessRequest" />
<Route path="/admin/subject-access-requests" page={SubjectAccessRequestsPage} name="subjectAccessRequests" />

View File

@@ -1,8 +1,9 @@
export type CadPackageType = 'openscad' | 'cadquery' | 'jscad'
export const ideTypeNameMap = {
export const ideTypeNameMap: { [key in CadPackageType]: string } = {
openscad: 'OpenSCAD',
cadquery: 'CadQuery',
jscad: 'JSCAD',
}
interface CadPackageProps {
@@ -19,18 +20,21 @@ const CadPackage = ({
const cadName = ideTypeNameMap[cadPackage] || ''
const isOpenScad = cadPackage === 'openscad'
const isCadQuery = cadPackage === 'cadquery'
const isJsCad = cadPackage === 'jscad'
return (
<div
className={
`grid grid-flow-col-dense items-center gap-2 cursor-default text-gray-100 ${
`grid grid-flow-col-dense items-center gap-2 text-gray-100 ${
isOpenScad && 'bg-yellow-800'
} ${isCadQuery && 'bg-ch-blue-700'} bg-opacity-30 ` + className
} ${isCadQuery && 'bg-ch-blue-700'} ${
isJsCad && 'bg-ch-purple-500'
} bg-opacity-30 ` + className
}
>
<div
className={`${isOpenScad && 'bg-yellow-200'} ${
isCadQuery && 'bg-blue-800'
} ${dotClass} rounded-full`}
} ${isJsCad && 'bg-yellow-300'} ${dotClass} rounded-full`}
/>
<div>{cadName}</div>
</div>

View File

@@ -0,0 +1,121 @@
import React, { useRef, useMemo } from 'react'
import * as THREE from 'three'
import { useLoader, useThree, useFrame } from '@react-three/fiber'
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader'
import { useEdgeSplit } from 'src/helpers/hooks/useEdgeSplit'
import texture from 'src/components/IdeViewer/dullFrontLitMetal.png'
import {
useTexture,
Environment,
MeshDistortMaterial,
Sphere,
} from '@react-three/drei'
const thresholdAngle = 10
export default function AssetWithGooey({
assetUrl,
offset,
preset,
scale,
}: {
assetUrl: string
offset: number[]
preset?: string
scale: number
}) {
const geo = useLoader(STLLoader, assetUrl)
const edgeRef = useRef(null)
const coffeeRef = useRef(null)
const mesh = useEdgeSplit((thresholdAngle * Math.PI) / 180, true, geo)
const colorMap = useTexture(texture)
const edges = React.useMemo(() => new THREE.EdgesGeometry(geo, 12), [geo])
const position = [offset[0], offset[1], 5]
const scaleArr = Array.from({ length: 3 }).map(() => scale)
const { mouse } = useThree()
useFrame((state, delta) => {
if (edgeRef.current) {
edgeRef.current.rotation.y += 0.01
coffeeRef.current.rotation.x = (-mouse.y * Math.PI) / 6
coffeeRef.current.rotation.y = (mouse.x * Math.PI) / 6
}
})
return (
<group dispose={null} ref={edgeRef} position={position}>
<group ref={coffeeRef}>
<Environment preset={preset || 'warehouse'} />
<mesh ref={mesh} scale={scaleArr} geometry={geo}>
<meshPhysicalMaterial
envMapIntensity={2}
color="#F472B6"
map={colorMap}
clearcoat={0.2}
clearcoatRoughness={0.01}
roughness={1}
metalness={0.9}
smoothShading
/>
</mesh>
<lineSegments scale={scale} geometry={edges} renderOrder={100}>
<lineBasicMaterial color="#aaaaff" />
</lineSegments>
</group>
<pointLight
position={[-1000, -1000, 1000]}
color="#5555FF"
intensity={1}
/>
<ambientLight intensity={0.3} />
<Gooey />
</group>
)
}
function randomSign(num: number): number {
return Math.random() > 0.5 ? num : -num
}
function Gooey() {
const blobsData = useMemo(() => {
const firstSet = Array.from({ length: 10 }).map((_, index) => {
const dist = Math.random() * 3 + 2.5
const x = randomSign(Math.random() * dist)
const y = randomSign(Math.sqrt(dist * dist - x * x))
const z = randomSign(Math.random() * 3)
const position: [number, number, number] = [x, z, y]
const size = Math.random() * 0.8 + 0.1
const distort = Math.random() * 0.8 + 0.1
const speed = (Math.random() * 0.8) / size / size + 0.1
return { position, size, distort, speed }
})
const secondSet = Array.from({ length: 10 }).map((_, index) => {
const dist = Math.random() * 3 + 1.5
const x = randomSign(Math.random() * dist)
const y = randomSign(Math.sqrt(dist * dist - x * x))
const z = randomSign(Math.random() * 3)
const position: [number, number, number] = [x, z, y]
const size = Math.random() * 0.2 + 0.05
const distort = Math.random() * 0.8 + 0.1
const speed = (Math.random() * 0.5) / size / size + 0.1
return { position, size, distort, speed }
})
return [...firstSet, ...secondSet]
}, [])
return (
<>
{blobsData.map(({ position, size, distort, speed }, index) => (
<Sphere key={index} visible position={position} args={[size, 16, 200]}>
<MeshDistortMaterial
color="#5098F1"
attach="material"
distort={distort} // Strength, 0 disables the effect (default=1)
speed={speed} // Speed (default=1)
roughness={0}
opacity={0.6}
transparent
/>
</Sphere>
))}
</>
)
}

View File

@@ -0,0 +1,481 @@
import { Canvas, useLoader, useFrame } from '@react-three/fiber'
import { Suspense } from 'react'
import { Html } from '@react-three/drei'
import CadPackage, {
CadPackageType,
} from 'src/components/CadPackage/CadPackage'
import { navigate, routes } from '@redwoodjs/router'
import Svg, { SvgNames } from 'src/components/Svg/Svg'
import Gravatar from 'src/components/Gravatar/Gravatar'
import ProjectsCell from 'src/components/ProjectsCell'
import OutBound from 'src/components/OutBound/OutBound'
// dynamic import to enable pre-render iof the homepage
const Coffee = React.lazy(() => import('src/components/Hero/AssetWithGooey'))
export const Hero = () => {
const [width, widthSetter] = React.useState(1024)
React.useEffect(() => {
const onResize = () => {
widthSetter(window.innerWidth)
}
window.addEventListener('resize', onResize)
onResize()
return () => {
window.removeEventListener('resize', onResize)
}
}, [])
const { heroOffset, tutOffset } = React.useMemo(() => {
if (width < 1024) {
return {
heroOffset: [0, -3],
tutOffset: [0, -3],
}
}
return {
heroOffset: [-5, 0],
tutOffset: [4, 0],
}
}, [width])
return (
<div className="bg-ch-gray-800">
<ModelSection assetUrl="/coffee-lid.stl" offset={heroOffset} scale={0.06}>
<div className="grid lg:grid-cols-2 py-32">
<div className="flex items-end justify-center row-start-2 lg:row-start-1 pt-96 lg:pt-0 pr-12 pl-6">
<div className="grid grid-flow-col gap-4 items-center bg-ch-gray-760 bg-opacity-95 text-ch-gray-300 rounded-md p-2 font-fira-sans relative z-10 shadow-ch">
<div className="pl-4">
<Gravatar
image="CadHub/xvrnxvarkv8tdzo4n65u"
className="w-12 h-12 mr-4"
size={60}
/>
</div>
<div>
<div className="text-3xl">Coffee Lid</div>
<div>IrevDev</div>
</div>
<div className="flex self-start">
<CadPackage
cadPackage="cadquery"
className="px-3 py-1 text-xl rounded transform translate-x-10"
/>
</div>
</div>
</div>
<div className="col-start-1 lg:col-start-2 px-4">
<div>
<span
className="text-7xl text-ch-blue-400 bg-ch-blue-640 bg-opacity-30 font-fira-code px-6 rounded-2xl shadow-ch"
style={{
boxShadow: 'inset 0 4px 4px 0 rgba(255,255,255, 0.06)',
}}
>
Code
</span>
</div>
<div className="text-6xl font-fira-sans mt-8 text-ch-gray-300">
is the future of CAD
</div>
<div className="text-2xl text-gray-600 mt-8 max-w-4xl">
Designs backed by reliable, easy-to-write code open a world of new
workflows and collaboration. We're building a place where you can
build that future.
</div>
<OutlineButton
color="pink"
isLeft
svgName="terminal"
onClick={() =>
navigate(routes.draftProject({ cadPackage: 'openscad' }))
}
>
Start Hacking
</OutlineButton>
</div>
</div>
</ModelSection>
<ChooseYourCharacter />
<Community />
<ModelSection
assetUrl="/hinge.stl"
offset={tutOffset}
scale={0.12}
preset="lobby"
>
<div className="max-w-7xl mx-auto grid py-16 overflow-hidden">
<div className="py-0 pb-32 lg:py-32 ml-4 col-start-1 lg:col-start-1 pr-12 pl-6">
<div className="text-4xl mb-6 text-ch-gray-300">Learn Code-CAD</div>
<p className="text-gray-600 max-w-lg">
We want you to learn Code-CAD today so it can change the way you
work tomorrow. Our community is writing tutorials to make this
powerful paradigm more accessible to people new to code and CAD.
</p>
<OutBound
to="https://learn.cadhub.xyz/docs/definitive-beginners/your-openscad-journey"
className=""
>
<OutlineButton color="pink" isLeft svgName="terminal">
Get Started with OpenSCAD
</OutlineButton>
</OutBound>
</div>
<div className="flex items-end justify-center row-start-2 lg:row-start-1 lg:col-start-2 pt-96 lg:pt-0 lg:pr-10">
<div className="grid grid-flow-col gap-2 items-center bg-ch-gray-760 bg-opacity-95 text-ch-gray-300 rounded-md p-2 font-fira-sans relative z-10 shadow-ch">
<div className="pl-4">
<Gravatar
image="CadHub/xvrnxvarkv8tdzo4n65u"
className="w-12 h-12 mr-4"
size={60}
/>
</div>
<div>
<div className="text-2xl">Print in Place Hinge</div>
<div>IrevDev</div>
</div>
<div className="flex self-start">
<CadPackage
cadPackage="openscad"
className="px-3 py-1 text-xl rounded transform translate-x-10"
/>
</div>
</div>
</div>
</div>
</ModelSection>
<Roadmap />
<div className="h-3 bg-gradient-to-r from-blue-500 via-purple-500 to-pink-500" />
<Footer />
</div>
)
}
function ModelSection({
assetUrl,
offset,
children,
preset,
scale,
}: {
assetUrl: string
offset: number[]
children: React.ReactNode
preset?: string
scale: number
}) {
return (
<div className="relative">
{children}
<div className="absolute inset-0">
<Canvas
linear
dpr={[1, 2]}
orthographic
camera={{ zoom: 75, position: [0, 0, 500] }}
>
<Suspense
fallback={<Html center className="loading" children="Loading..." />}
>
<Coffee
assetUrl={assetUrl}
offset={offset}
preset={preset}
scale={scale}
/>
</Suspense>
</Canvas>
</div>
</div>
)
}
function ChooseYourCharacter() {
return (
<div className="text-ch-gray-300 grid lg:grid-cols-2 gap-12 font-fira-sans py-32 max-w-7xl mx-auto px-4">
<div className="">
<div className="text-4xl mb-6">Choose your character</div>
<p className="text-gray-600 text-2xl">
CadHub is the place you can try out Code-CAD packages to find the one
that's right for you. Our dedicated community is making CAD easy to
learn on the web. Try one of our three integrations today and keep an
eye out for more.
</p>
</div>
<ul className="flex-col flex justify-around items-center lg:items-start text-gray-600">
{[
{
cadPackage: 'openscad',
desc: 'A mature Code-CAD library focused on Constructed Solid Geometry (CSG) modeling with syntax like C++.',
},
{
cadPackage: 'cadquery',
desc: 'A Python-based library with support for CSG and sketch-based modeling and a clean-feeling API.',
},
{
cadPackage: 'jscad',
desc: 'A JavaScript Code-CAD library that will feel familiar to web developers, based on the same tech as OpenSCAD.',
},
].map(
({
cadPackage,
desc,
}: {
cadPackage: CadPackageType
desc: string
}) => (
<li key={cadPackage} className="flex items-center">
<div className="mr-12">
<button
onClick={() => navigate(routes.draftProject({ cadPackage }))}
className="flex-shrink-0 cursor-pointer"
>
<CadPackage
cadPackage={cadPackage}
className="px-3 py-1 w-40 text-xl rounded"
/>
</button>
</div>
<p className="text-sm my-2 max-w-sm">{desc}</p>
</li>
)
)}
</ul>
</div>
)
}
function Community() {
return (
<div className="max-w-7xl mx-auto py-40">
<div className="text-ch-gray-300 grid lg:grid-cols-2 gap-8 font-fira-sans px-4 mb-6">
<div className="text-4xl">Explore with our community</div>
<p className="text-gray-600 text-sm">
CadHub is a social platform. You can ask users how they designed a
part, fork their work to put your own spin on it, and find inspiration
in abundance.
</p>
</div>
<ProjectsCell shouldFilterProjectsWithoutImage projectLimit={8} />
<div className="flex justify-end pr-4">
<OutlineButton
color="blue"
svgName="arrow-right"
onClick={() => navigate(routes.projects())}
>
See All Projects
</OutlineButton>
</div>
</div>
)
}
function OutlineButton({
color,
svgName,
isLeft = false,
children,
onClick,
}: {
color: 'blue' | 'pink' | 'purple'
svgName: SvgNames
isLeft?: boolean
children: React.ReactNode
onClick?: () => void
}) {
return (
<button
onClick={onClick}
className={`grid grid-flow-col-dense gap-4 items-center border px-4 py-1 rounded mt-6 relative z-10 ${
color === 'pink' && 'border-ch-pink-500'
} ${color === 'blue' && 'border-ch-blue-630'} ${
color === 'purple' && 'border-ch-purple-500'
}`}
>
{isLeft && (
<Svg
name={svgName}
className={`${color === 'pink' && 'text-ch-pink-500'} ${
color === 'blue' && 'text-ch-blue-300'
} ${color === 'purple' && 'text-ch-purple-200'} w-6 h-6`}
/>
)}
<span
className={`text-2xl ${color === 'pink' && 'text-ch-pink-300'} ${
color === 'blue' && 'text-ch-blue-300'
} ${color === 'purple' && 'text-ch-purple-200'}`}
>
{children}
</span>
{!isLeft && (
<Svg
name={svgName}
className={`${color === 'pink' && 'text-ch-pink-500'} ${
color === 'blue' && 'text-ch-blue-300'
} ${color === 'purple' && 'text-ch-purple-200'} w-6 h-6`}
/>
)}
</button>
)
}
function Roadmap() {
const sections = [
{
title: 'Read our roadmap',
desc: 'Version control with GitHub, multi-file projects, and team collaboration tools. Weve got a lot planned, and were building it in the open.',
buttonText: 'View on Github',
color: 'purple',
url: 'https://github.com/Irev-Dev/cadhub/discussions/212',
},
{
title: 'Join our community',
desc: 'CAD is ready to evolve. Join our Discord and opensource community on GitHub and build that future with us!',
buttonText: 'Join the Discord',
color: 'blue',
url: 'https://discord.gg/SD7zFRNjGH',
},
]
return (
<div className="max-w-7xl mx-auto grid md:grid-cols-2 py-32 mt-12">
{sections.map(({ title, desc, buttonText, color, url }) => (
<div className="ml-4 py-6" key={title}>
<div className="text-4xl mb-6 text-ch-gray-300">{title}</div>
<p className="text-gray-600 text-2xl max-w-lg">{desc}</p>
<OutBound to={url} className="">
<OutlineButton color={color} svgName="arrow-right">
{buttonText}
</OutlineButton>
</OutBound>
</div>
))}
</div>
)
}
function Footer() {
const section: {
header: string
links: { name: string; url: string }[]
}[] = [
{
header: 'Community',
links: [
{
name: 'Github',
url: 'https://github.com/Irev-Dev/cadhub',
},
{
name: 'Discord',
url: 'https://discord.gg/SD7zFRNjGH',
},
{
name: 'Newsletter',
url: 'https://kurthutten.com/signup/',
},
],
},
{
header: 'About',
links: [
{
name: 'Road Map',
url: 'https://github.com/Irev-Dev/cadhub/discussions/212',
},
{
name: 'Code of Conduct',
url: '/policies/code-of-conduct',
},
{
name: 'Privacy Policy',
url: '/policies/privacy-policy',
},
],
},
{
header: 'Learn',
links: [
{
name: 'Documentation',
url: 'https://learn.cadhub.xyz/',
},
{
name: 'Blog',
url: 'https://learn.cadhub.xyz/blog',
},
],
},
{
header: 'Integrations',
links: [
{
name: 'OpenSCAD',
url: 'https://openscad.org/',
},
{
name: 'CadQuery',
url: 'https://cadquery.readthedocs.io/en/latest/',
},
{
name: 'JSCAD',
url: 'https://github.com/jscad',
},
],
},
]
return (
<div className="max-w-7xl mx-auto py-16 px-4 grid">
<div className="pl-20 lg:pl-0">
<div className="flex items-center">
<div className="rounded-full overflow-hidden">
<Svg className="w-10 md:w-16" name="favicon" />
</div>
<div className="ml-2 md:ml-8 flex">
{/* Because of how specific these styles are to this heading/logo and it doesn't need to be replicated else where as well as it's very precise with the placement of "pre-alpha" I think it's appropriate. */}
<h2
className="text-indigo-300 text-2xl md:text-5xl font-ropa-sans py-1 md:tracking-wider"
style={{ letterSpacing: '0.3em' }}
>
CadHub
</h2>
<div
className="text-pink-400 text-sm font-bold font-ropa-sans hidden md:block"
style={{ paddingBottom: '2rem', marginLeft: '-1.8rem' }}
>
pre-alpha
</div>
</div>
</div>
<p className="text-gray-600 text-xl mt-12 max-w-xs">
Built by{' '}
<OutBound
to="https://github.com/Irev-Dev/cadhub/graphs/contributors"
className="font-bold"
>
16 contributors
</OutBound>{' '}
from around the world.
</p>
</div>
<div className="grid grid-cols-4 gap-4 flex-grow pl-20 row-start-2 lg:col-start-2 lg:row-start-1 mt-20 lg:mt-0">
{section.map(({ header, links }) => (
<ul className="text-ch-gray-300 font-fira-sans" key={header}>
<li className="text-xl font-bold">{header}</li>
{links.map(({ name, url }) => (
<li className="text-lg mt-6 font-light" key={url}>
<a href={url}>{name}</a>
</li>
))}
</ul>
))}
</div>
</div>
)
}

View File

@@ -5,9 +5,8 @@ import ReactGA from 'react-ga'
import Popover from '@material-ui/core/Popover'
import useUser from 'src/helpers/hooks/useUser'
import ImageUploader from 'src/components/ImageUploader'
import LoginModal from 'src/components/LoginModal'
import Gravatar from 'src/components//Gravatar/Gravatar'
import Gravatar from 'src/components/Gravatar/Gravatar'
const ProfileSlashLogin = () => {
const { logOut, isAuthenticated, currentUser, client } = useAuth()

View File

@@ -0,0 +1,59 @@
import { Link, routes } from '@redwoodjs/router'
import Svg from 'src/components/Svg/Svg'
import CadPackage from 'src/components/CadPackage/CadPackage'
import { countEmotes } from 'src/helpers/emote'
import ImageUploader from 'src/components/ImageUploader'
const ProjectCard = ({ title, mainImage, user, Reaction, cadPackage }) => (
<li
className="rounded p-1.5 bg-ch-gray-760 shadow-ch"
key={`${user?.userName}--${title}`}
>
<Link
to={routes.project({
userName: user?.userName,
projectTitle: title,
})}
>
<div className="relative">
<ImageUploader
className="rounded"
aspectRatio={1.4}
imageUrl={mainImage}
width={700}
/>
<CadPackage
cadPackage={cadPackage}
className="absolute right-0 top-0 p-1.5 rounded-bl text-sm bg-opacity-50"
dotClass="w-3 h-3"
/>
</div>
<div className="flex items-center mt-1">
<div className="w-8 h-8 overflow-hidden rounded-full border border-ch-gray-300 shadow">
<ImageUploader
className=""
aspectRatio={1}
imageUrl={user?.image}
width={50}
/>
</div>
<div className="ml-3 text-lg text-ch-gray-300 font-fira-sans">
<div className="">{title}</div>
<div className="text-sm">{user?.userName}</div>
</div>
</div>
<div className="grid grid-flow-col-dense gap-2 justify-start mt-1.5">
<div className="px-2 flex items-center bg-ch-gray-600 text-ch-gray-300 rounded-sm">
<Svg name="reactions" className="w-4 mr-2" />
{countEmotes(Reaction).reduce((prev, { count }) => prev + count, 0)}
</div>
<div className="px-2 flex items-center bg-ch-blue-650 bg-opacity-30 text-ch-gray-300 rounded-sm">
<Svg name="fork-new" className="w-4 mr-2" />0
</div>
</div>
</Link>
</li>
)
export default ProjectCard

View File

@@ -5,10 +5,12 @@ import CadPackage from 'src/components/CadPackage/CadPackage'
import { countEmotes } from 'src/helpers/emote'
import ImageUploader from 'src/components/ImageUploader'
import ProjectCard from 'src/components/ProjectCard/ProjectCard'
const ProjectsList = ({
projects,
shouldFilterProjectsWithoutImage = false,
projectLimit = 80,
}) => {
// temporary filtering projects that don't have images until some kind of search is added and there are more things on the website
// it helps avoid the look of the website just being filled with dumby data.
@@ -18,7 +20,9 @@ const ProjectsList = ({
const filteredProjects = useMemo(
() =>
(shouldFilterProjectsWithoutImage
? projects.filter(({ mainImage }) => mainImage)
? projects
.filter(({ mainImage }) => mainImage)
.slice(0, projectLimit || 80)
: [...projects]
)
// sort should probably be done on the service, but the filtering is temp too
@@ -30,64 +34,21 @@ const ProjectsList = ({
)
return (
<section className="max-w-6xl mx-auto">
<section className="max-w-7xl mx-auto">
<ul
className="grid gap-x-8 gap-y-12 items-center mx-4 relative"
className="grid gap-x-8 gap-y-8 items-center mx-4 relative"
style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(16rem, 1fr))' }}
>
{filteredProjects.map(
({ title, mainImage, user, Reaction, cadPackage }) => (
<li
className="rounded p-1.5 bg-ch-gray-760 shadow-ch"
key={`${user?.userName}--${title}`}
>
<Link
to={routes.project({
userName: user?.userName,
projectTitle: title,
})}
>
<div className="relative">
<ImageUploader
className="rounded"
aspectRatio={1.4}
imageUrl={mainImage}
width={700}
/>
<CadPackage
cadPackage={cadPackage}
className="absolute right-0 top-0 p-1.5 rounded-bl text-sm bg-opacity-50"
dotClass="w-3 h-3"
/>
</div>
<div className="flex items-center mt-1">
<div className="w-8 h-8 overflow-hidden rounded-full border border-ch-gray-300 shadow">
<ImageUploader
className=""
aspectRatio={1}
imageUrl={user?.image}
width={50}
/>
</div>
<div className="ml-3 text-lg text-ch-gray-300 font-fira-sans">
<div className="">{title}</div>
<div className="text-sm">{user?.userName}</div>
</div>
</div>
<div className="grid grid-flow-col-dense gap-2 justify-start mt-1.5">
<div className="px-2 flex items-center bg-ch-gray-600 text-ch-gray-300 rounded-sm">
<Svg name="reactions" className="w-4 mr-2" />
{countEmotes(Reaction).reduce(
(prev, { count }) => prev + count,
0
)}
</div>
<div className="px-2 flex items-center bg-ch-blue-650 bg-opacity-30 text-ch-gray-300 rounded-sm">
<Svg name="fork-new" className="w-4 mr-2" />0
</div>
</div>
</Link>
</li>
({ title, mainImage, user, Reaction, cadPackage }, index) => (
<ProjectCard
key={index}
title={title}
mainImage={mainImage}
user={user}
Reaction={Reaction}
cadPackage={cadPackage}
/>
)
)}
</ul>

View File

@@ -37,12 +37,13 @@ export const Empty = () => {
export const Success = ({
projects,
variables: { shouldFilterProjectsWithoutImage },
variables: { shouldFilterProjectsWithoutImage, projectLimit },
}) => {
return (
<Projects
projects={projects}
shouldFilterProjectsWithoutImage={shouldFilterProjectsWithoutImage}
projectLimit={projectLimit}
/>
)
}

View File

@@ -1,7 +1,8 @@
type SvgNames =
export type SvgNames =
| 'arrow-down'
// | 'arrow'
| 'arrow-left'
| 'arrow-right'
| 'camera'
| 'check'
| 'chevron-down'
@@ -71,6 +72,22 @@ const Svg = ({
/>
</svg>
),
'arrow-right': (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M14 5l7 7m0 0l-7 7m7-7H3"
/>
</svg>
),
camera: (
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 21">
<path

View File

@@ -93,18 +93,18 @@ const MainLayout = ({ children, shouldRemoveFooterInIde }) => {
return (
<div>
<header id="cadhub-main-header">
<nav className="flex justify-between h-20 md:px-12 bg-gradient-to-r from-gray-900 to-indigo-900">
<nav className="flex justify-between h-16 px-4 bg-ch-gray-900">
<ul className="flex items-center">
<li>
<Link to={routes.home()}>
<div className="rounded-full overflow-hidden ml-2 md:ml-8">
<Svg className="w-10 md:w-16" name="favicon" />
<div className="rounded-full overflow-hidden ml-2">
<Svg className="w-10" name="favicon" />
</div>
</Link>
</li>
<li>
<Tooltip title="Very alpha, there's lots of work todo">
<div className="ml-2 md:ml-12 flex">
<div className="ml-4 flex">
{/* Because of how specific these styles are to this heading/logo and it doesn't need to be replicated else where as well as it's very precise with the placement of "pre-alpha" I think it's appropriate. */}
<h2
className="text-indigo-300 text-2xl md:text-5xl font-ropa-sans py-1 md:tracking-wider"

View File

@@ -1,20 +1,16 @@
import MainLayout from 'src/layouts/MainLayout'
import ProjectsCell from 'src/components/ProjectsCell'
import LandingSection from 'src/components/LandingSection'
import Seo from 'src/components/Seo/Seo'
import { Hero } from 'src/components/Hero/Hero'
const ProjectsPage = () => {
return (
<MainLayout>
<MainLayout shouldRemoveFooterInIde>
<Seo
title="Projects page"
description="Cadhub Projects page"
title="Home page"
description="Learn about Code CAD and the CadHub community"
lang="en-US"
/>
<LandingSection />
<div className="bg-ch-gray-800 py-20">
<ProjectsCell shouldFilterProjectsWithoutImage />
</div>
<Hero />
</MainLayout>
)
}

View File

@@ -0,0 +1,23 @@
import ProjectsCell from 'src/components/ProjectsCell'
import MainLayout from 'src/layouts/MainLayout'
import Seo from 'src/components/Seo/Seo'
const ProjectsPage = () => {
return (
<MainLayout shouldRemoveFooterInIde>
<Seo
title="Projects page"
description="Cadhub Projects page"
lang="en-US"
/>
<div className="bg-ch-gray-800 pb-64">
<h1 className="max-w-7xl mx-auto text-4xl px-4 py-4 pt-16 text-ch-gray-300 font-sans">
Projects
</h1>
<ProjectsCell shouldFilterProjectsWithoutImage projectLimit={80} />
</div>
</MainLayout>
)
}
export default ProjectsPage