footers
This commit is contained in:
parent
7dc7c9720b
commit
e7095aaa66
3 changed files with 153 additions and 1 deletions
80
src/blocks/Skills/Component.ts
Normal file
80
src/blocks/Skills/Component.ts
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
import React from 'react'
|
||||
import { cn } from '@/utilities/ui'
|
||||
|
||||
type SkillCategory = {
|
||||
title: string
|
||||
icon: string
|
||||
tags: { tag: string }[]
|
||||
}
|
||||
|
||||
type SkillsBlockProps = {
|
||||
heading?: string
|
||||
keySkills?: { skill: string }[]
|
||||
categories?: SkillCategory[]
|
||||
}
|
||||
|
||||
export function SkillsBlock({ heading, keySkills, categories }: SkillsBlockProps) {
|
||||
return (
|
||||
<section className="w-full px-6 py-16">
|
||||
{/* Heading */}
|
||||
{heading && (
|
||||
<p className="text-center text-xs tracking-widest uppercase text-white/30 mb-6">
|
||||
{heading}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Key skills pills */}
|
||||
{Array.isArray(keySkills) && keySkills.length > 0 && (
|
||||
<div className="flex justify-center gap-3 flex-wrap mb-12">
|
||||
{keySkills.map(({ skill }, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className="text-xs text-white/70 border border-white/25 rounded-full px-4 py-1.5"
|
||||
>
|
||||
{skill}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Categories grid */}
|
||||
{Array.isArray(categories) && categories.length > 0 && (
|
||||
<div
|
||||
className="border border-white/8 rounded-xl overflow-hidden"
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(3, 1fr)',
|
||||
}}
|
||||
>
|
||||
{categories.map((cat, i) => {
|
||||
const isLastRow = i >= categories.length - (categories.length % 3 || 3)
|
||||
const isLastCol = (i + 1) % 3 === 0
|
||||
return (
|
||||
<div
|
||||
key={i}
|
||||
className={cn(
|
||||
'p-6 flex flex-col gap-3',
|
||||
!isLastCol && 'border-r border-white/8',
|
||||
!isLastRow && 'border-b border-white/8',
|
||||
)}
|
||||
>
|
||||
<i className={`ti ${cat.icon} text-white/40`} style={{ fontSize: 20 }} aria-hidden="true" />
|
||||
<p className="text-sm font-medium text-white/85">{cat.title}</p>
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{Array.isArray(cat.tags) && cat.tags.map(({ tag }, j) => (
|
||||
<span
|
||||
key={j}
|
||||
className="text-xs text-white/35 border border-white/10 rounded-full px-2.5 py-0.5"
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
71
src/blocks/Skills/config.ts
Normal file
71
src/blocks/Skills/config.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import type { Block } from 'payload'
|
||||
|
||||
export const SkillsBlock: Block = {
|
||||
slug: 'skills',
|
||||
labels: {
|
||||
singular: 'Skills Section',
|
||||
plural: 'Skills Sections',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'heading',
|
||||
type: 'text',
|
||||
defaultValue: 'what i bring to the table',
|
||||
},
|
||||
{
|
||||
name: 'keySkills',
|
||||
type: 'array',
|
||||
label: 'Key skills (pills at top)',
|
||||
fields: [
|
||||
{
|
||||
name: 'skill',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'categories',
|
||||
type: 'array',
|
||||
label: 'Skill categories',
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'icon',
|
||||
type: 'select',
|
||||
label: 'Icon (Tabler icon name)',
|
||||
defaultValue: 'ti-layout',
|
||||
options: [
|
||||
{ label: 'Layout', value: 'ti-layout' },
|
||||
{ label: 'Server', value: 'ti-server' },
|
||||
{ label: 'Design / Pen', value: 'ti-vector-pen' },
|
||||
{ label: 'Briefcase', value: 'ti-briefcase' },
|
||||
{ label: 'Globe', value: 'ti-world' },
|
||||
{ label: 'Camera', value: 'ti-camera' },
|
||||
{ label: 'Tools', value: 'ti-tools' },
|
||||
{ label: 'Sparkles', value: 'ti-sparkles' },
|
||||
{ label: 'Mobile', value: 'ti-device-mobile' },
|
||||
{ label: 'Code', value: 'ti-code' },
|
||||
{ label: 'Chart', value: 'ti-chart-bar' },
|
||||
{ label: 'Star', value: 'ti-star' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'tags',
|
||||
type: 'array',
|
||||
fields: [
|
||||
{
|
||||
name: 'tag',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import { CallToAction } from '../../blocks/CallToAction/config'
|
|||
import { Content } from '../../blocks/Content/config'
|
||||
import { FormBlock } from '../../blocks/Form/config'
|
||||
import { MediaBlock } from '../../blocks/MediaBlock/config'
|
||||
import { SkillsBlock } from '../../blocks/Skills/config'
|
||||
import { hero } from '@/heros/config'
|
||||
import { slugField } from 'payload'
|
||||
import { populatePublishedAt } from '../../hooks/populatePublishedAt'
|
||||
|
|
@ -72,7 +73,7 @@ export const Pages: CollectionConfig<'pages'> = {
|
|||
{
|
||||
name: 'layout',
|
||||
type: 'blocks',
|
||||
blocks: [CallToAction, Content, MediaBlock, Archive, FormBlock],
|
||||
blocks: [CallToAction, Content, MediaBlock, Archive, FormBlock, SkillsBlock],
|
||||
required: true,
|
||||
admin: {
|
||||
initCollapsed: true,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue