Fix stuff for mobile

This commit is contained in:
Gabriel Brown 2024-09-17 14:28:50 -05:00
parent 42cf2e6796
commit 071e5e4a12
10 changed files with 397 additions and 24 deletions

View File

@ -5,15 +5,16 @@ const AboutMe = () => {
<h2 className="text-3xl font-semibold mb-4">About Me</h2> <h2 className="text-3xl font-semibold mb-4">About Me</h2>
<p className="w-5/6 md:w-1/2 lg:w-1/3 mx-auto leading-relaxed indent-5"> <p className="w-5/6 md:w-1/2 lg:w-1/3 mx-auto leading-relaxed indent-5">
I am a recent USM graduate with a Bachelor&apos;s degree in Computer Science. I am a recent USM graduate with a Bachelor&apos;s degree in Computer Science.
Despite my short time in Software Engineering, I have an extensive portfolio Despite my short time in software development, I have an extensive portfolio
of Web Applications & broad range of knowledge & experience in many different of web applications & a broad range of knowledge & experience in many different
stacks & technologies. You can also be sure that any project I create will be stacks & technologies. You can also be sure that any project I create will be
completely self-hosted on my Fedora Server! completely self-hosted on my Fedora Server using technologies such as Docker,
Caddy, Node, PHP-FPM, PostgreSQL, MySQL, & more!
</p> </p>
<p className="w-5/6 md:w-1/2 lg:w-1/3 mx-auto leading-relaxed indent-5 mt-1"> <p className="w-5/6 md:w-1/2 lg:w-1/3 mx-auto leading-relaxed indent-5 mt-1">
I am a big fan of TypeScript and I have been I am a huge fan of TypeScript and I have been exclusively using it in my web
exclusively using it in my web projects for the past year with frameworks such as projects for the past year with frameworks such as Next.js, React, & React
Next.js & React Native. I also have experience building applications & backends Native. I also have experience building applications & backends
using the technologies listed below! using the technologies listed below!
</p> </p>
</section> </section>

View File

@ -10,7 +10,7 @@ import {
ChartContainer, ChartContainer,
ChartTooltip, ChartTooltip,
ChartTooltipContent, ChartTooltipContent,
} from "~/components/ui/chart" } from "~/components/ui/chart2"
const chartData = [ const chartData = [
{ technology: "Linux", proficiency: 95 }, { technology: "Linux", proficiency: 95 },
@ -44,8 +44,8 @@ export default function Component() {
data={chartData} data={chartData}
layout="vertical" layout="vertical"
margin={{ margin={{
left: 60, left: 0,
right: 60, right: 0,
top: 0, top: 0,
bottom: 0, bottom: 0,
}} }}
@ -58,6 +58,7 @@ export default function Component() {
axisLine={false} axisLine={false}
tickLine={false} tickLine={false}
fontSize={12} fontSize={12}
width={1000}
/> />
<YAxis <YAxis
dataKey="technology" dataKey="technology"

View File

@ -10,17 +10,17 @@ import { FaGithub } from "react-icons/fa";
export default function Fuse() { export default function Fuse() {
return ( return (
<section className="my-6 flex flex-col items-center justify-center m-auto"> <section className="my-6 flex flex-col items-center justify-center m-auto">
<Accordion type="single" collapsible className="w-1/3"> <Accordion type="single" collapsible className="w-5/6 md:w-1/3">
<AccordionItem value="item-1"> <AccordionItem value="item-1">
<AccordionTrigger> <AccordionTrigger>
<div className="flex flex-row mx-auto"> <div className="flex flex-row">
<h1 className="text-2xl font-semibold text-center mx-auto"> <h1 className="md:text-2xl font-semibold text-center">
Fuse (React Native, Next.js, & PostgreSQL) Fuse (React Native, Next.js, & PostgreSQL)
</h1> </h1>
<Link href="https://git.gbrown.org/gib/fuse_expo" <Link href="https://git.gbrown.org/gib/fuse_expo"
className="my-auto" className="my-auto"
> >
< FaGithub className="my-auto ml-2" size={22} /> < FaGithub className="my-auto ml-2 mr-4" size={22} />
</Link> </Link>
</div> </div>
</AccordionTrigger> </AccordionTrigger>

View File

@ -10,11 +10,11 @@ import { FaGithub } from "react-icons/fa";
export default function LazyPrimeagen() { export default function LazyPrimeagen() {
return ( return (
<section className="my-6 flex flex-col items-center justify-center m-auto"> <section className="my-6 flex flex-col items-center justify-center m-auto">
<Accordion type="single" collapsible className="w-1/3"> <Accordion type="single" collapsible className="w-5/6 md:w-1/3">
<AccordionItem value="item-1"> <AccordionItem value="item-1">
<AccordionTrigger> <AccordionTrigger>
<div className="flex flex-row mx-auto"> <div className="flex flex-row mx-auto">
<h1 className="text-2xl font-semibold text-center mx-auto"> <h1 className="md:text-2xl font-semibold text-center mx-auto">
Lazy Primeagen Neovim Config (Lua) Lazy Primeagen Neovim Config (Lua)
</h1> </h1>
<Link href="https://github.com/gibbyb/Lazy_Primeagen" <Link href="https://github.com/gibbyb/Lazy_Primeagen"

View File

@ -10,11 +10,11 @@ import { FaGithub } from "react-icons/fa";
export default function Sunhat() { export default function Sunhat() {
return ( return (
<section className="my-6 flex flex-col items-center justify-center m-auto"> <section className="my-6 flex flex-col items-center justify-center m-auto">
<Accordion type="single" collapsible className="w-1/3"> <Accordion type="single" collapsible className="w-5/6 md:w-1/3">
<AccordionItem value="item-1"> <AccordionItem value="item-1">
<AccordionTrigger> <AccordionTrigger>
<div className="flex flex-row mx-auto"> <div className="flex flex-row mx-auto">
<h1 className="text-2xl font-semibold text-center mx-auto">Sunhat (Bash)</h1> <h1 className="md:text-2xl font-semibold text-center mx-auto">Sunhat (Bash)</h1>
<Link href="https://git.gbrown.org/gib/sunhat" <Link href="https://git.gbrown.org/gib/sunhat"
className="my-auto" className="my-auto"
> >

View File

@ -10,10 +10,10 @@ import { FaGithub } from "react-icons/fa";
export default function TechTracker() { export default function TechTracker() {
return ( return (
<section className="my-6 flex flex-col items-center justify-center m-auto"> <section className="my-6 flex flex-col items-center justify-center m-auto">
<Accordion type="single" collapsible className="w-1/3"> <Accordion type="single" collapsible className="w-5/6 md:w-1/3">
<AccordionItem value="item-1"> <AccordionItem value="item-1">
<AccordionTrigger> <AccordionTrigger>
<h1 className="text-2xl font-semibold text-center mx-auto">Tech Tracker (Next.js, Swift & MySQL)</h1> <h1 className="md:text-2xl font-semibold text-center mx-auto">Tech Tracker (Next.js, Swift & MySQL)</h1>
</AccordionTrigger> </AccordionTrigger>
<AccordionContent> <AccordionContent>
<div className="flex flex-col"> <div className="flex flex-col">

View File

@ -10,11 +10,11 @@ import { FaGithub } from "react-icons/fa";
export default function TenantPortal() { export default function TenantPortal() {
return ( return (
<section className="my-6 flex flex-col items-center justify-center m-auto"> <section className="my-6 flex flex-col items-center justify-center m-auto">
<Accordion type="single" collapsible className="w-1/3"> <Accordion type="single" collapsible className="w-5/6 md:w-1/3">
<AccordionItem value="item-1"> <AccordionItem value="item-1">
<AccordionTrigger> <AccordionTrigger>
<div className="flex flex-row mx-auto"> <div className="flex flex-row mx-auto">
<h1 className="text-2xl font-semibold text-center mx-auto"> <h1 className="md:text-2xl font-semibold text-center mx-auto">
Tenant Portal (Next.js & PostgreSQL) Tenant Portal (Next.js & PostgreSQL)
</h1> </h1>
<Link href="https://git.gbrown.org/gib/rent_portal" <Link href="https://git.gbrown.org/gib/rent_portal"

View File

@ -10,11 +10,11 @@ import { FaGithub } from "react-icons/fa";
export default function WiredWorld() { export default function WiredWorld() {
return ( return (
<section className="my-6 flex flex-col items-center justify-center m-auto"> <section className="my-6 flex flex-col items-center justify-center m-auto">
<Accordion type="single" collapsible className="w-1/3"> <Accordion type="single" collapsible className="w-5/6 md:w-1/3">
<AccordionItem value="item-1"> <AccordionItem value="item-1">
<AccordionTrigger> <AccordionTrigger>
<div className="flex flex-row mx-auto"> <div className="flex flex-row mx-auto">
<h1 className="text-2xl font-semibold text-center mx-auto"> <h1 className="md:text-2xl font-semibold text-center mx-auto">
Wired World (PHP & MySQL) Wired World (PHP & MySQL)
</h1> </h1>
<Link href="https://github.com/gibbyb/WiredWorld" <Link href="https://github.com/gibbyb/WiredWorld"

View File

@ -49,7 +49,7 @@ const ChartContainer = React.forwardRef<
} }
>(({ id, className, children, config, ...props }, ref) => { >(({ id, className, children, config, ...props }, ref) => {
const uniqueId = React.useId() const uniqueId = React.useId()
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`
return ( return (
<ChartContext.Provider value={{ config }}> <ChartContext.Provider value={{ config }}>

View File

@ -0,0 +1,371 @@
"use client"
import * as React from "react"
import * as RechartsPrimitive from "recharts"
import {
NameType,
Payload,
ValueType,
} from "recharts/types/component/DefaultTooltipContent"
import { cn } from "~/lib/utils"
// Format: { THEME_NAME: CSS_SELECTOR }
const THEMES = { light: "", dark: ".dark" } as const
export type ChartConfig = {
[k in string]: {
label?: React.ReactNode
icon?: React.ComponentType
} & (
| { color?: string; theme?: never }
| { color?: never; theme: Record<keyof typeof THEMES, string> }
)
}
type ChartContextProps = {
config: ChartConfig
}
const ChartContext = React.createContext<ChartContextProps | null>(null)
function useChart() {
const context = React.useContext(ChartContext)
if (!context) {
throw new Error("useChart must be used within a <ChartContainer />")
}
return context
}
const ChartContainer = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div"> & {
config: ChartConfig
children: React.ComponentProps<
typeof RechartsPrimitive.ResponsiveContainer
>["children"]
}
>(({ id, className, children, config, ...props }, ref) => {
const uniqueId = React.useId()
const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`
return (
<ChartContext.Provider value={{ config }}>
<div
data-chart={chartId}
ref={ref}
className={cn(
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
className
)}
{...props}
>
<ChartStyle id={chartId} config={config} />
<RechartsPrimitive.ResponsiveContainer>
{children}
</RechartsPrimitive.ResponsiveContainer>
</div>
</ChartContext.Provider>
)
})
ChartContainer.displayName = "Chart"
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
const colorConfig = Object.entries(config).filter(
([_, config]) => config.theme ?? config.color
)
if (!colorConfig.length) {
return null
}
return (
<style
dangerouslySetInnerHTML={{
__html: Object.entries(THEMES)
.map(
([theme, prefix]) => `
${prefix} [data-chart=${id}] {
${colorConfig
.map(([key, itemConfig]) => {
const color =
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??
itemConfig.color
return color ? ` --color-${key}: ${color};` : null
})
.join("\n")}
}
`
)
.join("\n"),
}}
/>
)
}
const ChartTooltip = RechartsPrimitive.Tooltip
const ChartTooltipContent = React.forwardRef<
HTMLDivElement,
React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
React.ComponentProps<"div"> & {
hideLabel?: boolean
hideIndicator?: boolean
indicator?: "line" | "dot" | "dashed"
nameKey?: string
labelKey?: string
}
>(
(
{
active,
payload,
className,
indicator = "dot",
hideLabel = false,
hideIndicator = false,
label,
labelFormatter,
labelClassName,
formatter,
color,
nameKey,
labelKey,
},
ref
) => {
const { config } = useChart()
const tooltipLabel = React.useMemo(() => {
if (hideLabel || !payload?.length) {
return null
}
const [item] = payload
const key = `${labelKey ?? item.dataKey ?? item.name ?? "value"}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)
const value =
!labelKey && typeof label === "string"
? config[label as keyof typeof config]?.label ?? label
: itemConfig?.label
if (labelFormatter) {
return (
<div className={cn("font-medium", labelClassName)}>
{labelFormatter(value, payload)}
</div>
)
}
if (!value) {
return null
}
return <div className={cn("font-medium", labelClassName)}>{value}</div>
}, [
label,
labelFormatter,
payload,
hideLabel,
labelClassName,
config,
labelKey,
])
if (!active || !payload?.length) {
return null
}
const nestLabel = payload.length === 1 && indicator !== "dot"
return (
<div
ref={ref}
className={cn(
"grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
className
)}
>
{!nestLabel ? tooltipLabel : null}
<div className="grid gap-1.5">
{payload.map((item, index) => {
const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)
const indicatorColor = color ?? item.payload.fill ?? item.color
return (
<div
key={item.dataKey}
className={cn(
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
indicator === "dot" && "items-center"
)}
>
{formatter && item?.value !== undefined && item.name ? (
formatter(item.value, item.name, item, index, item.payload)
) : (
<>
{itemConfig?.icon ? (
<itemConfig.icon />
) : (
!hideIndicator && (
<div
className={cn(
"shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]",
{
"h-2.5 w-2.5": indicator === "dot",
"w-1": indicator === "line",
"w-0 border-[1.5px] border-dashed bg-transparent":
indicator === "dashed",
"my-0.5": nestLabel && indicator === "dashed",
}
)}
style={
{
// @ts-expect-error - Not my code
"--color-bg": indicatorColor,
"--color-border": indicatorColor,
} as React.CSSProperties
}
/>
)
)}
<div
className={cn(
"flex flex-1 justify-between leading-none",
nestLabel ? "items-end" : "items-center"
)}
>
<div className="grid gap-1.5">
{nestLabel ? tooltipLabel : null}
<span className="text-muted-foreground">
{itemConfig?.label ?? item.name}
</span>
</div>
{item.value && (
<span className="font-mono font-medium tabular-nums text-foreground">
{item.value.toLocaleString()}
</span>
)}
</div>
</>
)}
</div>
)
})}
</div>
</div>
)
}
)
ChartTooltipContent.displayName = "ChartTooltip"
const ChartLegend = RechartsPrimitive.Legend
const ChartLegendContent = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div"> &
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
hideIcon?: boolean
nameKey?: string
}
>(
(
{ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey },
ref
) => {
const { config } = useChart()
if (!payload?.length) {
return null
}
return (
<div
ref={ref}
className={cn(
"flex items-center justify-center gap-4",
verticalAlign === "top" ? "pb-3" : "pt-3",
className
)}
>
{payload.map((item) => {
const key = `${nameKey || item.dataKey || "value"}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)
return (
<div
key={item.value}
className={cn(
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
)}
>
{itemConfig?.icon && !hideIcon ? (
<itemConfig.icon />
) : (
<div
className="h-2 w-2 shrink-0 rounded-[2px]"
style={{
backgroundColor: item.color,
}}
/>
)}
{itemConfig?.label}
</div>
)
})}
</div>
)
}
)
ChartLegendContent.displayName = "ChartLegend"
// Helper to extract item config from a payload.
function getPayloadConfigFromPayload(
config: ChartConfig,
payload: unknown,
key: string
) {
if (typeof payload !== "object" || payload === null) {
return undefined
}
const payloadPayload =
"payload" in payload &&
typeof payload.payload === "object" &&
payload.payload !== null
? payload.payload
: undefined
let configLabelKey: string = key
if (
key in payload &&
typeof payload[key as keyof typeof payload] === "string"
) {
configLabelKey = payload[key as keyof typeof payload] as string
} else if (
payloadPayload &&
key in payloadPayload &&
typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
) {
configLabelKey = payloadPayload[
key as keyof typeof payloadPayload
] as string
}
return configLabelKey in config
? config[configLabelKey]
: config[key as keyof typeof config]
}
export {
ChartContainer,
ChartTooltip,
ChartTooltipContent,
ChartLegend,
ChartLegendContent,
ChartStyle,
}