mirror of
https://github.com/theoludwig/theoludwig.git
synced 2026-02-20 03:09:20 +01:00
chore: migrate from ESLint/Prettier to Oxc
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
import typescriptESLint from "typescript-eslint"
|
||||
import { defineConfig } from "eslint/config"
|
||||
import config from "@repo/config-eslint"
|
||||
|
||||
export default defineConfig(...config, {
|
||||
files: ["**/*.ts", "**/*.tsx"],
|
||||
languageOptions: {
|
||||
parser: typescriptESLint.parser,
|
||||
parserOptions: {
|
||||
projectService: true,
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -23,14 +23,12 @@
|
||||
"./Layout/Section": "./src/Layout/Section/Section.tsx"
|
||||
},
|
||||
"scripts": {
|
||||
"lint:eslint": "eslint src --max-warnings 0",
|
||||
"lint:typescript": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@repo/config-tailwind": "workspace:*",
|
||||
"@repo/utils": "workspace:*",
|
||||
"@repo/i18n": "workspace:*",
|
||||
"cva": "catalog:",
|
||||
"@repo/utils": "workspace:*",
|
||||
"next": "catalog:",
|
||||
"next-intl": "catalog:",
|
||||
"next-themes": "catalog:",
|
||||
@@ -39,18 +37,15 @@
|
||||
"react-icons": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@repo/config-eslint": "workspace:*",
|
||||
"@repo/config-typescript": "workspace:*",
|
||||
"@storybook/nextjs": "catalog:",
|
||||
"@tailwindcss/postcss": "catalog:",
|
||||
"@total-typescript/ts-reset": "catalog:",
|
||||
"@types/react": "catalog:",
|
||||
"@types/react-dom": "catalog:",
|
||||
"@total-typescript/ts-reset": "catalog:",
|
||||
"storybook": "catalog:",
|
||||
"@storybook/nextjs": "catalog:",
|
||||
"eslint": "catalog:",
|
||||
"postcss": "catalog:",
|
||||
"storybook": "catalog:",
|
||||
"tailwindcss": "catalog:",
|
||||
"@tailwindcss/postcss": "catalog:",
|
||||
"typescript-eslint": "catalog:",
|
||||
"typescript": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@ import { CurriculumVitaeSection } from "./CurriculumVitaeSection.tsx"
|
||||
|
||||
export interface CurriculumVitaeEducationProps {}
|
||||
|
||||
export const CurriculumVitaeEducation: React.FC<
|
||||
CurriculumVitaeEducationProps
|
||||
> = () => {
|
||||
export const CurriculumVitaeEducation: React.FC<CurriculumVitaeEducationProps> = () => {
|
||||
const t = useTranslations()
|
||||
|
||||
const educations = [
|
||||
@@ -27,20 +25,15 @@ export const CurriculumVitaeEducation: React.FC<
|
||||
title: t("curriculum-vitae.education.iut.years.2021-2022.title"),
|
||||
courses: [
|
||||
t("curriculum-vitae.education.iut.years.2021-2022.courses.java"),
|
||||
t(
|
||||
"curriculum-vitae.education.iut.years.2021-2022.courses.systems-c",
|
||||
),
|
||||
t("curriculum-vitae.education.iut.years.2021-2022.courses.systems-c"),
|
||||
// t(
|
||||
// "curriculum-vitae.education.iut.years.2021-2022.courses.windows-forms",
|
||||
// ),
|
||||
t.rich(
|
||||
"curriculum-vitae.education.iut.years.2021-2022.courses.sql",
|
||||
{
|
||||
strong: (children) => {
|
||||
return <strong>{children}</strong>
|
||||
},
|
||||
t.rich("curriculum-vitae.education.iut.years.2021-2022.courses.sql", {
|
||||
strong: (children) => {
|
||||
return <strong>{children}</strong>
|
||||
},
|
||||
),
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -48,49 +41,35 @@ export const CurriculumVitaeEducation: React.FC<
|
||||
title: t("curriculum-vitae.education.iut.years.2022-2023.title"),
|
||||
courses: [
|
||||
t("curriculum-vitae.education.iut.years.2022-2023.courses.web"),
|
||||
t.rich(
|
||||
"curriculum-vitae.education.iut.years.2022-2023.courses.tests",
|
||||
{
|
||||
strong: (children) => {
|
||||
return <strong>{children}</strong>
|
||||
},
|
||||
t.rich("curriculum-vitae.education.iut.years.2022-2023.courses.tests", {
|
||||
strong: (children) => {
|
||||
return <strong>{children}</strong>
|
||||
},
|
||||
),
|
||||
t.rich(
|
||||
"curriculum-vitae.education.iut.years.2022-2023.courses.clean-code",
|
||||
{
|
||||
strong: (children) => {
|
||||
return <strong>{children}</strong>
|
||||
},
|
||||
}),
|
||||
t.rich("curriculum-vitae.education.iut.years.2022-2023.courses.clean-code", {
|
||||
strong: (children) => {
|
||||
return <strong>{children}</strong>
|
||||
},
|
||||
),
|
||||
}),
|
||||
// t("curriculum-vitae.education.iut.years.2022-2023.courses.sql-security"),
|
||||
t.rich(
|
||||
"curriculum-vitae.education.iut.years.2022-2023.courses.systems-c",
|
||||
{
|
||||
strong: (children) => {
|
||||
return <strong>{children}</strong>
|
||||
},
|
||||
t.rich("curriculum-vitae.education.iut.years.2022-2023.courses.systems-c", {
|
||||
strong: (children) => {
|
||||
return <strong>{children}</strong>
|
||||
},
|
||||
),
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
year: t("curriculum-vitae.education.iut.years.2023-2024.description"),
|
||||
title: t("curriculum-vitae.education.iut.years.2023-2024.title"),
|
||||
courses: [
|
||||
t.rich(
|
||||
"curriculum-vitae.education.iut.years.2023-2024.courses.web",
|
||||
{
|
||||
strong: (children) => {
|
||||
return <strong>{children}</strong>
|
||||
},
|
||||
t.rich("curriculum-vitae.education.iut.years.2023-2024.courses.web", {
|
||||
strong: (children) => {
|
||||
return <strong>{children}</strong>
|
||||
},
|
||||
),
|
||||
}),
|
||||
t("curriculum-vitae.education.iut.years.2023-2024.courses.ci-cd"),
|
||||
t(
|
||||
"curriculum-vitae.education.iut.years.2023-2024.courses.complexity-algorithms",
|
||||
),
|
||||
t("curriculum-vitae.education.iut.years.2023-2024.courses.complexity-algorithms"),
|
||||
t("curriculum-vitae.education.iut.years.2023-2024.courses.no-sql"),
|
||||
],
|
||||
},
|
||||
|
||||
@@ -4,9 +4,7 @@ import { CurriculumVitaeSection } from "./CurriculumVitaeSection.tsx"
|
||||
|
||||
export interface CurriculumVitaeInterestsProps {}
|
||||
|
||||
export const CurriculumVitaeInterests: React.FC<
|
||||
CurriculumVitaeInterestsProps
|
||||
> = () => {
|
||||
export const CurriculumVitaeInterests: React.FC<CurriculumVitaeInterestsProps> = () => {
|
||||
const t = useTranslations()
|
||||
|
||||
const interests = [
|
||||
@@ -16,22 +14,14 @@ export const CurriculumVitaeInterests: React.FC<
|
||||
},
|
||||
"link-github": (children) => {
|
||||
return (
|
||||
<a
|
||||
href="https://github.com/theoludwig"
|
||||
target="_blank"
|
||||
className="font-semibold"
|
||||
>
|
||||
<a href="https://github.com/theoludwig" target="_blank" className="font-semibold">
|
||||
{children}
|
||||
</a>
|
||||
)
|
||||
},
|
||||
"link-leon": (children) => {
|
||||
return (
|
||||
<a
|
||||
href="https://github.com/leon-ai/leon"
|
||||
target="_blank"
|
||||
className="font-semibold"
|
||||
>
|
||||
<a href="https://github.com/leon-ai/leon" target="_blank" className="font-semibold">
|
||||
{children}
|
||||
</a>
|
||||
)
|
||||
|
||||
@@ -6,9 +6,7 @@ import { Locales } from "../Layout/Header/Locales/Locales.tsx"
|
||||
|
||||
export interface CurriculumVitaeProfileProps {}
|
||||
|
||||
export const CurriculumVitaeProfile: React.FC<
|
||||
CurriculumVitaeProfileProps
|
||||
> = () => {
|
||||
export const CurriculumVitaeProfile: React.FC<CurriculumVitaeProfileProps> = () => {
|
||||
const t = useTranslations()
|
||||
|
||||
return (
|
||||
@@ -30,9 +28,7 @@ export const CurriculumVitaeProfile: React.FC<
|
||||
<h1 className="h3 my-1!">
|
||||
<strong>{t("meta.title")}</strong>
|
||||
</h1>
|
||||
<h2 className="text-muted h5 font-semibold">
|
||||
{t("curriculum-vitae.description")}
|
||||
</h2>
|
||||
<h2 className="text-muted h5 font-semibold">{t("curriculum-vitae.description")}</h2>
|
||||
<h2 className="text-muted h5">
|
||||
<BirthDate />
|
||||
</h2>
|
||||
|
||||
@@ -4,9 +4,7 @@ export interface CurriculumVitaeSectionProps extends React.PropsWithChildren {
|
||||
title: string
|
||||
}
|
||||
|
||||
export const CurriculumVitaeSection: React.FC<CurriculumVitaeSectionProps> = (
|
||||
props,
|
||||
) => {
|
||||
export const CurriculumVitaeSection: React.FC<CurriculumVitaeSectionProps> = (props) => {
|
||||
const { id, icon, title, children } = props
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
import { useTranslations } from "next-intl"
|
||||
import { FaToolbox } from "react-icons/fa"
|
||||
import {
|
||||
SKILL_CATEGORIES,
|
||||
SKILL_NAMES_BY_CATEGORY,
|
||||
} from "../Home/Skills/skills.ts"
|
||||
import { SKILL_CATEGORIES, SKILL_NAMES_BY_CATEGORY } from "../Home/Skills/skills.ts"
|
||||
import { CurriculumVitaeSection } from "./CurriculumVitaeSection.tsx"
|
||||
|
||||
export interface CurriculumVitaeSkillsProps {}
|
||||
|
||||
export const CurriculumVitaeSkills: React.FC<
|
||||
CurriculumVitaeSkillsProps
|
||||
> = () => {
|
||||
export const CurriculumVitaeSkills: React.FC<CurriculumVitaeSkillsProps> = () => {
|
||||
const t = useTranslations()
|
||||
|
||||
const skills = [
|
||||
@@ -23,11 +18,7 @@ export const CurriculumVitaeSkills: React.FC<
|
||||
}),
|
||||
{
|
||||
category: "others",
|
||||
skillNames: [
|
||||
t("fr-FR-main"),
|
||||
t("locales.en-US"),
|
||||
t("home.skills.driving-license"),
|
||||
],
|
||||
skillNames: [t("fr-FR-main"), t("locales.en-US"), t("home.skills.driving-license")],
|
||||
},
|
||||
] as const
|
||||
|
||||
|
||||
@@ -136,10 +136,7 @@ export const LinkWithIcons: Story = {
|
||||
<Button leftIcon={<FaCheck size={18} />} {...(args as ButtonLinkProps)}>
|
||||
Link Left Icon
|
||||
</Button>
|
||||
<Button
|
||||
rightIcon={<FaCheck size={18} />}
|
||||
{...(args as ButtonLinkProps)}
|
||||
>
|
||||
<Button rightIcon={<FaCheck size={18} />} {...(args as ButtonLinkProps)}>
|
||||
Link Right Icon
|
||||
</Button>
|
||||
</ButtonContainer>
|
||||
|
||||
@@ -1,32 +1,37 @@
|
||||
import { classNames } from "@repo/config-tailwind/classNames"
|
||||
import { Link as NextLink } from "@repo/i18n/routing"
|
||||
import type { VariantProps } from "cva"
|
||||
import { cva } from "cva"
|
||||
|
||||
import { Spinner } from "../Spinner/Spinner.tsx"
|
||||
import { Ripple } from "./Ripple.tsx"
|
||||
|
||||
const buttonVariants = cva({
|
||||
base: "relative inline-flex items-center justify-center overflow-hidden rounded-md text-base font-semibold transition duration-150 ease-in-out focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
||||
variants: {
|
||||
variant: {
|
||||
solid: "bg-primary hover:bg-primary/80 text-white",
|
||||
outline:
|
||||
"dark:border-primary-dark/60 dark:text-primary-dark dark:hover:border-primary-dark border-primary/60 text-primary hover:border-primary hover:bg-primary border bg-transparent hover:text-white",
|
||||
},
|
||||
size: {
|
||||
small: "h-9 rounded-md px-3",
|
||||
medium: "h-10 px-4 py-2",
|
||||
large: "h-11 rounded-md px-8",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "solid",
|
||||
size: "medium",
|
||||
},
|
||||
})
|
||||
const BUTTON_VARIANTS = ["solid", "outline"] as const
|
||||
type ButtonVariant = (typeof BUTTON_VARIANTS)[number]
|
||||
|
||||
const BUTTON_SIZES = ["small", "medium", "large"] as const
|
||||
type ButtonSize = (typeof BUTTON_SIZES)[number]
|
||||
|
||||
const buttonVariants = (options?: { variant?: ButtonVariant; size?: ButtonSize }): string => {
|
||||
const { variant = "solid", size = "medium" } = options ?? {}
|
||||
return classNames(
|
||||
"relative inline-flex items-center justify-center overflow-hidden rounded-md text-base font-semibold transition duration-150 ease-in-out focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
||||
{
|
||||
"bg-primary text-white hover:bg-primary/80": variant === "solid",
|
||||
|
||||
"border border-primary/60 bg-transparent text-primary hover:border-primary hover:bg-primary hover:text-white dark:border-primary-dark/60 dark:text-primary-dark dark:hover:border-primary-dark":
|
||||
variant === "outline",
|
||||
},
|
||||
{
|
||||
"h-9 rounded-md px-3": size === "small",
|
||||
"h-10 px-4 py-2": size === "medium",
|
||||
"h-11 rounded-md px-8": size === "large",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
interface ButtonBaseProps {
|
||||
variant?: ButtonVariant
|
||||
size?: ButtonSize
|
||||
|
||||
interface ButtonBaseProps extends VariantProps<typeof buttonVariants> {
|
||||
leftIcon?: React.ReactNode
|
||||
rightIcon?: React.ReactNode
|
||||
disabled?: boolean
|
||||
@@ -34,14 +39,10 @@ interface ButtonBaseProps extends VariantProps<typeof buttonVariants> {
|
||||
}
|
||||
|
||||
interface ButtonElementProps extends React.ComponentPropsWithoutRef<"button"> {}
|
||||
interface LinkElementProps extends React.ComponentPropsWithoutRef<
|
||||
typeof NextLink
|
||||
> {}
|
||||
interface LinkElementProps extends React.ComponentPropsWithoutRef<typeof NextLink> {}
|
||||
|
||||
export type ButtonLinkProps = ButtonBaseProps &
|
||||
LinkElementProps & { href: string }
|
||||
export type ButtonButtonProps = ButtonBaseProps &
|
||||
ButtonElementProps & { href?: never }
|
||||
export type ButtonLinkProps = ButtonBaseProps & LinkElementProps & { href: string }
|
||||
export type ButtonButtonProps = ButtonBaseProps & ButtonElementProps & { href?: never }
|
||||
|
||||
export type ButtonProps = ButtonButtonProps | ButtonLinkProps
|
||||
|
||||
@@ -51,18 +52,13 @@ export type ButtonProps = ButtonButtonProps | ButtonLinkProps
|
||||
* @returns
|
||||
*/
|
||||
export const Button: React.FC<ButtonProps> = (props) => {
|
||||
const rippleColor =
|
||||
props.variant === "outline" ? "rgb(30, 64, 175)" : "rgb(229, 231, 235)"
|
||||
const rippleColor = props.variant === "outline" ? "rgb(30, 64, 175)" : "rgb(229, 231, 235)"
|
||||
|
||||
if (typeof props.href === "string") {
|
||||
const { variant, size, leftIcon, rightIcon, className, children, ...rest } =
|
||||
props
|
||||
const { variant, size, leftIcon, rightIcon, className, children, ...rest } = props
|
||||
|
||||
return (
|
||||
<NextLink
|
||||
className={classNames(buttonVariants({ variant, size }), className)}
|
||||
{...rest}
|
||||
>
|
||||
<NextLink className={classNames(buttonVariants({ variant, size }), className)} {...rest}>
|
||||
{leftIcon != null ? <span className="mr-2">{leftIcon}</span> : null}
|
||||
<span>{children}</span>
|
||||
{rightIcon != null ? <span className="ml-2">{rightIcon}</span> : null}
|
||||
@@ -98,13 +94,9 @@ export const Button: React.FC<ButtonProps> = (props) => {
|
||||
disabled={isDisabled}
|
||||
{...rest}
|
||||
>
|
||||
{leftIconElement != null ? (
|
||||
<span className="mr-2">{leftIconElement}</span>
|
||||
) : null}
|
||||
{leftIconElement != null ? <span className="mr-2">{leftIconElement}</span> : null}
|
||||
<span>{children}</span>
|
||||
{rightIcon != null && !isLoading ? (
|
||||
<span className="ml-2">{rightIcon}</span>
|
||||
) : null}
|
||||
{rightIcon != null && !isLoading ? <span className="ml-2">{rightIcon}</span> : null}
|
||||
|
||||
<Ripple color={rippleColor} />
|
||||
</button>
|
||||
|
||||
@@ -17,7 +17,7 @@ export const Link: React.FC<LinkProps> = (props) => {
|
||||
return (
|
||||
<NextLink
|
||||
className={classNames(
|
||||
"text-primary dark:text-primary-dark inline-flex items-center gap-1 font-semibold hover:underline focus:rounded-md focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none",
|
||||
"inline-flex items-center gap-1 font-semibold text-primary hover:underline focus:rounded-md focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none dark:text-primary-dark",
|
||||
className,
|
||||
)}
|
||||
target={target}
|
||||
@@ -25,11 +25,7 @@ export const Link: React.FC<LinkProps> = (props) => {
|
||||
>
|
||||
{children}
|
||||
|
||||
{target === "_blank" && isExternal ? (
|
||||
<FiExternalLink size={16} strokeWidth={2.5} />
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{target === "_blank" && isExternal ? <FiExternalLink size={16} strokeWidth={2.5} /> : <></>}
|
||||
</NextLink>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export const Spinner: React.FC<SpinnerProps> = (props) => {
|
||||
height: size,
|
||||
}}
|
||||
className={classNames(
|
||||
"text-primary dark:text-primary-dark flex animate-spin rounded-full border-2 border-current border-t-transparent",
|
||||
"flex animate-spin rounded-full border-2 border-current border-t-transparent text-primary dark:text-primary-dark",
|
||||
className,
|
||||
)}
|
||||
role="status"
|
||||
|
||||
@@ -67,8 +67,7 @@ export const Variants: Story = {
|
||||
</Typography>
|
||||
|
||||
<Typography as="p" variant="text1">
|
||||
<abbr title="Cascading Style Sheets">CSS</abbr> (Abbreviation or
|
||||
Acronym)
|
||||
<abbr title="Cascading Style Sheets">CSS</abbr> (Abbreviation or Acronym)
|
||||
</Typography>
|
||||
|
||||
<Typography as="p" variant="text1">
|
||||
@@ -76,8 +75,8 @@ export const Variants: Story = {
|
||||
</Typography>
|
||||
|
||||
<Typography as="p" variant="text1">
|
||||
A <dfn id="def-validator">validator</dfn> is a program that checks for
|
||||
syntax errors in code or documents. (Definition)
|
||||
A <dfn id="def-validator">validator</dfn> is a program that checks for syntax errors in
|
||||
code or documents. (Definition)
|
||||
</Typography>
|
||||
|
||||
<Typography as="blockquote" variant="text1">
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
import { classNames } from "@repo/config-tailwind/classNames"
|
||||
import type { VariantProps } from "cva"
|
||||
import { cva } from "cva"
|
||||
|
||||
const typographyVariants = cva({
|
||||
variants: {
|
||||
variant: {
|
||||
h1: "text-primary dark:text-primary-dark text-4xl font-semibold",
|
||||
h2: "text-primary dark:text-primary-dark text-3xl font-semibold",
|
||||
h3: "text-primary dark:text-primary-dark text-2xl font-semibold",
|
||||
h4: "text-primary dark:text-primary-dark text-xl font-semibold",
|
||||
h5: "text-primary dark:text-primary-dark text-xl font-medium",
|
||||
h6: "text-primary dark:text-primary-dark text-lg font-medium",
|
||||
text1: "text-base break-words",
|
||||
text2: "text-sm break-words",
|
||||
},
|
||||
},
|
||||
})
|
||||
const TYPOGRAPHY_VARIANTS = ["h1", "h2", "h3", "h4", "h5", "h6", "text1", "text2"] as const
|
||||
type TypographyVariant = (typeof TYPOGRAPHY_VARIANTS)[number]
|
||||
|
||||
const typographyVariants = (options?: { variant?: TypographyVariant }): string => {
|
||||
const { variant = "text1" } = options ?? {}
|
||||
return classNames({
|
||||
"text-4xl font-semibold text-primary dark:text-primary-dark": variant === "h1",
|
||||
"text-3xl font-semibold text-primary dark:text-primary-dark": variant === "h2",
|
||||
"text-2xl font-semibold text-primary dark:text-primary-dark": variant === "h3",
|
||||
"text-xl font-semibold text-primary dark:text-primary-dark": variant === "h4",
|
||||
"text-xl font-medium text-primary dark:text-primary-dark": variant === "h5",
|
||||
"text-lg font-medium text-primary dark:text-primary-dark": variant === "h6",
|
||||
"text-base wrap-break-word": variant === "text1",
|
||||
"text-sm wrap-break-word": variant === "text2",
|
||||
})
|
||||
}
|
||||
|
||||
export type TypographyProps<Component extends React.ElementType = "p"> = {
|
||||
as?: Component
|
||||
} & React.ComponentPropsWithoutRef<Component> &
|
||||
VariantProps<typeof typographyVariants>
|
||||
} & React.ComponentPropsWithoutRef<Component> & {
|
||||
variant?: TypographyVariant
|
||||
}
|
||||
|
||||
/**
|
||||
* Typography and styling abstraction component used to ensure consistency and standardize text throughout your application.
|
||||
@@ -35,10 +36,7 @@ export const Typography = <Component extends React.ElementType = "p">(
|
||||
const ComponentAs = as
|
||||
|
||||
return (
|
||||
<ComponentAs
|
||||
className={classNames(typographyVariants({ variant }), className)}
|
||||
{...rest}
|
||||
>
|
||||
<ComponentAs className={classNames(typographyVariants({ variant }), className)} {...rest}>
|
||||
{children}
|
||||
</ComponentAs>
|
||||
)
|
||||
|
||||
@@ -17,8 +17,7 @@ export const ErrorNotFound: React.FC<ErrorNotFoundProps> = () => {
|
||||
</Typography>
|
||||
|
||||
<Typography variant="text1" as="p" className="mt-4">
|
||||
{t("errors.page-doesnt-exist")}{" "}
|
||||
<Link href="/">{t("errors.return-to-home-page")}</Link>
|
||||
{t("errors.page-doesnt-exist")} <Link href="/">{t("errors.return-to-home-page")}</Link>
|
||||
</Typography>
|
||||
</Section>
|
||||
</MainLayout>
|
||||
|
||||
@@ -8,7 +8,7 @@ export const AboutDescription: React.FC<AboutDescriptionProps> = () => {
|
||||
const t = useTranslations()
|
||||
|
||||
return (
|
||||
<div className="dark:text-gray-lighter my-6 max-w-md text-center text-black">
|
||||
<div className="my-6 max-w-md text-center text-black dark:text-gray-lighter">
|
||||
<Typography as="p" variant="text1" className="my-6">
|
||||
{t.rich("home.about.description", {
|
||||
strong: (children) => {
|
||||
|
||||
@@ -9,10 +9,8 @@ export const AboutItem: React.FC<AboutItemProps> = (props) => {
|
||||
|
||||
return (
|
||||
<li className="flex items-center justify-between sm:justify-start">
|
||||
<strong className="w-24 text-sm text-black lg:w-32 dark:text-white">
|
||||
{label}
|
||||
</strong>
|
||||
<span className="dark:text-gray-lighter block text-sm font-normal text-black">
|
||||
<strong className="w-24 text-sm text-black lg:w-32 dark:text-white">{label}</strong>
|
||||
<span className="block text-sm font-normal text-black dark:text-gray-lighter">
|
||||
{link != null ? (
|
||||
<a className="hover:underline" href={link}>
|
||||
{value}
|
||||
|
||||
@@ -9,14 +9,8 @@ export const AboutList: React.FC<AboutListProps> = () => {
|
||||
|
||||
return (
|
||||
<ul className="my-6 list-none space-y-3">
|
||||
<AboutItem
|
||||
label={t("home.about.pronouns.label")}
|
||||
value={t("home.about.pronouns.value")}
|
||||
/>
|
||||
<AboutItem
|
||||
label={t("home.about.birth-date.label")}
|
||||
value={<BirthDate />}
|
||||
/>
|
||||
<AboutItem label={t("home.about.pronouns.label")} value={t("home.about.pronouns.value")} />
|
||||
<AboutItem label={t("home.about.birth-date.label")} value={<BirthDate />} />
|
||||
<AboutItem
|
||||
label={t("home.about.nationality.label")}
|
||||
value={t("home.about.nationality.value")}
|
||||
|
||||
@@ -8,13 +8,7 @@ export const AboutLogo: React.FC<AboutLogoProps> = () => {
|
||||
|
||||
return (
|
||||
<div className="max-h-[370px] max-w-[370px] px-2 py-6">
|
||||
<Image
|
||||
src="/images/logo.webp"
|
||||
alt={t("meta.title")}
|
||||
width={800}
|
||||
height={800}
|
||||
priority
|
||||
/>
|
||||
<Image src="/images/logo.webp" alt={t("meta.title")} width={800} height={800} priority />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,10 +7,7 @@ export const Icon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => {
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
className={classNames(
|
||||
"size-8 fill-current text-black dark:text-white",
|
||||
className,
|
||||
)}
|
||||
className={classNames("size-8 fill-current text-black dark:text-white", className)}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -24,24 +24,15 @@ export const SocialMediaList: React.FC<SocialMediaListProps> = () => {
|
||||
<NPMIcon />
|
||||
</SocialMediaItem>
|
||||
|
||||
<SocialMediaItem
|
||||
link="https://twitter.com/theoludwig_"
|
||||
ariaLabel="X/Twitter"
|
||||
>
|
||||
<SocialMediaItem link="https://twitter.com/theoludwig_" ariaLabel="X/Twitter">
|
||||
<TwitterIcon />
|
||||
</SocialMediaItem>
|
||||
|
||||
<SocialMediaItem
|
||||
link="https://www.youtube.com/@theo_ludwig"
|
||||
ariaLabel="YouTube"
|
||||
>
|
||||
<SocialMediaItem link="https://www.youtube.com/@theo_ludwig" ariaLabel="YouTube">
|
||||
<YouTubeIcon />
|
||||
</SocialMediaItem>
|
||||
|
||||
<SocialMediaItem
|
||||
link="https://www.twitch.tv/theoludwig"
|
||||
ariaLabel="Twitch"
|
||||
>
|
||||
<SocialMediaItem link="https://www.twitch.tv/theoludwig" ariaLabel="Twitch">
|
||||
<TwitchIcon />
|
||||
</SocialMediaItem>
|
||||
|
||||
|
||||
@@ -14,11 +14,7 @@ export const InterestItem: React.FC<InterestItemProps> = (props) => {
|
||||
{title}
|
||||
</Typography>
|
||||
|
||||
<Typography
|
||||
as="p"
|
||||
variant="text1"
|
||||
className="dark:text-gray-lighter my-2 text-black"
|
||||
>
|
||||
<Typography as="p" variant="text1" className="my-2 text-black dark:text-gray-lighter">
|
||||
{description}
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
@@ -2,11 +2,7 @@ import { GIT_REPO_LINK } from "@repo/utils/constants"
|
||||
import { useTranslations } from "next-intl"
|
||||
import { FaGit, FaMicrochip } from "react-icons/fa"
|
||||
import { Link } from "../../Design/Link/Link.tsx"
|
||||
import {
|
||||
Section,
|
||||
SectionContent,
|
||||
SectionTitle,
|
||||
} from "../../Layout/Section/Section.tsx"
|
||||
import { Section, SectionContent, SectionTitle } from "../../Layout/Section/Section.tsx"
|
||||
import { InterestItem } from "./InterestItem.tsx"
|
||||
|
||||
export interface InterestsProps {}
|
||||
@@ -59,13 +55,7 @@ export const Interests: React.FC<InterestsProps> = () => {
|
||||
<SectionContent shadowContainer>
|
||||
<div className="max-w-full">
|
||||
{items.map((item) => {
|
||||
return (
|
||||
<InterestItem
|
||||
key={item.id}
|
||||
title={item.title}
|
||||
description={item.description}
|
||||
/>
|
||||
)
|
||||
return <InterestItem key={item.id} title={item.title} description={item.description} />
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -74,7 +64,7 @@ export const Interests: React.FC<InterestsProps> = () => {
|
||||
{items.map((item) => {
|
||||
return (
|
||||
<li className="m-2 size-8" key={item.id} title={item.title}>
|
||||
<item.Icon className="text-primary dark:text-primary-dark block size-full" />
|
||||
<item.Icon className="block size-full text-primary dark:text-primary-dark" />
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { useTranslations } from "next-intl"
|
||||
import {
|
||||
Section,
|
||||
SectionDescription,
|
||||
SectionTitle,
|
||||
} from "../../Layout/Section/Section.tsx"
|
||||
import { Section, SectionDescription, SectionTitle } from "../../Layout/Section/Section.tsx"
|
||||
import { Repository } from "./Repository.tsx"
|
||||
|
||||
export interface OpenSourceProps {}
|
||||
@@ -14,9 +10,7 @@ export const OpenSource: React.FC<OpenSourceProps> = () => {
|
||||
return (
|
||||
<Section verticalSpacing horizontalSpacing id="open-source">
|
||||
<SectionTitle>{t("home.open-source.title")}</SectionTitle>
|
||||
<SectionDescription>
|
||||
{t("home.open-source.description")}
|
||||
</SectionDescription>
|
||||
<SectionDescription>{t("home.open-source.description")}</SectionDescription>
|
||||
|
||||
<div className="flex max-w-full flex-col items-center">
|
||||
<ul className="grid list-none grid-cols-1 gap-6 md:w-10/12 md:grid-cols-2">
|
||||
|
||||
@@ -20,9 +20,7 @@ export const Repository: React.FC<RepositoryProps> = (props) => {
|
||||
>
|
||||
<Typography as="h3" variant="text1" className="flex items-center">
|
||||
<GitHubIcon className="mr-2 h-6" />
|
||||
<span className="text-primary dark:text-primary-dark font-semibold">
|
||||
{name}
|
||||
</span>
|
||||
<span className="font-semibold text-primary dark:text-primary-dark">{name}</span>
|
||||
</Typography>
|
||||
<p className="mt-4">{description}</p>
|
||||
</SectionContent>
|
||||
|
||||
@@ -26,10 +26,7 @@ export const PortfolioItem: React.FC<PortfolioItemProps> = (props) => {
|
||||
href={link}
|
||||
aria-label={title}
|
||||
>
|
||||
<SectionContent
|
||||
className="relative cursor-pointer items-center p-0 sm:p-0"
|
||||
shadowContainer
|
||||
>
|
||||
<SectionContent className="relative cursor-pointer items-center p-0 sm:p-0" shadowContainer>
|
||||
<div className="flex justify-center">
|
||||
<Image
|
||||
className="size-[300px] rounded-xl transition-opacity duration-500 group-hover:opacity-15 dark:group-hover:opacity-5"
|
||||
|
||||
@@ -13,19 +13,14 @@ export const Footer: React.FC<FooterProps> = (props) => {
|
||||
const t = useTranslations()
|
||||
|
||||
return (
|
||||
<footer className="bg-background dark:bg-background-dark border-gray-darker dark:border-gray-darker-dark flex flex-col items-center justify-center border-t-2 p-6 text-lg">
|
||||
<footer className="flex flex-col items-center justify-center border-t-2 border-gray-darker bg-background p-6 text-lg dark:border-gray-darker-dark dark:bg-background-dark">
|
||||
<p>
|
||||
<Link href="/">{t("meta.title")}</Link> |{" "}
|
||||
{t("footer.all-rights-reserved")}
|
||||
<Link href="/">{t("meta.title")}</Link> | {t("footer.all-rights-reserved")}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Version{" "}
|
||||
<Link
|
||||
href={`${GIT_REPO_LINK}/releases/tag/v${version}`}
|
||||
target="_blank"
|
||||
isExternal={false}
|
||||
>
|
||||
<Link href={`${GIT_REPO_LINK}/releases/tag/v${version}`} target="_blank" isExternal={false}>
|
||||
{version}
|
||||
</Link>
|
||||
</p>
|
||||
|
||||
@@ -10,7 +10,7 @@ export const Header: React.FC<HeaderProps> = () => {
|
||||
const t = useTranslations()
|
||||
|
||||
return (
|
||||
<header className="bg-background dark:bg-background-dark border-gray-darker dark:border-gray-darker-dark sticky top-0 z-50 flex w-full justify-between gap-4 border-b-2 px-6 py-2">
|
||||
<header className="sticky top-0 z-50 flex w-full justify-between gap-4 border-b-2 border-gray-darker bg-background px-6 py-2 dark:border-gray-darker-dark dark:bg-background-dark">
|
||||
<h1>
|
||||
<Link href="/" className="flex items-center justify-center">
|
||||
<Image
|
||||
@@ -21,9 +21,7 @@ export const Header: React.FC<HeaderProps> = () => {
|
||||
alt={`${t("meta.title")} Logo`}
|
||||
priority
|
||||
/>
|
||||
<strong className="ml-1 hidden sm:block sm:text-xl">
|
||||
{t("meta.title")}
|
||||
</strong>
|
||||
<strong className="ml-1 hidden sm:block sm:text-xl">{t("meta.title")}</strong>
|
||||
</Link>
|
||||
</h1>
|
||||
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
export const Arrow: React.FC = () => {
|
||||
return (
|
||||
<svg
|
||||
width="12"
|
||||
height="8"
|
||||
viewBox="0 0 12 8"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg width="12" height="8" viewBox="0 0 12 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
className="fill-current text-black dark:text-white"
|
||||
d="M9.8024 0.292969L5.61855 4.58597L1.43469 0.292969L0.0566406 1.70697L5.61855 7.41397L11.1805 1.70697L9.8024 0.292969Z"
|
||||
|
||||
@@ -17,11 +17,7 @@ export const Locales: React.FC<LocalesProps> = () => {
|
||||
const pathname = usePathname()
|
||||
const localeCurrent = useLocale()
|
||||
|
||||
const {
|
||||
value: isVisibleMenu,
|
||||
toggle: toggleMenu,
|
||||
setFalse: hideMenu,
|
||||
} = useBoolean()
|
||||
const { value: isVisibleMenu, toggle: toggleMenu, setFalse: hideMenu } = useBoolean()
|
||||
const languageClickRef = useRef<HTMLButtonElement | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -47,18 +43,14 @@ export const Locales: React.FC<LocalesProps> = () => {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<button
|
||||
ref={languageClickRef}
|
||||
className="flex items-center"
|
||||
onClick={toggleMenu}
|
||||
>
|
||||
<button ref={languageClickRef} className="flex items-center" onClick={toggleMenu}>
|
||||
<LocaleFlag locale={localeCurrent} />
|
||||
<Arrow />
|
||||
</button>
|
||||
|
||||
<ul
|
||||
className={classNames(
|
||||
"shadow-lightFlag dark:shadow-darkFlag bg-background dark:bg-background-dark absolute top-14 z-10 mt-2 flex w-32 list-none flex-col items-center justify-center rounded-lg p-0",
|
||||
"absolute top-14 z-10 mt-2 flex w-32 list-none flex-col items-center justify-center rounded-lg bg-background p-0 shadow-lightFlag dark:bg-background-dark dark:shadow-darkFlag",
|
||||
{ hidden: !isVisibleMenu },
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
import { classNames } from "@repo/config-tailwind/classNames"
|
||||
import type { Theme } from "@repo/utils/constants"
|
||||
import { THEME_DEFAULT } from "@repo/utils/constants"
|
||||
import {
|
||||
ThemeProvider as NextThemeProvider,
|
||||
useTheme as useNextTheme,
|
||||
} from "next-themes"
|
||||
import { ThemeProvider as NextThemeProvider, useTheme as useNextTheme } from "next-themes"
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
export interface ThemeProviderProps extends React.PropsWithChildren {
|
||||
@@ -38,7 +35,6 @@ export const useTheme = (): UseThemeOutput => {
|
||||
const [isMounted, setIsMounted] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
setIsMounted(true)
|
||||
}, [])
|
||||
|
||||
@@ -73,9 +69,7 @@ export const SwitchTheme: React.FC<SwitchThemeProps> = () => {
|
||||
},
|
||||
)}
|
||||
>
|
||||
<span className="relative flex size-[10px] items-center justify-center">
|
||||
🌜
|
||||
</span>
|
||||
<span className="relative flex size-[10px] items-center justify-center">🌜</span>
|
||||
</div>
|
||||
<div
|
||||
className={classNames(
|
||||
@@ -86,9 +80,7 @@ export const SwitchTheme: React.FC<SwitchThemeProps> = () => {
|
||||
},
|
||||
)}
|
||||
>
|
||||
<span className="relative flex size-[10px] items-center justify-center">
|
||||
🌞
|
||||
</span>
|
||||
<span className="relative flex size-[10px] items-center justify-center">🌞</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -9,8 +9,7 @@ export const RevealFade: React.FC<RevealFadeProps> = (props) => {
|
||||
|
||||
const htmlElement = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
const className =
|
||||
"opacity-100 visible translate-y-0 transition-all duration-700 ease-in-out"
|
||||
const className = "opacity-100 visible translate-y-0 transition-all duration-700 ease-in-out"
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new window.IntersectionObserver(
|
||||
|
||||
@@ -10,12 +10,7 @@ export interface SectionProps extends React.ComponentPropsWithoutRef<"section">
|
||||
}
|
||||
|
||||
export const Section: React.FC<SectionProps> = (props) => {
|
||||
const {
|
||||
className,
|
||||
verticalSpacing = false,
|
||||
horizontalSpacing = false,
|
||||
...rest
|
||||
} = props
|
||||
const { className, verticalSpacing = false, horizontalSpacing = false, ...rest } = props
|
||||
|
||||
return (
|
||||
<section
|
||||
@@ -48,9 +43,7 @@ export const SectionTitle: React.FC<SectionTitleProps> = (props) => {
|
||||
|
||||
export interface SectionDescriptionProps extends TypographyProps<"p"> {}
|
||||
|
||||
export const SectionDescription: React.FC<SectionDescriptionProps> = (
|
||||
props,
|
||||
) => {
|
||||
export const SectionDescription: React.FC<SectionDescriptionProps> = (props) => {
|
||||
const { className, ...rest } = props
|
||||
|
||||
return (
|
||||
@@ -75,7 +68,7 @@ export const SectionContent: React.FC<SectionContentProps> = (props) => {
|
||||
className={classNames(
|
||||
"size-full max-w-full px-6 py-4 break-words sm:px-16",
|
||||
{
|
||||
"shadow-light dark:shadow-dark max-w-full rounded-2xl border border-solid border-black":
|
||||
"max-w-full rounded-2xl border border-solid border-black shadow-light dark:shadow-dark":
|
||||
shadowContainer,
|
||||
},
|
||||
className,
|
||||
|
||||
Reference in New Issue
Block a user