Make new project card
designs https://www.figma.com/file/VUh53RdncjZ7NuFYj0RGB9/CadHub?node-id=1150%3A1619 Resolves #492
This commit is contained in:
@@ -13,6 +13,9 @@ module.exports = {
|
|||||||
borderRadius: {
|
borderRadius: {
|
||||||
half: '50%',
|
half: '50%',
|
||||||
},
|
},
|
||||||
|
boxShadow: {
|
||||||
|
ch: '0 4px 4px 0 rgba(0, 0, 0, 0.25), 0 4px 4px 0 rgba(13, 13, 19, 0.15)',
|
||||||
|
},
|
||||||
colors: {
|
colors: {
|
||||||
'ch-gray': {
|
'ch-gray': {
|
||||||
900: '#0D0D13',
|
900: '#0D0D13',
|
||||||
@@ -35,9 +38,10 @@ module.exports = {
|
|||||||
200: '#DBDBEC',
|
200: '#DBDBEC',
|
||||||
},
|
},
|
||||||
'ch-blue': {
|
'ch-blue': {
|
||||||
600: '#79B2F8',
|
700: '#08466F',
|
||||||
|
650: '#0958BA',
|
||||||
500: '5098F1',
|
500: '5098F1',
|
||||||
300: '#08466F'
|
400: '#79B2F8',
|
||||||
},
|
},
|
||||||
'ch-pink': {
|
'ch-pink': {
|
||||||
800: '#93064F',
|
800: '#93064F',
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
import { ideTypeNameMap } from 'src/helpers/hooks/useIdeContext'
|
import { ideTypeNameMap } from 'src/helpers/hooks/useIdeContext'
|
||||||
|
import type { CadPackage as CadPackageType } from 'src/helpers/hooks/useIdeState'
|
||||||
|
|
||||||
interface CadPackageProps {
|
interface CadPackageProps {
|
||||||
cadPackage: string
|
cadPackage: CadPackageType
|
||||||
className?: string
|
className?: string
|
||||||
|
dotClass?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const CadPackage = ({ cadPackage, className = '' }: CadPackageProps) => {
|
const CadPackage = ({
|
||||||
|
cadPackage,
|
||||||
|
className = '',
|
||||||
|
dotClass = 'w-5 h-5',
|
||||||
|
}: CadPackageProps) => {
|
||||||
const cadName = ideTypeNameMap[cadPackage] || ''
|
const cadName = ideTypeNameMap[cadPackage] || ''
|
||||||
const isOpenScad = cadPackage === 'openscad'
|
const isOpenScad = cadPackage === 'openscad'
|
||||||
const isCadQuery = cadPackage === 'cadquery'
|
const isCadQuery = cadPackage === 'cadquery'
|
||||||
@@ -14,13 +20,13 @@ const CadPackage = ({ cadPackage, className = '' }: CadPackageProps) => {
|
|||||||
className={
|
className={
|
||||||
`grid grid-flow-col-dense items-center gap-2 cursor-default text-gray-100 ${
|
`grid grid-flow-col-dense items-center gap-2 cursor-default text-gray-100 ${
|
||||||
isOpenScad && 'bg-yellow-800'
|
isOpenScad && 'bg-yellow-800'
|
||||||
} ${isCadQuery && 'bg-ch-blue-300'} bg-opacity-30 ` + className
|
} ${isCadQuery && 'bg-ch-blue-700'} bg-opacity-30 ` + className
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`${isOpenScad && 'bg-yellow-200'} ${
|
className={`${isOpenScad && 'bg-yellow-200'} ${
|
||||||
isCadQuery && 'bg-blue-800'
|
isCadQuery && 'bg-blue-800'
|
||||||
} w-5 h-5 rounded-full`}
|
} ${dotClass} rounded-full`}
|
||||||
/>
|
/>
|
||||||
<div>{cadName}</div>
|
<div>{cadName}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ function ChoiceParam({
|
|||||||
className={({ active }) =>
|
className={({ active }) =>
|
||||||
`${
|
`${
|
||||||
active
|
active
|
||||||
? 'text-ch-blue-600 bg-ch-gray-700'
|
? 'text-ch-blue-400 bg-ch-gray-700'
|
||||||
: 'text-ch-gray-300'
|
: 'text-ch-gray-300'
|
||||||
}
|
}
|
||||||
cursor-default select-none relative py-2 pl-10 pr-4`
|
cursor-default select-none relative py-2 pl-10 pr-4`
|
||||||
@@ -241,7 +241,7 @@ function ChoiceParam({
|
|||||||
{selected ? (
|
{selected ? (
|
||||||
<span
|
<span
|
||||||
className={`${
|
className={`${
|
||||||
active ? 'text-ch-blue-600' : 'text-ch-gray-300'
|
active ? 'text-ch-blue-400' : 'text-ch-gray-300'
|
||||||
}
|
}
|
||||||
absolute inset-y-0 left-0 flex items-center pl-3`}
|
absolute inset-y-0 left-0 flex items-center pl-3`}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
import Footer from './Footer'
|
|
||||||
|
|
||||||
export const generated = () => {
|
|
||||||
return <Footer />
|
|
||||||
}
|
|
||||||
|
|
||||||
export default { title: 'Components/Footer' }
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import { render } from '@redwoodjs/testing'
|
|
||||||
|
|
||||||
import Footer from './Footer'
|
|
||||||
|
|
||||||
describe('Footer', () => {
|
|
||||||
it('renders successfully', () => {
|
|
||||||
expect(() => {
|
|
||||||
render(<Footer />)
|
|
||||||
}).not.toThrow()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -3,7 +3,7 @@ import OutBound from 'src/components/OutBound'
|
|||||||
|
|
||||||
const Footer = () => {
|
const Footer = () => {
|
||||||
return (
|
return (
|
||||||
<div className="bg-indigo-900 text-indigo-200 font-roboto mt-20 text-sm">
|
<div className="bg-indigo-900 text-indigo-200 font-roboto text-sm">
|
||||||
<div className="flex h-16 md:justify-end items-center mx-2 md:mx-16 flex-wrap">
|
<div className="flex h-16 md:justify-end items-center mx-2 md:mx-16 flex-wrap">
|
||||||
<OutBound className="mr-8" to="https://github.com/Irev-Dev/cadhub">
|
<OutBound className="mr-8" to="https://github.com/Irev-Dev/cadhub">
|
||||||
Github
|
Github
|
||||||
@@ -18,7 +18,7 @@ const IdeConsole = () => {
|
|||||||
className="font-mono text-sm text-gray-400"
|
className="font-mono text-sm text-gray-400"
|
||||||
key={`${message} ${index}`}
|
key={`${message} ${index}`}
|
||||||
>
|
>
|
||||||
<div className="text-xs font-bold pt-2 text-ch-blue-600">
|
<div className="text-xs font-bold pt-2 text-ch-blue-400">
|
||||||
{time?.toLocaleString()}
|
{time?.toLocaleString()}
|
||||||
</div>
|
</div>
|
||||||
<div className={(type === 'error' ? 'text-red-400' : '') + ' pl-4'}>
|
<div className={(type === 'error' ? 'text-red-400' : '') + ' pl-4'}>
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import Editor, { useMonaco } from '@monaco-editor/react'
|
|||||||
import { theme } from 'src/../config/tailwind.config'
|
import { theme } from 'src/../config/tailwind.config'
|
||||||
import { useSaveCode } from 'src/components/IdeWrapper/useSaveCode'
|
import { useSaveCode } from 'src/components/IdeWrapper/useSaveCode'
|
||||||
import type { CadPackage as CadPackageType } from 'src/helpers/hooks/useIdeState'
|
import type { CadPackage as CadPackageType } from 'src/helpers/hooks/useIdeState'
|
||||||
import CadPackage from '../CadPackage/CadPackage'
|
|
||||||
|
|
||||||
const colors = theme.extend.colors
|
const colors = theme.extend.colors
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const KeyValue = ({
|
|||||||
if (!children || hide) return null
|
if (!children || hide) return null
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="text-ch-blue-600 font-fira-code flex text-sm whitespace-nowrap">
|
<div className="text-ch-blue-400 font-fira-code flex text-sm whitespace-nowrap">
|
||||||
{keyName}
|
{keyName}
|
||||||
{canEdit &&
|
{canEdit &&
|
||||||
(isEditable ? (
|
(isEditable ? (
|
||||||
@@ -246,7 +246,7 @@ const ProjectProfile = ({
|
|||||||
/>
|
/>
|
||||||
{user?.userName}
|
{user?.userName}
|
||||||
</Link>
|
</Link>
|
||||||
<div className="font-fira-code text-ch-blue-600 flex items-center">
|
<div className="font-fira-code text-ch-blue-400 flex items-center">
|
||||||
{new Date(createdAt).toDateString()}
|
{new Date(createdAt).toDateString()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { Link, routes } from '@redwoodjs/router'
|
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 { countEmotes } from 'src/helpers/emote'
|
||||||
import ImageUploader from 'src/components/ImageUploader'
|
import ImageUploader from 'src/components/ImageUploader'
|
||||||
@@ -11,6 +13,8 @@ const ProjectsList = ({
|
|||||||
// temporary filtering projects that don't have images until some kind of search is added and there are more things on the website
|
// 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.
|
// it helps avoid the look of the website just being filled with dumby data.
|
||||||
// related issue-104
|
// related issue-104
|
||||||
|
|
||||||
|
// note to self the projectCard is hardcoded directly into this component will not be hard the extract later when we need it elsewhere.
|
||||||
const filteredProjects = useMemo(
|
const filteredProjects = useMemo(
|
||||||
() =>
|
() =>
|
||||||
(shouldFilterProjectsWithoutImage
|
(shouldFilterProjectsWithoutImage
|
||||||
@@ -24,15 +28,17 @@ const ProjectsList = ({
|
|||||||
),
|
),
|
||||||
[projects, shouldFilterProjectsWithoutImage]
|
[projects, shouldFilterProjectsWithoutImage]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="max-w-6xl mx-auto mt-8">
|
<section className="max-w-6xl mx-auto">
|
||||||
<ul
|
<ul
|
||||||
className="grid gap-x-8 gap-y-12 items-center mx-4 relative"
|
className="grid gap-x-8 gap-y-12 items-center mx-4 relative"
|
||||||
style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(16rem, 1fr))' }}
|
style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(16rem, 1fr))' }}
|
||||||
>
|
>
|
||||||
{filteredProjects.map(({ title, mainImage, user, Reaction }) => (
|
{filteredProjects.map(
|
||||||
|
({ title, mainImage, user, Reaction, cadPackage }) => (
|
||||||
<li
|
<li
|
||||||
className="rounded-lg shadow-md hover:shadow-lg mx-px transform hover:-translate-y-px transition-all duration-150"
|
className="rounded p-1.5 bg-ch-gray-760 shadow-ch"
|
||||||
key={`${user?.userName}--${title}`}
|
key={`${user?.userName}--${title}`}
|
||||||
>
|
>
|
||||||
<Link
|
<Link
|
||||||
@@ -41,8 +47,21 @@ const ProjectsList = ({
|
|||||||
projectTitle: title,
|
projectTitle: title,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div className="flex items-center p-2 bg-gray-200 border-gray-300 rounded-t-lg border-t border-l border-r">
|
<div className="relative">
|
||||||
<div className="w-8 h-8 overflow-hidden rounded-full border border-indigo-300 shadow">
|
<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
|
<ImageUploader
|
||||||
className=""
|
className=""
|
||||||
aspectRatio={1}
|
aspectRatio={1}
|
||||||
@@ -50,41 +69,27 @@ const ProjectsList = ({
|
|||||||
width={50}
|
width={50}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className="font-ropa-sans ml-3 text-lg text-indigo-900">
|
<div className="ml-3 text-lg text-ch-gray-300 font-fira-sans">
|
||||||
{title}
|
<div className="">{title}</div>
|
||||||
</span>
|
<div className="text-sm">{user?.userName}</div>
|
||||||
</div>
|
|
||||||
<div className="w-full overflow-hidden relative rounded-b-lg">
|
|
||||||
<ImageUploader
|
|
||||||
className=""
|
|
||||||
aspectRatio={1.4}
|
|
||||||
imageUrl={mainImage}
|
|
||||||
width={700}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className="absolute inset-0"
|
|
||||||
style={{
|
|
||||||
background:
|
|
||||||
'linear-gradient(19.04deg, rgba(62, 44, 118, 0.46) 10.52%, rgba(60, 54, 107, 0) 40.02%)',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="absolute inset-x-0 bottom-0 -mb-4 mr-4 flex justify-end">
|
|
||||||
{countEmotes(Reaction).map(({ emoji, count }) => (
|
|
||||||
<div
|
|
||||||
key={emoji}
|
|
||||||
className="h-8 w-8 overflow-hidden ml-2 p-1 rounded-full bg-opacity-75 bg-gray-200 border border-gray-300 shadow-md flex items-center justify-between"
|
|
||||||
>
|
|
||||||
<div className="-ml-px text-sm w-1">{emoji}</div>
|
|
||||||
<div className="text-sm pl-1 font-ropa-sans text-gray-800">
|
|
||||||
{count}
|
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
))}
|
)
|
||||||
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export const QUERY = gql`
|
|||||||
projects {
|
projects {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
|
cadPackage
|
||||||
mainImage
|
mainImage
|
||||||
createdAt
|
createdAt
|
||||||
updatedAt
|
updatedAt
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ const ProjectsPage = () => {
|
|||||||
lang="en-US"
|
lang="en-US"
|
||||||
/>
|
/>
|
||||||
<LandingSection />
|
<LandingSection />
|
||||||
|
<div className="bg-ch-gray-800 py-20">
|
||||||
<ProjectsCell shouldFilterProjectsWithoutImage />
|
<ProjectsCell shouldFilterProjectsWithoutImage />
|
||||||
|
</div>
|
||||||
</MainLayout>
|
</MainLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user