Ilia Mashkov
b88263a65a
fix: DetailedProjectCard — render description as RichText
2026-05-18 20:46:13 +03:00
Ilia Mashkov
06e39b58c6
refactor: ProjectsSection — use shared buildFileUrl, pass url prop, switch to stacked layout
2026-05-18 20:46:02 +03:00
Ilia Mashkov
ac9ee0eb4e
feat: ProjectCard — add url prop, RichText description, open link in new tab
2026-05-18 20:45:54 +03:00
Ilia Mashkov
2ae5ae3210
feat: wire Footer to PocketBase site_settings
...
Fetches CV file, email and social links via expand=contacts,contacts.socials.
CV rendered as polymorphic Button with download attr; socials and email
rendered as Link components.
2026-05-18 20:45:44 +03:00
Ilia Mashkov
f159c6e861
feat: add SocialRecord, ContactsRecord, SiteSettingsRecord API types
...
Models PocketBase relations: SiteSettings → contacts → ContactsRecord
→ socials[] → SocialRecord. expand fields typed as optional resolved
records for use with PocketBase expand query param.
2026-05-18 20:45:32 +03:00
Ilia Mashkov
b33b9f328c
feat: add Link shared component
...
Renders Next.js Link for internal routes, plain anchor with
target="_blank" rel="noopener noreferrer" when external prop is set.
2026-05-18 20:45:17 +03:00
Ilia Mashkov
c9631f9905
feat: add buildFileUrl utility with tests
...
Moved from ProjectsSection inline function to shared/lib/utils.
Accepts optional baseUrl for testability without env mocking.
2026-05-18 20:45:06 +03:00
Ilia Mashkov
ba7395cb32
feat: make Button polymorphic — renders <a> when href is provided
...
Discriminated union types (AsButton | AsAnchor), isAnchorProps type guard
eliminates all 'as' casts. as const satisfies for VARIANTS/SIZES lookup
tables. brutal-border replaces border-[3px] in ghost variant.
2026-05-18 20:44:50 +03:00
Ilia Mashkov
7e542597d0
feat: Footer widget with email link and CV download, added to root layout
2026-05-18 14:15:25 +03:00
Ilia Mashkov
0552a2a8e5
refactor: register text-section-title in @theme inline, use as plain utility class
2026-05-18 14:06:01 +03:00
Ilia Mashkov
d955aeb628
refactor: replace inline style with Tailwind class and font-wonk utility
2026-05-18 14:04:56 +03:00
Ilia Mashkov
b40ff4f588
fix: fluid section title with clamp() to prevent wrapping below 900px
2026-05-18 14:02:03 +03:00
Ilia Mashkov
531de6899e
refactor: ProjectCard sm button, left-border year matching ExperienceCard style
2026-05-18 13:20:47 +03:00
Ilia Mashkov
10034ec561
refactor: ProjectCard sidebar layout — year, tags, button in sidebar
2026-05-18 13:14:40 +03:00
Ilia Mashkov
458ee0e449
refactor: CardSidebar layout breakpoint md → lg for wider description area
2026-05-18 13:11:53 +03:00
Ilia Mashkov
979e2071d1
refactor: widen section and sidebar, plain period text, Badge xs size for stack
2026-05-18 13:07:01 +03:00
Ilia Mashkov
37098be3c8
feat: Badge size prop (sm/md) and use Badge in ExperienceCard
2026-05-18 13:02:07 +03:00
Ilia Mashkov
48a08ec3fb
feat: formatMonthYearRange — period now includes abbreviated month
2026-05-18 13:01:58 +03:00
Ilia Mashkov
1550989fd9
feat: CardSidebar layout component and ExperienceCard sidebar redesign
...
Sidebar: period badge, company, stack tags.
Main: role title and rich-text description.
2026-05-18 12:51:33 +03:00
Ilia Mashkov
782c619a91
feat: ExperienceCard stack field and Card subcomponent layout
2026-05-18 12:39:41 +03:00
Ilia Mashkov
543020f85c
feat: apply Fraunces font to ProjectCard title
2026-05-18 12:39:33 +03:00
Ilia Mashkov
e00c1460e1
refactor: responsive spacing on CardHeader and CardFooter
2026-05-18 12:39:20 +03:00
Ilia Mashkov
f874a943ff
fix: a11y — accessible label on SectionAccordion, opacity-60 on category headings
2026-05-18 12:39:07 +03:00
Ilia Mashkov
ff62cba5b1
feat: add line-height-relaxed token and text selection/focus-visible styles
2026-05-18 12:38:28 +03:00
Ilia Mashkov
f4986d6657
chore: split React import to satisfy linter in ViewTransitionWrapper
2026-05-18 12:38:17 +03:00
Ilia Mashkov
e3959c0e45
fix: add cursor-pointer to Button
2026-05-18 12:38:10 +03:00
Ilia Mashkov
76f5b269f8
refactor: use shadow theme tokens, remove ProjectCard translate-hover
...
Replace inline var(--blue) arbitrary shadow values with typed theme
tokens (shadow-brutal-xl, shadow-brutal-2xl). Remove translate on
ProjectCard hover — shadow-only interaction is less distracting in
a dense grid layout.
2026-05-16 19:04:37 +03:00
Ilia Mashkov
b8b5e65497
feat: constrain section content width with max-w-section
...
Adds max-w-section (56rem via --container-section token) to the
experience, projects, and skills section wrappers for consistent
readable line length across all content areas.
2026-05-16 19:04:27 +03:00
Ilia Mashkov
e63de14515
feat: apply RichText to content sections and experience cards
...
ExperienceCard description switches from a plain <p> to RichText so
rich-text HTML from PocketBase renders correctly. BioSection and
IntroSection drop the prose class overrides — RichText handles
typography consistently.
2026-05-16 19:04:18 +03:00
Ilia Mashkov
dfc3ed4715
feat: editorial typography via RichText component
...
Always wraps content in .rich-text: max-width 65ch, onum figures,
hanging punctuation, pretty text-wrap, auto hyphens, 1.65 line-height,
and 1.2em paragraph spacing. className prop merges additonal classes.
2026-05-16 19:04:08 +03:00
Ilia Mashkov
a77cd43749
feat: Button elevation hover/active effect with snap shadow
...
Variants now use brutal shadow tokens. On hover the button translates
up-left (−0.5px), on active down-right (+0.5px). Only transform animates
(130ms ease-out); shadow snaps instantly so the eye reads button movement
not shadow resize. Primary keeps rgba alpha shadow; secondary/outline use
solid brutal tokens.
2026-05-16 19:04:00 +03:00
Ilia Mashkov
8db4f81f70
refactor: simplify section body animation to hard-cut on navigation
2026-05-16 19:03:50 +03:00
Ilia Mashkov
f1049624f7
refactor: design tokens — shadow scale, animation timing, section width
...
- Expand brutal shadow scale: xs (1px) through 2xl (12px)
- Add --ease-micro cubic-bezier for fast micro-interactions
- Tune --duration-normal 200ms→150ms, --duration-spring 380ms→220ms
- Add --section-content-width and register as --container-section in @theme inline
- Register all brutal shadow tokens in @theme inline for Tailwind utility generation
- Add .btn-transition utility (transform-only, shadow snaps instantly)
- Add .rich-text editorial typography class with magazine-quality settings
- Remove section-body blur-out/slide-in view transition animations
2026-05-16 19:03:43 +03:00
Ilia Mashkov
92e4a01641
refactor: group experience/ui components into subdirectories
2026-05-13 09:40:09 +03:00
Ilia Mashkov
9cf8caaead
refactor: group project/ui components into subdirectories
2026-05-13 09:40:00 +03:00
Ilia Mashkov
e518fc46a9
feat: section body animation with blur-out, delayed enter, and animation tokens
...
Add animation tokens to :root (--ease-spring, --ease-decelerate,
--ease-default, --duration-fast/normal/slow/spring). Apply spring easing
to section title enter. Add separate section-body transition: fast
blur-out exit (100ms), clean slide-in enter (350ms) delayed by 200ms so
content appears after the title animation completes.
2026-05-13 09:39:47 +03:00
Ilia Mashkov
481dda3c95
fix: resolve inactive section title hover opacity conflict
...
hover:opacity-60 on Link and opacity-30/group-hover:opacity-50 on h2
were multiplying (0.6 × 0.5 = 0.30 = base), making hover invisible.
Removed opacity from Link, consolidated to h2 only: opacity-30 base,
group-hover:opacity-60 on hover.
2026-05-13 09:39:08 +03:00
Ilia Mashkov
d28343e22c
feat: section open/close animations via ViewTransition and @starting-style
...
Enable experimental.viewTransition in Next.js config. Wrap active section
in ViewTransitionWrapper so the browser cross-fades between sections on
navigation. Replace animate-fadeIn keyframe with @starting-style + CSS
transition for the initial render enter animation.
2026-05-12 16:10:50 +03:00
Ilia Mashkov
7cba3053f4
feat: ViewTransitionWrapper shared component with stable react-dom fallback
...
Wraps children in React's ViewTransition (canary API) when available,
falling back to Fragment in environments where ViewTransition is undefined
(test env, stable react-dom). Add react/canary to tsconfig types to
expose the ViewTransition component type.
2026-05-12 16:10:37 +03:00
Ilia Mashkov
0090718869
fix: add outline to primary and secondary button variants
2026-05-12 13:58:29 +03:00
Ilia Mashkov
301e7a2555
feat: RichText component for safe PocketBase HTML rendering
...
Add html-react-parser-backed RichText component that converts HTML
strings from PocketBase rich-text fields into React elements without
dangerouslySetInnerHTML. Replace raw <p> render in IntroSection and
BioSection, and drop the invalid slug filters those collections lacked.
2026-05-12 13:58:17 +03:00
Ilia Mashkov
0a99a37bca
fix: remove underline from collapsed section title links
...
Global a { border-bottom } was leaking onto the inactive section
nav links. Override with border-b-0 hover:border-b-0.
2026-05-12 13:57:39 +03:00
Ilia Mashkov
e8bf8b502e
fix: align PocketBase type definitions with actual schema
...
Remove slug field from PageContentRecord (intro/bio collections have none).
Remove number field from SectionRecord (not stored in PocketBase); derive
zero-padded display number from the order field at render time.
2026-05-12 13:57:25 +03:00
Ilia Mashkov
30f8e4be95
design: two-color palette — rename all tokens to --cream / --blue
...
Replace ochre-clay, carbon-black, burnt-oxide, slate-indigo with clean
two-color system: --cream (#f4f0e8) and --blue (#041cf3). Update every
component, utility class, and test assertion.
2026-05-11 12:59:32 +03:00
Ilia Mashkov
fed9c97ddb
feat: URL-driven catchall routing, drop sidebar nav, split export build
...
- app/[[...slug]]/page.tsx replaces app/page.tsx; activeSlug from URL params
- SidebarNav and MobileNav removed from main layout (sections accordion is the nav)
- next.config.ts: output:export controlled by STATIC_EXPORT env var instead of NODE_ENV
- package.json: yarn build is standard Next.js build; yarn export is STATIC_EXPORT=true
- Mock API route: force-static + generateStaticParams for output:export compatibility
2026-05-11 11:12:21 +03:00
Ilia Mashkov
af165ec356
feat: MobileNav section items use Link, close menu on pathname change
2026-05-11 11:11:53 +03:00
Ilia Mashkov
1dfa9a62a2
design: update color palette from ochre-clay to white/blue scheme
2026-05-11 11:11:29 +03:00
Ilia Mashkov
b4bda4b8f7
chore: biome format vitest config, add Props JSDoc to SidebarNav
2026-05-11 11:11:24 +03:00
Ilia Mashkov
f9cdb06632
refactor: SidebarNav uses usePathname and Link instead of IntersectionObserver
2026-05-07 12:54:53 +03:00
Ilia Mashkov
9fa2156ee8
feat: SectionAccordion inactive state uses Link href instead of button onClick
2026-05-07 12:52:54 +03:00
Ilia Mashkov
ced77f6f07
fix: make output export build-only so dev route handlers work
2026-05-07 12:28:42 +03:00
Ilia Mashkov
f163b750b2
docs: add URL-driven section routing implementation plan
2026-05-07 11:48:55 +03:00
Ilia Mashkov
41d1a37352
docs: add URL-driven section routing design
2026-05-07 11:45:54 +03:00
Ilia Mashkov
1a413e3d04
feat: implement portfolio home page with split layout
2026-05-05 09:42:04 +03:00
Ilia Mashkov
24bf946cb0
refactor: SectionFactory static registry, remove dynamic imports
2026-05-05 09:41:56 +03:00
Ilia Mashkov
4219a7b4e7
fix: correct RSC error patterns and extract skills grouping to utility
2026-05-05 09:41:49 +03:00
Ilia Mashkov
4b18fc454e
chore: add mock API route handlers and dev env config
2026-05-05 09:41:39 +03:00
Ilia Mashkov
41edc7edf7
refactor: reorganize shared/lib into per-function subfolders
2026-04-24 11:43:08 +03:00
Ilia Mashkov
f3b4e1d064
refactor: extract contact links to shared config
2026-04-24 10:11:34 +03:00
Ilia Mashkov
fce4672218
feat: add groupByKey utility
2026-04-24 09:34:27 +03:00
Ilia Mashkov
d89dc2ee70
chore: add vitest/globals types, remove redundant vitest imports, fix pre-existing lint issues
2026-04-24 09:34:27 +03:00
Ilia Mashkov
f0fccd55f1
fix: replace revalidate with cache force-cache for SSG compatibility
2026-04-24 09:34:27 +03:00
Ilia Mashkov
5dbf5e34c2
fix: mock next/font in tests and remove broken shared export
2026-04-23 21:01:46 +03:00
Ilia Mashkov
68d5de3716
chore: setup lefthook for pre-commit checks
2026-04-23 21:00:43 +03:00
Ilia Mashkov
1d333fd945
chore: format codebase and move SectionAccordion to entities/Section
2026-04-23 20:52:43 +03:00
Ilia Mashkov
8aff27f8ac
chore: configure biome for linting and formatting
2026-04-23 20:40:11 +03:00
Ilia Mashkov
9c139adbf5
feat: define PocketBase types and fetch client
2026-04-23 20:35:46 +03:00
Ilia Mashkov
759f579695
fix: storybook font rendering and shared fonts module
2026-04-23 20:35:32 +03:00
Ilia Mashkov
de03d21429
feat: add Storybook with component stories
...
Installs @storybook/nextjs-vite. Stories co-located with components,
grouped by layer (Shared/Entities/Widgets). Multi-variant cases use
render functions instead of one story per variant/size.
2026-04-19 09:19:17 +03:00
Ilia Mashkov
a47341ffcb
feat: add Navigation widget barrel export
2026-04-19 08:40:10 +03:00
Ilia Mashkov
cfe50069b7
feat: add MobileNav, SidebarNav, and UtilityBar widgets
...
TDD implementation of three navigation widgets: mobile overlay toggle,
fixed sidebar with IntersectionObserver-driven active section tracking,
and utility bar with contact info and CV download action.
2026-04-19 08:40:08 +03:00
Ilia Mashkov
590147adb1
feat: add experience entity (ExperienceCard) and entities barrel export
2026-04-19 08:37:24 +03:00
Ilia Mashkov
eeef679f69
feat: add project entity (ProjectMetadata, ProjectCard, DetailedProjectCard)
2026-04-19 08:37:21 +03:00
Ilia Mashkov
0fa66f275d
feat: add shared/ui and shared barrel exports; add FSD path aliases to tsconfig
2026-04-19 08:34:38 +03:00
Ilia Mashkov
ad188fcb21
feat: add TechStackBrick and TechStackGrid components to shared/ui
2026-04-19 08:27:56 +03:00
Ilia Mashkov
faf6c574d1
feat: add SectionAccordion component to shared/ui
2026-04-19 08:27:08 +03:00
Ilia Mashkov
d17104b294
feat: add Section and Container components to shared/ui
2026-04-19 08:26:26 +03:00
Ilia Mashkov
9c52889b72
fix: associate Input/Textarea labels and wire error aria-describedby
...
Uses useId() for stable IDs so label htmlFor matches input id,
and error spans are referenced via aria-describedby.
2026-04-19 08:25:07 +03:00
Ilia Mashkov
dc3bedeeec
feat: add Input and Textarea components to shared/ui
2026-04-19 08:20:29 +03:00
Ilia Mashkov
26860b27e5
feat: add Card component family to shared/ui
2026-04-19 08:19:58 +03:00
Ilia Mashkov
11e7aa9a96
feat: add Button component to shared/ui
2026-04-19 08:19:23 +03:00
Ilia Mashkov
169988906c
refactor: rename shared/ui component dirs to PascalCase
2026-04-18 23:26:14 +03:00
Ilia Mashkov
f95588381d
fix: export BadgeVariant type from Badge public API
2026-04-18 15:54:45 +03:00
Ilia Mashkov
bb9c91b4f8
feat: add Badge component to shared/ui
2026-04-18 15:53:01 +03:00
Ilia Mashkov
db2d7b78dd
fix: fix indentation, export ClassValue, add object-syntax test
2026-04-18 15:52:05 +03:00
Ilia Mashkov
f4c95d5ea6
feat: add cn utility to shared/lib
2026-04-18 15:49:24 +03:00
Ilia Mashkov
38d7a59e1e
fix: add h6 to heading selector and display:block to grain overlay
2026-04-18 15:48:29 +03:00
Ilia Mashkov
939884c95d
fix: expose all semantic color tokens in @theme inline block
2026-04-18 15:46:40 +03:00
Ilia Mashkov
3a29b99ae8
feat: transfer brutalist design tokens and configure next/font
2026-04-18 15:45:55 +03:00
Ilia Mashkov
7c00f8bb1e
chore: add $routes and @ aliases to vitest config
2026-04-18 15:41:08 +03:00
Ilia Mashkov
08071b3d27
chore: configure vitest with jsdom and layer aliases
2026-04-18 15:39:44 +03:00
Ilia Mashkov
0fdafb22f1
chore: add test infrastructure and static export config
2026-04-18 15:32:01 +03:00
Ilia Mashkov
2dfd9a81b7
chore: update .gitignore
2026-04-18 14:53:36 +03:00
Ilia Mashkov
8d0df31537
feature: initial TS + Next.js + Tailwind + ESLint setup
2026-04-18 14:52:39 +03:00