Skip to content

Commit d03939d

Browse files
committed
feat: hero
Signed-off-by: Innei <[email protected]>
1 parent 1423459 commit d03939d

File tree

4 files changed

+251
-11
lines changed

4 files changed

+251
-11
lines changed

src/app.config.ts

+30
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,36 @@ export const appConfig = {
88
favicon: '/innei.svg',
99
},
1010

11+
hero: {
12+
title: {
13+
template: [
14+
{
15+
type: 'h1',
16+
text: '你好呀,我是',
17+
class: 'font-light text-4xl',
18+
},
19+
{
20+
type: 'h1',
21+
text: 'Innei',
22+
class: 'font-medium mx-2 text-4xl',
23+
},
24+
{
25+
type: 'h1',
26+
text: '👋。',
27+
class: 'font-light text-4xl',
28+
},
29+
{
30+
type: 'br',
31+
},
32+
{
33+
type: 'h1',
34+
text: '一个独立开发者',
35+
class: 'font-light text-4xl',
36+
},
37+
],
38+
},
39+
description: `一位深入研究编程领域的独立开发者,热衷于纯音乐、二次元文化和电子产品。持有强烈的创新精神,始终以用户体验为首要考虑,在技术开发中追求卓越。`,
40+
},
1141
module: {
1242
donate: {
1343
enable: true,

src/app/(home)/page.tsx

+100-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
'use client'
22

3-
import { forwardRef } from 'react'
3+
import { createElement, forwardRef } from 'react'
4+
import clsx from 'clsx'
45
import { m } from 'framer-motion'
56
import type { PropsWithChildren } from 'react'
67

8+
import { BottomToUpTransitionView } from '~/components/ui/transition/BottomToUpTransitionView'
9+
import { SocialIcon } from '~/components/widgets/home/SocialIcon'
710
import { softBouncePrest } from '~/constants/spring'
11+
import { useConfig } from '~/hooks/data/use-config'
12+
import { isDev } from '~/lib/env'
813
import { clsxm } from '~/lib/helper'
14+
import { noopObj } from '~/lib/noop'
15+
import { useAggregationSelector } from '~/providers/root/aggregation-data-provider'
916

17+
const debugStyle = {
18+
outline: '1px solid #0088cc',
19+
}
1020
const Screen = forwardRef<
1121
HTMLDivElement,
1222
PropsWithChildren<{
@@ -16,7 +26,11 @@ const Screen = forwardRef<
1626
return (
1727
<div
1828
ref={ref}
19-
className={clsxm('flex h-screen flex-col center', props.className)}
29+
style={isDev ? debugStyle : undefined}
30+
className={clsxm(
31+
'relative flex h-screen flex-col center',
32+
props.className,
33+
)}
2034
>
2135
{props.children}
2236
</div>
@@ -37,9 +51,7 @@ export default function Home() {
3751
<Welcome />
3852

3953
<Screen>
40-
<h1>
41-
在这个矩阵中,你可以找到各种各样的代码块,它们是我在计算机科学的探索和实践的证明。
42-
</h1>
54+
<PostBlock />
4355
</Screen>
4456
<Screen>
4557
<h1>
@@ -61,17 +73,96 @@ export default function Home() {
6173
}
6274

6375
const Welcome = () => {
76+
const { title, description } = useConfig().hero
77+
const siteOwner = useAggregationSelector((agg) => agg.user)
78+
const { avatar, socialIds } = siteOwner || {}
6479
return (
6580
<Screen className="mt-[-4.5rem]">
66-
<div>
67-
<m.h1
68-
initial={{ opacity: 0.0001, y: 100 }}
81+
<div className="flex h-full w-full flex-col flex-wrap items-center lg:flex-row">
82+
<div className="flex h-1/2 w-full flex-col center lg:h-auto lg:w-1/2">
83+
<div className="relative max-w-xl">
84+
<m.div
85+
className="relative leading-[4] [&_*]:inline-block"
86+
initial={{ opacity: 0.0001, y: 50 }}
87+
animate={{ opacity: 1, y: 0 }}
88+
transition={softBouncePrest}
89+
>
90+
{title.template.map((t, i) => {
91+
const { type } = t
92+
return createElement(
93+
type,
94+
{ key: i, className: t.class },
95+
t.text,
96+
)
97+
})}
98+
</m.div>
99+
100+
<BottomToUpTransitionView
101+
delay={300}
102+
transition={softBouncePrest}
103+
className="my-3"
104+
>
105+
<span className="opacity-80">{description}</span>
106+
</BottomToUpTransitionView>
107+
108+
<ul className="flex space-x-4 center lg:mt-[7rem] lg:block">
109+
{Object.entries(socialIds || noopObj).map(
110+
([type, id]: any, index) => {
111+
return (
112+
<BottomToUpTransitionView
113+
key={type}
114+
delay={index * 100 + 500}
115+
className="inline-block"
116+
as="li"
117+
>
118+
<SocialIcon id={id} type={type} />
119+
</BottomToUpTransitionView>
120+
)
121+
},
122+
)}
123+
</ul>
124+
</div>
125+
</div>
126+
127+
<div className="flex h-1/2 w-full center lg:h-full lg:w-1/2">
128+
<img
129+
src={avatar}
130+
alt="Site Owner Avatar"
131+
className={clsxm(
132+
'aspect-square rounded-full ring-1 ring-slate-200 dark:ring-neutral-800',
133+
'lg:h-[300px] lg:w-[300px]',
134+
'h-[200px] w-[200px]',
135+
)}
136+
/>
137+
</div>
138+
</div>
139+
140+
<div
141+
className={clsx(
142+
'absolute bottom-0 left-0 right-0 flex flex-col center',
143+
144+
'text-neutral-800/80 center dark:text-neutral-200/80',
145+
)}
146+
>
147+
<m.small
148+
initial={{ opacity: 0.0001, y: 50 }}
69149
animate={{ opacity: 1, y: 0 }}
70150
transition={softBouncePrest}
71151
>
72152
欢迎,来到这个小小的宇宙,一个闪烁着光彩的星球,等待着你的探索。
73-
</m.h1>
153+
</m.small>
154+
<span className="mt-8 animate-bounce">
155+
<i className="icon-[mingcute--right-line] rotate-90 text-2xl" />
156+
</span>
74157
</div>
75158
</Screen>
76159
)
77160
}
161+
162+
const PostBlock = () => {
163+
return (
164+
<h1>
165+
在这个矩阵中,你可以找到各种各样的代码块,它们是我在计算机科学的探索和实践的证明。
166+
</h1>
167+
)
168+
}
+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { memo, useMemo } from 'react'
2+
3+
import { MotionButtonBase } from '~/components/ui/button'
4+
import { FloatPopover } from '~/components/ui/float-popover'
5+
6+
interface SocialIconProps {
7+
type: string
8+
id: string
9+
}
10+
11+
const type2Copy = {
12+
github: 'GitHub',
13+
twitter: 'Twitter',
14+
telegram: 'Telegram',
15+
mail: 'Email',
16+
rss: 'RSS',
17+
email: 'Email',
18+
feed: 'RSS',
19+
} as any
20+
export const SocialIcon = memo((props: SocialIconProps) => {
21+
const { id, type } = props
22+
const Icon = useMemo(() => {
23+
switch (type) {
24+
case 'github': {
25+
return <i className="icon-[mingcute--github-line]" />
26+
}
27+
case 'twitter': {
28+
return <i className="icon-[mingcute--twitter-line]" />
29+
}
30+
31+
case 'telegram': {
32+
return <i className="icon-[mingcute--telegram-line]" />
33+
}
34+
case 'mail':
35+
case 'email': {
36+
return <i className="icon-[mingcute--mail-line]" />
37+
}
38+
case 'rss':
39+
case 'feed': {
40+
return <i className="icon-[mingcute--rss-line]" />
41+
}
42+
}
43+
44+
return null
45+
}, [type])
46+
const href = useMemo(() => {
47+
switch (type) {
48+
case 'github': {
49+
return `https://github.com/${id}`
50+
}
51+
case 'twitter': {
52+
return `https://twitter.com/${id}`
53+
}
54+
55+
case 'telegram': {
56+
return `https://t.me/${id}`
57+
}
58+
case 'mail':
59+
case 'email': {
60+
return `mailto:${id}`
61+
}
62+
case 'rss':
63+
case 'feed': {
64+
return id
65+
}
66+
}
67+
}, [id, type])
68+
69+
const iconBg = useMemo(() => {
70+
switch (type) {
71+
case 'github': {
72+
return '#181717'
73+
}
74+
case 'twitter': {
75+
return '#1DA1F2'
76+
}
77+
78+
case 'telegram': {
79+
return '#0088cc'
80+
}
81+
case 'mail':
82+
case 'email': {
83+
return '#D44638'
84+
}
85+
case 'rss':
86+
case 'feed': {
87+
return '#FFA500'
88+
}
89+
}
90+
}, [type])
91+
92+
if (!Icon) return null
93+
94+
return (
95+
<FloatPopover
96+
type="tooltip"
97+
TriggerComponent={() => (
98+
<MotionButtonBase
99+
className="flex aspect-square h-10 w-10 rounded-full text-2xl text-white center"
100+
style={{
101+
background: iconBg,
102+
}}
103+
>
104+
<a
105+
target="_blank"
106+
href={href}
107+
className="flex center"
108+
rel="noreferrer"
109+
>
110+
{Icon}
111+
</a>
112+
</MotionButtonBase>
113+
)}
114+
>
115+
{type2Copy[type] || ''}
116+
</FloatPopover>
117+
)
118+
})
119+
SocialIcon.displayName = 'SocialIcon'

src/styles/image-zoom.css

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/* image-zoom */
22
.medium-zoom-overlay {
3-
z-index: 9;
3+
z-index: 99;
44

55
@apply !bg-slate-50 dark:!bg-neutral-900;
66
}
77

88
.medium-zoom-overlay + .medium-zoom-image {
9-
z-index: 10;
9+
z-index: 100;
1010
}
1111

1212
.medium-zoom-image {

0 commit comments

Comments
 (0)