Skip to content

Commit

Permalink
style(frontend): add work experience section
Browse files Browse the repository at this point in the history
  • Loading branch information
arpitdalal committed May 8, 2024
1 parent 92d9e0d commit 1c8af3c
Show file tree
Hide file tree
Showing 13 changed files with 387 additions and 62 deletions.
8 changes: 7 additions & 1 deletion app/components/external-link.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { cn } from '#app/utils/misc.js'

interface ExternalLinkProps
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
href: string
children: React.ReactNode
className?: string
applyBaseClassName?: boolean
}

const baseClassName =
'ring-offset-background transition-colors outline-none focus-visible:ring-2 focus-within:ring-2 ring-ring ring-offset-2'
export default function ExternalLink({
href,
children,
className = 'underlined text-foreground/70',
applyBaseClassName = true,
...props
}: ExternalLinkProps) {
return (
<a
href={href}
className={className}
className={cn(applyBaseClassName && baseClassName, className)}
target="_blank"
rel="noreferrer"
{...props}
Expand Down
11 changes: 7 additions & 4 deletions app/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,23 +170,23 @@ export function Header({
>
<div className="flex items-center justify-between gap-4 md:gap-8">
<a
className="absolute -top-96 left-0 z-50 m-3 bg-primary p-3 opacity-0 transition-opacity duration-200 ease-in-out focus:top-0 focus:opacity-100"
className="absolute -top-96 left-0 z-50 m-3 bg-primary p-3 opacity-0 outline-none ring-ring ring-offset-2 ring-offset-background transition-all duration-200 ease-in-out focus-within:ring-2 focus:top-0 focus:opacity-100 focus-visible:ring-2"
// eslint-disable-next-line remix-react-routes/use-link-for-routes -- Needed because Link doesn't work here
href="#main"
>
Skip Navigation
</a>
<Link
to="/"
className="group z-10 flex items-center gap-4 overflow-clip"
className="group z-10 flex items-center gap-4 overflow-clip outline-none ring-ring ring-offset-2 ring-offset-background transition-colors focus-within:ring-2 focus-visible:ring-2"
>
<Logo className="z-10">
<LogoCircle />
<LogoSpinner />
<LogoImage />
</Logo>
<motion.span
className="underlined text-h2"
className="underlined xs:text-h2 text-h3"
style={{
opacity: textOpacity,
x: textX,
Expand All @@ -198,7 +198,10 @@ export function Header({
</Link>
<ul className="hidden items-center gap-4 md:flex md:gap-8">
<li>
<ExternalLink href="https://blog.arpitdalal.dev">
<ExternalLink
href="https://blog.arpitdalal.dev"
applyBaseClassName={false}
>
Blog
</ExternalLink>
</li>
Expand Down
4 changes: 2 additions & 2 deletions app/components/hero-highlight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const HeroHighlight = ({
}

return (
<div
<section
className={cn(
'group relative flex w-full items-center justify-center py-20',
containerClassName,
Expand Down Expand Up @@ -65,7 +65,7 @@ export const HeroHighlight = ({
<div className={cn('relative z-20', className)}>
<>{children}</>
</div>
</div>
</section>
)
}

Expand Down
36 changes: 36 additions & 0 deletions app/components/ui/badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { cva, type VariantProps } from 'class-variance-authority'
import * as React from 'react'

import { cn } from '#app/utils/misc.tsx'

const badgeVariants = cva(
'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
{
variants: {
variant: {
default:
'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
secondary:
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
destructive:
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
outline: 'text-foreground',
},
},
defaultVariants: {
variant: 'default',
},
},
)

export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}

function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
)
}

export { Badge, badgeVariants }
2 changes: 2 additions & 0 deletions app/components/ui/icons/name.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

export type IconName =
| 'arrow-left-outline'
| 'arrow-up-outline'
| 'arrow-up-right-outline'
| 'brand-github-outline'
| 'brand-linkedin-outline'
| 'brand-x-outline'
Expand Down
9 changes: 9 additions & 0 deletions app/components/ui/icons/sprite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
103 changes: 103 additions & 0 deletions app/components/work-experience.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import ExternalLink from '#app/components/external-link.js'
import { Badge } from '#app/components/ui/badge.js'
import { Icon } from '#app/components/ui/icon.js'

export type WorkExperienceCardProps = {
title: string
previousTitles?: string[]
link: string
company: string
location: string
description: string
startDate: string
endDate: string
technologies: string[]
}
export function WorkExperienceCard({
title,
previousTitles,
link,
company,
location,
description,
startDate,
endDate,
technologies,
}: WorkExperienceCardProps) {
return (
<li>
<article className="group relative grid py-8 transition-all sm:grid-cols-8 sm:gap-8 md:gap-4 lg:hover:!opacity-100 lg:group-hover/ol:opacity-50">
<div
className="absolute -inset-x-4 -inset-y-4 z-0 hidden rounded-md transition motion-reduce:transition-none lg:-inset-x-6 lg:block lg:group-hover:bg-accent/60 lg:group-hover:shadow-[inset_0_1px_0_0_rgba(148,163,184,0.1)] lg:group-hover:drop-shadow-lg"
aria-hidden
/>
<div
className="absolute inset-0 mr-4 hidden grid-cols-8 sm:grid"
aria-hidden
>
<div className="col-span-2 border-r-2" />
<div className="relative">
<div className="absolute -left-[9px] top-10 size-4 rounded-full bg-primary" />
</div>
</div>
<header
className="z-10 mb-2 mt-1 font-semibold uppercase tracking-wide text-foreground/70 sm:col-span-2 sm:pr-3 sm:text-right"
aria-label={`${startDate} ${endDate.toLowerCase() === 'present' ? 'till' : 'to'} ${endDate}`}
>
<time>
{startDate} - {endDate}
</time>
</header>
<div className="z-10 sm:col-span-6 sm:pl-3">
<h3 className="font-medium">
<ExternalLink
href={link}
className="group/link inline-flex items-baseline font-medium leading-tight"
aria-label={`${title} at ${company} (opens in a new tab)`}
>
<span
className="absolute -inset-x-4 -inset-y-2.5 hidden rounded md:-inset-x-6 md:-inset-y-4 lg:block"
aria-hidden
></span>
<span>
{title} ·{' '}
<span className="inline-block">
{company}
<Icon
name="arrow-up-right-outline"
className="ml-1 translate-y-px transition-transform group-hover/link:-translate-y-1 group-hover/link:translate-x-1 group-focus-visible/link:-translate-y-1 group-focus-visible/link:translate-x-1 motion-reduce:transition-none"
aria-hidden
/>
</span>
</span>
</ExternalLink>
</h3>
{previousTitles && previousTitles.length > 0 && (
<ol aria-label="Previous titles">
{previousTitles.map(previousTitle => (
<li key={previousTitle} className="text-sm text-foreground/90">
<Icon
name="arrow-up-outline"
arial-label={`Previous title: ${previousTitle}`}
>
{previousTitle}
</Icon>
</li>
))}
</ol>
)}
<p className="mt-1 text-foreground/70">{location}</p>
<p className="mt-2 leading-normal">{description}</p>
<ul
className="mt-4 flex flex-wrap space-x-2"
aria-label="Technologies used"
>
{technologies.map(technology => (
<Badge key={technology}>{technology}</Badge>
))}
</ul>
</div>
</article>
</li>
)
}
12 changes: 8 additions & 4 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import { withSentry } from '@sentry/remix'
import { ClientOnly } from 'remix-utils/client-only'
import { HoneypotProvider } from 'remix-utils/honeypot/react'
import ExternalLink from '#app/components/external-link.js'
import { Header, ClientHeader } from '#app/components/header.tsx'
import {
Logo,
Expand Down Expand Up @@ -190,7 +191,10 @@ function Footer() {
return (
<footer className="border-t border-foreground/40">
<div className="container flex flex-wrap justify-between gap-10 py-5">
<Link to="/" className="group z-10 flex items-center gap-4">
<Link
to="/"
className="group z-10 flex items-center gap-4 outline-none ring-ring ring-offset-2 ring-offset-background transition-colors focus-within:ring-2 focus-visible:ring-2"
>
<Logo>
<LogoCircle />
<LogoSpinner />
Expand All @@ -209,12 +213,12 @@ function Footer() {
</Link>
</li>
<li>
<a
className="underlined text-foreground/70"
<ExternalLink
href="https://blog.arpitdalal.dev"
applyBaseClassName={false}
>
Blog
</a>
</ExternalLink>
</li>
{Object.entries(headerAndFooterCommonLinks).map(([key, value]) => (
<li key={key}>
Expand Down
102 changes: 102 additions & 0 deletions app/routes/_marketing+/__data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { type IconName } from '#app/components/ui/icon'
import { type WorkExperienceCardProps } from '#app/components/work-experience.js'

type SocialLink = {
name: string
href: string
icon: IconName
}
export const socialLinks = [
{
name: 'Twitter',
href: 'https://arpit.im/x',
icon: 'brand-x-outline',
},
{
name: 'GitHub',
href: 'https://arpit.im/gh',
icon: 'brand-github-outline',
},
{
name: 'Youtube',
href: 'https://arpit.im/yt',
icon: 'brand-youtube-outline',
},
{
name: 'LinkedIn',
href: 'https://arpit.im/in',
icon: 'brand-linkedin-outline',
},
] satisfies SocialLink[]

export const workExperience = [
{
title: 'Web Developer Product Specialist',
link: 'https://points.com',
company: 'Points',
location: 'ON, Canada',
description:
'Develop production-ready storefronts for millions of users, collaborating with multiple stakeholders to formulate comprehensive plans for product development, testing, and launch.',
startDate: 'Aug 2021',
endDate: 'Present',
technologies: ['React', 'JavaScript', 'Typescript', 'Node.js', 'PHP'],
},
{
title: 'Web Developer',
link: 'https://reddingdesigns.com',
company: 'Redding Designs',
location: 'ON, Canada',
description:
'Work collaboratively with clients and in-house teams to provide fast, secure, responsive and client-acclaimed full-stack web applications for user-optimized experiences.',
startDate: 'Aug 2020',
endDate: 'Jul 2021',
technologies: [
'React',
'Typescript',
'Bootstrap',
'Node.js',
'PHP',
'WordPress',
],
},
{
title: 'Full Stack Web Developer',
link: 'https://revolution.ca',
company: 'Revolution Media',
location: 'PE, Canada',
description:
'Create robust full-stack web solutions tailored to client needs, leveraging the most suitable technology stack for optimal performance and accessibility.',
startDate: 'Jul 2019',
endDate: 'Apr 2020',
technologies: [
'React',
'Typescript',
'Tailwind CSS',
'Node.js',
'PHP',
'WordPress',
],
},
{
title: 'Full Stack Developer',
link: 'https://bigsurge.ca/',
company: 'Big Surge',
location: 'PE, Canada',
description:
'Collaborate within a dynamic team, contributing to multiple codebases in a fast-paced startup. Utilize React, Next.js, Redux, and TypeScript to craft highly responsive user interfaces.',
startDate: 'Feb 2019',
endDate: 'Jun 2019',
technologies: ['React', 'Next.js', 'Typescript', 'Node.js'],
},
{
title: 'Junior Developer',
link: 'https://www.linkedin.com/company/auberon-canada-inc/',
company: 'Auberon',
location: 'Remote, Canada',
description:
'Gained valuable experience and proficiency in HTML, CSS, React, JavaScript, and Node.js, contributing actively to projects and accelerating learning curve.',
startDate: 'Feb 2017',
endDate: 'May 2018',
technologies: ['JavaScript', 'Node.js', 'React', 'HTML', 'CSS'],
},
] satisfies WorkExperienceCardProps[]
Loading

0 comments on commit 1c8af3c

Please sign in to comment.