diff --git a/questions/2026.yaml b/questions/2026.yaml index bd9a5db..1857c9b 100644 --- a/questions/2026.yaml +++ b/questions/2026.yaml @@ -12,7 +12,7 @@ status: draft sections: - id: about - title: 나에 대해 + title: 기본 정보 questions: - id: status fixed: true diff --git a/src/components/QuestionStep.tsx b/src/components/QuestionStep.tsx index af3b1d5..db302bf 100644 --- a/src/components/QuestionStep.tsx +++ b/src/components/QuestionStep.tsx @@ -47,6 +47,11 @@ export function QuestionStep({ question: q, value, error, onPick, onToggle, onTe {q.label} + {q.required && ( + + {' *'} + + )} {q.help && ( diff --git a/src/components/ShareButton.tsx b/src/components/ShareButton.tsx index 303238d..be10cd2 100644 --- a/src/components/ShareButton.tsx +++ b/src/components/ShareButton.tsx @@ -37,7 +37,7 @@ export function ShareButton({ type, edition }: { type: DevType; edition: { id: s }, []) async function copy() { - await navigator.clipboard.writeText(`${text}\n${url}`) + await navigator.clipboard.writeText(url) setCopied(true) } diff --git a/src/components/StarBurst.tsx b/src/components/StarBurst.tsx new file mode 100644 index 0000000..a4b89f2 --- /dev/null +++ b/src/components/StarBurst.tsx @@ -0,0 +1,60 @@ +import { Icon } from 'daleui' +import { useState } from 'react' + +// 유형 결과가 처음 나올 때 한 번 터지는 별. 모션 줄이기 설정에서는 숨긴다. +const COUNT = 28 +const TONES = ['brand', 'warning', 'info'] as const + +export function StarBurst() { + // 제출한 뒤 브라우저에서만 그려지므로 Math.random 이 하이드레이션과 어긋나지 않는다 + const [stars] = useState(() => + Array.from({ length: COUNT }, (_, i) => { + const angle = (i / COUNT) * Math.PI * 2 + Math.random() * 0.4 + const dist = 140 + Math.random() * 220 + return { + x: Math.cos(angle) * dist, + y: Math.sin(angle) * dist * 0.7 - 60, + r: (Math.random() - 0.5) * 540, + delay: Math.random() * 150, + tone: TONES[i % TONES.length], + size: Math.random() < 0.3 ? ('md' as const) : ('sm' as const), + } + }), + ) + return ( +
+ + {stars.map((s, i) => ( + + + + ))} +
+ ) +} diff --git a/src/routes/$edition.survey.tsx b/src/routes/$edition.survey.tsx index 72c734d..c48cd48 100644 --- a/src/routes/$edition.survey.tsx +++ b/src/routes/$edition.survey.tsx @@ -10,6 +10,7 @@ import { ReadmeBadge } from '@/components/ReadmeBadge' import { SiteFooter } from '@/components/SiteFooter' import { SiteHeader } from '@/components/SiteHeader' import { ShareButton } from '@/components/ShareButton' +import { StarBurst } from '@/components/StarBurst' import { type DevType, devTypeOf, findDevType } from '@/lib/devType' import { findEdition, isBeta, isClosed } from '@/editions' import { koDate } from '@/lib/date' @@ -61,6 +62,62 @@ const quietAction: React.CSSProperties = { cursor: 'pointer', } +// 제출하는 동안 보여 주는 분석 화면. 유형을 정하는 두 문항(ai_frequency, company_criteria)을 짚어서 +// 결과가 내 답에서 나온다는 걸 보여 준다. 제출 대기와 겹치므로 실제로 늘어나는 시간은 짧다. +const ANALYSIS_STEPS = ['응답을 익명으로 저장하는 중', 'AI 사용 습관 읽는 중', '커리어 우선순위 확인 중', '2027년 커리어 한 줄 뽑는 중'] +const ANALYSIS_STEP_MS = 1200 +const ANALYSIS_MIN_MS = ANALYSIS_STEPS.length * ANALYSIS_STEP_MS + 400 +// 별 회전과 체크 표시에 쓰는, 살짝 지나쳤다 돌아오는 곡선 +const POP = 'cubic-bezier(0.34, 1.56, 0.64, 1)' + +function Analyzing() { + const [done, setDone] = useState(0) + useEffect(() => { + const t = setInterval(() => setDone((n) => Math.min(n + 1, ANALYSIS_STEPS.length)), ANALYSIS_STEP_MS) + return () => clearInterval(t) + }, []) + return ( +
+
+ {/* 단계마다 별이 돈다. 모션 줄이기 설정에서는 돌지 않는다 */} + + + + +
+ 두구두구… + + 내 답도 2026 한국 개발자 결과에 함께 담겨요! + +
+
    + {ANALYSIS_STEPS.map((step, i) => ( +
  • + {/* 끝난 단계에만 체크. 자리는 비워 둬서 글자가 움직이지 않게 한다 */} + + + + {i === done ? `${step}…` : step} +
  • + ))} +
+
+
+ ) +} + const bar: React.CSSProperties = { maxWidth: 1120, margin: '0 auto', boxSizing: 'border-box' } // 아래 버튼 줄. 데스크톱은 이전 | 건너뛸게요 ... 다음, 휴대폰은 다음을 넓게(1:2) 두고 건너뛸게요를 위로 올린다. @@ -110,7 +167,7 @@ function Finished({ saved, title, lead, devType, edition, onRetake }: {
- 응답을 저장했어요 + 익명으로 저장했어요
)} @@ -122,6 +179,7 @@ function Finished({ saved, title, lead, devType, edition, onRetake }: { {devType && (
+ {saved && }