fix: merge conflicts

This commit is contained in:
Danilo Cesa 2025-07-24 23:25:40 +08:00
parent b664ee6071
commit 1d99937849
64 changed files with 4479 additions and 1072 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

6
.dockerignore Normal file
View File

@ -0,0 +1,6 @@
**/target
**/dist
LICENSES
LICENSE
temp
README.md

2
.gitignore vendored
View File

@ -5,3 +5,5 @@
# These are backup files generated by rustfmt
**/*.rs.bk
/node_modules

489
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,14 @@
[package]
name = "dx-portfolio"
version = "0.1.0"
authors = ["Danilo Cesa <dev.github@dan.dcesa.cc>"]
authors = ["Danilo Cesa <dev@dan.dcesa.cc>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dioxus = { version = "0.6.0", features = ["router", "fullstack"] }
dioxus = { version = "0.6.3", features = ["router", "fullstack"] }
#dioxus-logger = {version = "0.6.3" }
[features]
default = ["web"]

View File

@ -3,7 +3,7 @@
[web.app]
# HTML title tag content
title = "dx-portfolio"
title = "Dan Portfolio"
# include `assets` in web platform
[web.resource]

33
Dockerfile Normal file
View File

@ -0,0 +1,33 @@
FROM rust:1 AS chef
RUN cargo install cargo-chef
WORKDIR /app
FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM chef AS builder
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json
COPY . .
# Install `dx`
RUN curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
RUN cargo binstall dioxus-cli --root /.cargo -y --force
ENV PATH="/.cargo/bin:$PATH"
# Create the final bundle folder. Bundle always executes in release mode with optimizations enabled
RUN dx bundle --platform web
FROM chef AS runtime
COPY --from=builder /app/target/dx/dx-portfolio/release/web/ /usr/local/app
# set our port and make sure to listen for all connections
ENV PORT=8080
ENV IP=0.0.0.0
# expose the port 8080
EXPOSE 8080
WORKDIR /usr/local/app
ENTRYPOINT [ "/usr/local/app/server" ]

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
assets/favicon/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
assets/images/aws-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
assets/images/css-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/images/d3js-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
assets/images/gcp-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
assets/images/git-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
assets/images/html-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
assets/images/js.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
assets/images/ovh-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
assets/images/php.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
assets/images/rust-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
assets/images/sass-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
assets/images/sql-logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

0
assets/main.js Normal file
View File

View File

@ -0,0 +1,89 @@
.experience-card {
background: var(--main);
border: 1px solid var(--border);
border-radius: 15px;
padding: 25px;
margin: 0 0 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
display: flex;
flex-direction: column;
}
.experience-card:hover {
border-color: var(--border-hover);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
transform: translateY(-2px);
}
.experience-avatar {
width: 48px;
height: 48px;
background: #64748b;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.experience-avatar-inner {
width: 32px;
height: 32px;
background: rgba(255, 255, 255, 0.3);
border-radius: 8px;
}
.experience-skills {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 20px;
}
.skill-chip {
/* width: 24px; */
padding: 2px;
height: 24px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
font-weight: bold;
color: white;
border: 1px solid var(--border);
transition: all 0.2s ease;
cursor: pointer;
}
.skill-chip:hover {
transform: scale(1.1);
border-color: var(--border-hover);
}
@media (min-width: 1024px) {
.experience-item {
padding: 0 60px; /* Add padding to bring cards closer to center */
}
.experience-card-container {
width: calc(
50% - 30px
) !important; /* Reduce width to bring closer to center */
}
.timeline-spacer {
flex: 0 0 20% !important; /* Reduce spacer size from 50% to 20% */
}
.timeline-dot {
left: 50% !important;
transform: translateX(-50%) !important;
}
.timeline-line {
left: 50% !important;
transform: translateX(-50%) !important;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -31,8 +31,8 @@
--code-operator-light: #016464;
--link-dark: #2563eb;
--link-light: #3b82f6;
--dark-0-60: rgba(0, 0, 0, .6);
--light-0-60: rgba(255, 255, 255, .6);
--dark-0-60: rgba(0, 0, 0, 0.6);
--light-0-60: rgba(255, 255, 255, 0.6);
--text-f: "Inter";
--title-f: "Inter";
overflow-y: scroll;
@ -62,12 +62,16 @@
--code-function: var(--code-function-light);
--code-constant: var(--code-constant-light);
--code-operator: var(--code-operator-light);
--link: var(--link-dark)
--link: var(--link-dark);
}
.content .mb6t29 {
display: flex;
flex-direction: column;
flex: 1;
padding: 0;
.card.d1441skb {
background:
linear-gradient(
90deg,
var(--main) 0%,
var(--main) 60%,
var(--main-60) 100%
),
no-repeat right 40% / 40% var(--bg-img);
}

View File

@ -1,4 +1,4 @@
@media (min-width: 640px) {
/* @media (min-width: 640px) {
.container {
max-width:640px
}
@ -26,7 +26,11 @@
.container {
max-width:1536px
}
<<<<<<< HEAD
}
=======
} */
>>>>>>> 6ac0b89 (feature: initial portfolio template)
/*
@media (min-width: 640px) {

View File

@ -10,7 +10,11 @@
z-index: 10;
padding: 0 10px;
height: 50px;
background-color:var(--main)
background-color: var(--main);
}
.nav-menu .jdc7ud:hover {
background-color: var(--main-hover);
}
.nav-menu-item .jdc7ud {
@ -24,12 +28,12 @@
}
.nav-menu-item-label .jdc7ud {
margin-left:10px
margin-left: 10px;
}
.nav-menu-item .jdc7ud:hover {
/* .nav-menu-item .jdc7ud:hover {
background-color:var(--main-hover)
}
} */
.nav-menu-mobile .jdc7ud {
z-index: -1;
@ -41,52 +45,261 @@
top: 51px;
transform: translateY(-100vh);
transition-property: transform opacity;
transition: .4s ease;
opacity:0
transition: 0.4s ease;
opacity: 0;
}
.nav-menu-mobile-open .jdc7ud {
opacity: 1;
transform: translateY(0)
transform: translateY(0);
}
.nav-bar-mobile-btn {
width: 36px;
height:36px
height: 36px;
}
.nav-bar-mobile-btn:before, .nav-bar-mobile-btn:after {
.nav-bar-mobile-btn:before,
.nav-bar-mobile-btn:after {
content: "";
display: block;
height: 1px;
width: 20px;
background-color: var(--secondary-text);
transition:transform .2s ease
transition: transform 0.2s ease;
}
.nav-bar-mobile-btn:hover:before, .nav-bar-mobile-btn:hover:after {
background-color:auto
.nav-bar-mobile-btn:hover:before,
.nav-bar-mobile-btn:hover:after {
background-color: auto;
}
.nav-bar-mobile-btn:before {
transform:translateY(-5px) rotate(0)
transform: translateY(-5px) rotate(0);
}
.nav-bar-mobile-btn:after {
transform:translateY(4px) rotate(0)
transform: translateY(4px) rotate(0);
}
.nav-bar-mobile-btn-expanded:before {
transform:translateY(2px) rotate(45deg)
transform: translateY(2px) rotate(45deg);
}
.nav-bar-mobile-btn-expanded:after {
transform:translateY(0) rotate(-45deg)
transform: translateY(0) rotate(-45deg);
}
@media (max-width: 950px) {
.nav-menu-item-label .jdc7ud {
display:none
display: none;
}
}
/* Dropdown Menu Styles */
.dropdown:hover .dropdown-content {
display: block;
}
.dropdown-content {
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
/* Bottom Sheet Menu Styles */
.quick-menu-button {
position: fixed;
bottom: 2rem;
left: 50%;
transform: translateX(-50%);
z-index: 106;
display: flex;
align-items: center;
justify-content: space-between;
background: linear-gradient(to right, #60a5fa, #2563eb);
padding: 0.75rem 1.25rem;
border-radius: 1.75rem;
box-shadow:
0 10px 25px -3px rgba(0, 0, 0, 0.1),
0 4px 6px -2px rgba(0, 0, 0, 0.05);
color: white;
font-size: 1rem;
white-space: nowrap;
cursor: pointer;
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
border: none;
}
.quick-menu-button:hover {
box-shadow:
0 20px 35px -10px rgba(0, 0, 0, 0.2),
0 10px 10px -5px rgba(0, 0, 0, 0.04);
transform: translateX(-50%) scale(1.05);
}
.quick-menu-hamburger {
display: flex;
align-items: center;
width: 0.75rem;
height: 0.75rem;
margin-right: 1.25rem;
}
.quick-menu-hamburger-line {
width: 100%;
height: 1px;
background: white;
position: relative;
box-shadow:
0 4px 0 white,
0 -4px 0 white;
}
.bottom-sheet-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.3);
z-index: 100;
transition: opacity 0.3s ease;
}
.bottom-sheet-menu {
position: fixed;
bottom: 0;
left: 0;
right: 0;
width: 100%;
background: white;
border-top-left-radius: 1.25rem;
border-top-right-radius: 1.25rem;
box-shadow: 0px -9px 50px -30px black;
z-index: 105;
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
font-family:
"Montserrat",
-apple-system,
BlinkMacSystemFont,
sans-serif;
}
.bottom-sheet-menu.hidden {
transform: translateY(100%);
}
.bottom-sheet-menu.visible {
transform: translateY(0);
}
.menu-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 1.25rem;
border-bottom: 2px solid #f3f4f6;
}
.menu-handle::after {
content: "";
width: 2px;
height: 0.625rem;
background: #1f2937;
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
}
.menu-title {
font-size: 1.125rem;
font-weight: bold;
color: #1f2937;
}
.menu-close {
display: flex;
align-items: center;
justify-content: center;
width: 1.5rem;
height: 1.5rem;
background: #4b5563;
border-radius: 50%;
cursor: pointer;
border: none;
}
.menu-close-icon {
width: 1rem;
height: 2px;
background: white;
position: relative;
transform: rotate(45deg);
}
.menu-close-icon::before {
content: "";
width: 2px;
height: 1rem;
background: white;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.menu-links {
display: flex;
padding: 0.75rem 1rem;
font-weight: bold;
overflow-x: auto;
border-bottom: 2px solid #f3f4f6;
}
.menu-link {
flex: 1 1 auto;
padding: 0.75rem 0.5rem;
color: #1f2937;
text-decoration: none;
text-align: center;
white-space: nowrap;
border-radius: 0.375rem;
transition: background-color 0.15s ease;
}
.menu-link:hover {
background-color: #f9fafb;
}
.menu-contact {
display: flex;
padding: 0.5rem;
padding-bottom: 1rem;
}
.menu-contact-item {
flex: 1 1 33.333333%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0.75rem;
margin: 0 0.25rem;
border-radius: 0.5rem;
background: #f3f4f6;
color: #2563eb;
text-decoration: none;
font-size: 0.875rem;
font-weight: bold;
transition: background-color 0.15s ease;
}
.menu-contact-item:hover {
background-color: #e5e7eb;
}
.menu-contact-icon {
width: 1.5rem;
height: 1.5rem;
margin-bottom: 0.25rem;
fill: currentColor;
}

822
assets/styling/tailwind.css Normal file
View File

@ -0,0 +1,822 @@
/*! tailwindcss v4.1.7 | MIT License | https://tailwindcss.com */
@layer properties;
@layer theme, base, components, utilities;
@layer theme {
:root, :host {
--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
"Courier New", monospace;
--spacing: 0.25rem;
--text-sm: 0.875rem;
--text-sm--line-height: calc(1.25 / 0.875);
--font-weight-extralight: 200;
--font-weight-light: 300;
--font-weight-medium: 500;
--font-weight-bold: 700;
--font-weight-black: 900;
--tracking-wider: 0.05em;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
--default-transition-duration: 150ms;
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
--default-font-family: var(--font-sans);
--default-mono-font-family: var(--font-mono);
}
}
@layer base {
*, ::after, ::before, ::backdrop, ::file-selector-button {
box-sizing: border-box;
margin: 0;
padding: 0;
border: 0 solid;
}
html, :host {
line-height: 1.5;
-webkit-text-size-adjust: 100%;
tab-size: 4;
font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
font-feature-settings: var(--default-font-feature-settings, normal);
font-variation-settings: var(--default-font-variation-settings, normal);
-webkit-tap-highlight-color: transparent;
}
hr {
height: 0;
color: inherit;
border-top-width: 1px;
}
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
h1, h2, h3, h4, h5, h6 {
font-size: inherit;
font-weight: inherit;
}
a {
color: inherit;
-webkit-text-decoration: inherit;
text-decoration: inherit;
}
b, strong {
font-weight: bolder;
}
code, kbd, samp, pre {
font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
font-feature-settings: var(--default-mono-font-feature-settings, normal);
font-variation-settings: var(--default-mono-font-variation-settings, normal);
font-size: 1em;
}
small {
font-size: 80%;
}
sub, sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
table {
text-indent: 0;
border-color: inherit;
border-collapse: collapse;
}
:-moz-focusring {
outline: auto;
}
progress {
vertical-align: baseline;
}
summary {
display: list-item;
}
ol, ul, menu {
list-style: none;
}
img, svg, video, canvas, audio, iframe, embed, object {
display: block;
vertical-align: middle;
}
img, video {
max-width: 100%;
height: auto;
}
button, input, select, optgroup, textarea, ::file-selector-button {
font: inherit;
font-feature-settings: inherit;
font-variation-settings: inherit;
letter-spacing: inherit;
color: inherit;
border-radius: 0;
background-color: transparent;
opacity: 1;
}
:where(select:is([multiple], [size])) optgroup {
font-weight: bolder;
}
:where(select:is([multiple], [size])) optgroup option {
padding-inline-start: 20px;
}
::file-selector-button {
margin-inline-end: 4px;
}
::placeholder {
opacity: 1;
}
@supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {
::placeholder {
color: currentcolor;
@supports (color: color-mix(in lab, red, red)) {
color: color-mix(in oklab, currentcolor 50%, transparent);
}
}
}
textarea {
resize: vertical;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-date-and-time-value {
min-height: 1lh;
text-align: inherit;
}
::-webkit-datetime-edit {
display: inline-flex;
}
::-webkit-datetime-edit-fields-wrapper {
padding: 0;
}
::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {
padding-block: 0;
}
:-moz-ui-invalid {
box-shadow: none;
}
button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {
appearance: button;
}
::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
height: auto;
}
[hidden]:where(:not([hidden="until-found"])) {
display: none !important;
}
}
@layer utilities {
.visible {
visibility: visible;
}
.absolute {
position: absolute;
}
.relative {
position: relative;
}
.top-0 {
top: calc(var(--spacing) * 0);
}
.bottom-0 {
bottom: calc(var(--spacing) * 0);
}
.container {
width: 100%;
@media (width >= 40rem) {
max-width: 40rem;
}
@media (width >= 48rem) {
max-width: 48rem;
}
@media (width >= 64rem) {
max-width: 64rem;
}
@media (width >= 80rem) {
max-width: 80rem;
}
@media (width >= 96rem) {
max-width: 96rem;
}
}
.m-\[2\.5px\] {
margin: 2.5px;
}
.my-\[10px\] {
margin-block: 10px;
}
.mt-5 {
margin-top: calc(var(--spacing) * 5);
}
.mt-10 {
margin-top: calc(var(--spacing) * 10);
}
.mb-7 {
margin-bottom: calc(var(--spacing) * 7);
}
.ml-0 {
margin-left: calc(var(--spacing) * 0);
}
.ml-2 {
margin-left: calc(var(--spacing) * 2);
}
.line-clamp-3 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}
.block {
display: block;
}
.contents {
display: contents;
}
.flex {
display: flex;
}
.grid {
display: grid;
}
.hidden {
display: none;
}
.inline-block {
display: inline-block;
}
.inline-flex {
display: inline-flex;
}
.h-\[1px\] {
height: 1px;
}
.h-full {
height: 100%;
}
.w-\[0\.5px\] {
width: 0.5px;
}
.w-\[20px\] {
width: 20px;
}
.w-auto {
width: auto;
}
.w-full {
width: 100%;
}
.flex-1 {
flex: 1;
}
.transform {
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
}
.cursor-pointer {
cursor: pointer;
}
.grid-cols-1 {
grid-template-columns: repeat(1, minmax(0, 1fr));
}
.flex-col {
flex-direction: column;
}
.flex-row {
flex-direction: row;
}
.flex-row-reverse {
flex-direction: row-reverse;
}
.flex-wrap {
flex-wrap: wrap;
}
.content-center {
align-content: center;
}
.items-center {
align-items: center;
}
.items-start {
align-items: flex-start;
}
.items-stretch {
align-items: stretch;
}
.justify-between {
justify-content: space-between;
}
.justify-center {
justify-content: center;
}
.gap-1 {
gap: calc(var(--spacing) * 1);
}
.gap-2 {
gap: calc(var(--spacing) * 2);
}
.gap-3 {
gap: calc(var(--spacing) * 3);
}
.gap-5 {
gap: calc(var(--spacing) * 5);
}
.gap-7 {
gap: calc(var(--spacing) * 7);
}
.self-center {
align-self: center;
}
.self-stretch {
align-self: stretch;
}
.overflow-hidden {
overflow: hidden;
}
.rounded {
border-radius: 0.25rem;
}
.rounded-\[15px\] {
border-radius: 15px;
}
.rounded-\[20px\] {
border-radius: 20px;
}
.rounded-lg {
border-radius: var(--radius-lg);
}
.rounded-md {
border-radius: var(--radius-md);
}
.border {
border-style: var(--tw-border-style);
border-width: 1px;
}
.border-1 {
border-style: var(--tw-border-style);
border-width: 1px;
}
.border-\[1px\] {
border-style: var(--tw-border-style);
border-width: 1px;
}
.border-none {
--tw-border-style: none;
border-style: none;
}
.border-solid {
--tw-border-style: solid;
border-style: solid;
}
.border-\[var\(--border\)\] {
border-color: var(--border);
}
.border-transparent {
border-color: transparent;
}
.bg-\[var\(--border\)\] {
background-color: var(--border);
}
.bg-\[var\(--main\)\] {
background-color: var(--main);
}
.bg-\[var\(--main-hover\)\] {
background-color: var(--main-hover);
}
.bg-transparent {
background-color: transparent;
}
.p-5 {
padding: calc(var(--spacing) * 5);
}
.p-15 {
padding: calc(var(--spacing) * 15);
}
.px-2 {
padding-inline: calc(var(--spacing) * 2);
}
.px-4 {
padding-inline: calc(var(--spacing) * 4);
}
.px-\[15px\] {
padding-inline: 15px;
}
.px-\[20px\] {
padding-inline: 20px;
}
.py-2 {
padding-block: calc(var(--spacing) * 2);
}
.py-4 {
padding-block: calc(var(--spacing) * 4);
}
.py-\[5px\] {
padding-block: 5px;
}
.py-\[10px\] {
padding-block: 10px;
}
.text-center {
text-align: center;
}
.text-sm {
font-size: var(--text-sm);
line-height: var(--tw-leading, var(--text-sm--line-height));
}
.text-\[0\.9em\] {
font-size: 0.9em;
}
.text-\[1\.2em\] {
font-size: 1.2em;
}
.text-\[1\.15em\] {
font-size: 1.15em;
}
.font-\[var\(--title-f\)\] {
--tw-font-weight: var(--title-f);
font-weight: var(--title-f);
}
.font-black {
--tw-font-weight: var(--font-weight-black);
font-weight: var(--font-weight-black);
}
.font-bold {
--tw-font-weight: var(--font-weight-bold);
font-weight: var(--font-weight-bold);
}
.font-extralight {
--tw-font-weight: var(--font-weight-extralight);
font-weight: var(--font-weight-extralight);
}
.font-light {
--tw-font-weight: var(--font-weight-light);
font-weight: var(--font-weight-light);
}
.font-medium {
--tw-font-weight: var(--font-weight-medium);
font-weight: var(--font-weight-medium);
}
.tracking-\[4px\] {
--tw-tracking: 4px;
letter-spacing: 4px;
}
.tracking-wider {
--tw-tracking: var(--tracking-wider);
letter-spacing: var(--tracking-wider);
}
.text-ellipsis {
text-overflow: ellipsis;
}
.whitespace-nowrap {
white-space: nowrap;
}
.\!text-\[var\(--secondary-text\)\] {
color: var(--secondary-text) !important;
}
.text-\[inherit\] {
color: inherit;
}
.text-\[var\(--main-close\)\] {
color: var(--main-close);
}
.text-\[var\(--secondary-text\)\] {
color: var(--secondary-text);
}
.text-\[var\(--tertiary-text\)\] {
color: var(--tertiary-text);
}
.text-\[var\(--text\)\] {
color: var(--text);
}
.text-inherit {
color: inherit;
}
.grayscale-65 {
--tw-grayscale: grayscale(65%);
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
}
.transition {
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, visibility, content-visibility, overlay, pointer-events;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
transition-duration: var(--tw-duration, var(--default-transition-duration));
}
.duration-300 {
--tw-duration: 300ms;
transition-duration: 300ms;
}
.duration-\[150ms\] {
--tw-duration: 150ms;
transition-duration: 150ms;
}
.hover\:z-5 {
&:hover {
@media (hover: hover) {
z-index: 5;
}
}
}
.hover\:border-\[var\(--border-hover\)\] {
&:hover {
@media (hover: hover) {
border-color: var(--border-hover);
}
}
}
.hover\:bg-\[color\:var\(--main-hover\)\] {
&:hover {
@media (hover: hover) {
background-color: var(--main-hover);
}
}
}
.hover\:bg-\[var\(--main-hover\)\] {
&:hover {
@media (hover: hover) {
background-color: var(--main-hover);
}
}
}
.hover\:grayscale-0 {
&:hover {
@media (hover: hover) {
--tw-grayscale: grayscale(0%);
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
}
}
}
.sm\:flex-row {
@media (width >= 40rem) {
flex-direction: row;
}
}
.sm\:items-center {
@media (width >= 40rem) {
align-items: center;
}
}
.sm\:gap-5 {
@media (width >= 40rem) {
gap: calc(var(--spacing) * 5);
}
}
.sm\:px-4 {
@media (width >= 40rem) {
padding-inline: calc(var(--spacing) * 4);
}
}
.sm\:py-8 {
@media (width >= 40rem) {
padding-block: calc(var(--spacing) * 8);
}
}
.sm\:text-\[3em\] {
@media (width >= 40rem) {
font-size: 3em;
}
}
.md\:ml-\[20px\] {
@media (width >= 48rem) {
margin-left: 20px;
}
}
.md\:flex {
@media (width >= 48rem) {
display: flex;
}
}
.md\:hidden {
@media (width >= 48rem) {
display: none;
}
}
.md\:inline {
@media (width >= 48rem) {
display: inline;
}
}
.md\:flex-1 {
@media (width >= 48rem) {
flex: 1;
}
}
.md\:grid-cols-2 {
@media (width >= 48rem) {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
.md\:flex-col {
@media (width >= 48rem) {
flex-direction: column;
}
}
.md\:flex-row {
@media (width >= 48rem) {
flex-direction: row;
}
}
.md\:items-start {
@media (width >= 48rem) {
align-items: flex-start;
}
}
.md\:justify-start {
@media (width >= 48rem) {
justify-content: flex-start;
}
}
.md\:gap-0 {
@media (width >= 48rem) {
gap: calc(var(--spacing) * 0);
}
}
.md\:gap-1 {
@media (width >= 48rem) {
gap: calc(var(--spacing) * 1);
}
}
.md\:gap-3 {
@media (width >= 48rem) {
gap: calc(var(--spacing) * 3);
}
}
.md\:px-6 {
@media (width >= 48rem) {
padding-inline: calc(var(--spacing) * 6);
}
}
.md\:py-12 {
@media (width >= 48rem) {
padding-block: calc(var(--spacing) * 12);
}
}
.md\:text-left {
@media (width >= 48rem) {
text-align: left;
}
}
.md\:text-\[3\.5em\] {
@media (width >= 48rem) {
font-size: 3.5em;
}
}
.lg\:flex {
@media (width >= 64rem) {
display: flex;
}
}
.lg\:inline {
@media (width >= 64rem) {
display: inline;
}
}
.lg\:w-auto {
@media (width >= 64rem) {
width: auto;
}
}
.lg\:grid-cols-3 {
@media (width >= 64rem) {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
.lg\:flex-row {
@media (width >= 64rem) {
flex-direction: row;
}
}
.lg\:items-center {
@media (width >= 64rem) {
align-items: center;
}
}
.lg\:gap-5 {
@media (width >= 64rem) {
gap: calc(var(--spacing) * 5);
}
}
.lg\:text-\[4em\] {
@media (width >= 64rem) {
font-size: 4em;
}
}
}
@property --tw-rotate-x {
syntax: "*";
inherits: false;
}
@property --tw-rotate-y {
syntax: "*";
inherits: false;
}
@property --tw-rotate-z {
syntax: "*";
inherits: false;
}
@property --tw-skew-x {
syntax: "*";
inherits: false;
}
@property --tw-skew-y {
syntax: "*";
inherits: false;
}
@property --tw-border-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-font-weight {
syntax: "*";
inherits: false;
}
@property --tw-tracking {
syntax: "*";
inherits: false;
}
@property --tw-blur {
syntax: "*";
inherits: false;
}
@property --tw-brightness {
syntax: "*";
inherits: false;
}
@property --tw-contrast {
syntax: "*";
inherits: false;
}
@property --tw-grayscale {
syntax: "*";
inherits: false;
}
@property --tw-hue-rotate {
syntax: "*";
inherits: false;
}
@property --tw-invert {
syntax: "*";
inherits: false;
}
@property --tw-opacity {
syntax: "*";
inherits: false;
}
@property --tw-saturate {
syntax: "*";
inherits: false;
}
@property --tw-sepia {
syntax: "*";
inherits: false;
}
@property --tw-drop-shadow {
syntax: "*";
inherits: false;
}
@property --tw-drop-shadow-color {
syntax: "*";
inherits: false;
}
@property --tw-drop-shadow-alpha {
syntax: "<percentage>";
inherits: false;
initial-value: 100%;
}
@property --tw-drop-shadow-size {
syntax: "*";
inherits: false;
}
@property --tw-duration {
syntax: "*";
inherits: false;
}
@layer properties {
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
*, ::before, ::after, ::backdrop {
--tw-rotate-x: initial;
--tw-rotate-y: initial;
--tw-rotate-z: initial;
--tw-skew-x: initial;
--tw-skew-y: initial;
--tw-border-style: solid;
--tw-font-weight: initial;
--tw-tracking: initial;
--tw-blur: initial;
--tw-brightness: initial;
--tw-contrast: initial;
--tw-grayscale: initial;
--tw-hue-rotate: initial;
--tw-invert: initial;
--tw-opacity: initial;
--tw-saturate: initial;
--tw-sepia: initial;
--tw-drop-shadow: initial;
--tw-drop-shadow-color: initial;
--tw-drop-shadow-alpha: 100%;
--tw-drop-shadow-size: initial;
--tw-duration: initial;
}
}
}

View File

@ -1,4 +1,3 @@
@import "tailwindcss";
@tailwind base;
@tailwind components;
@tailwind utilities;
@source "./src/**/*.{rs,html,css}";
@source "./assets/**/*.{css,png,jpeg,jpg}";

389
package-lock.json generated
View File

@ -1,12 +1,14 @@
{
"name": "dx-portfolio",
"name": "portfolio-dx",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"@tailwindcss/cli": "^4.1.7",
"tailwindcss": "^4.1.7"
"autoprefixer": "^10.4.21",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.10"
}
},
"node_modules/@ampproject/remapping": {
@ -35,17 +37,13 @@
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
"version": "0.3.12",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
"integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
"license": "MIT",
"dependencies": {
"@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/resolve-uri": {
@ -57,25 +55,16 @@
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
"integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"version": "0.3.29",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
"integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
@ -378,27 +367,27 @@
}
},
"node_modules/@tailwindcss/cli": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/cli/-/cli-4.1.7.tgz",
"integrity": "sha512-hJNjpov/UiJc9ZWH4j/eEQxqklADrD/71s+t8Y0wbyQVAwtLkSp+MeC/sHTb03X+28rfbe0fRXkiBsf73/IwPg==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/cli/-/cli-4.1.11.tgz",
"integrity": "sha512-7RAFOrVaXCFz5ooEG36Kbh+sMJiI2j4+Ozp71smgjnLfBRu7DTfoq8DsTvzse2/6nDeo2M3vS/FGaxfDgr3rtQ==",
"license": "MIT",
"dependencies": {
"@parcel/watcher": "^2.5.1",
"@tailwindcss/node": "4.1.7",
"@tailwindcss/oxide": "4.1.7",
"@tailwindcss/node": "4.1.11",
"@tailwindcss/oxide": "4.1.11",
"enhanced-resolve": "^5.18.1",
"mri": "^1.2.0",
"picocolors": "^1.1.1",
"tailwindcss": "4.1.7"
"tailwindcss": "4.1.11"
},
"bin": {
"tailwindcss": "dist/index.mjs"
}
},
"node_modules/@tailwindcss/node": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.7.tgz",
"integrity": "sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz",
"integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==",
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.3.0",
@ -407,13 +396,13 @@
"lightningcss": "1.30.1",
"magic-string": "^0.30.17",
"source-map-js": "^1.2.1",
"tailwindcss": "4.1.7"
"tailwindcss": "4.1.11"
}
},
"node_modules/@tailwindcss/oxide": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.7.tgz",
"integrity": "sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz",
"integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@ -424,24 +413,24 @@
"node": ">= 10"
},
"optionalDependencies": {
"@tailwindcss/oxide-android-arm64": "4.1.7",
"@tailwindcss/oxide-darwin-arm64": "4.1.7",
"@tailwindcss/oxide-darwin-x64": "4.1.7",
"@tailwindcss/oxide-freebsd-x64": "4.1.7",
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.7",
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.7",
"@tailwindcss/oxide-linux-arm64-musl": "4.1.7",
"@tailwindcss/oxide-linux-x64-gnu": "4.1.7",
"@tailwindcss/oxide-linux-x64-musl": "4.1.7",
"@tailwindcss/oxide-wasm32-wasi": "4.1.7",
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.7",
"@tailwindcss/oxide-win32-x64-msvc": "4.1.7"
"@tailwindcss/oxide-android-arm64": "4.1.11",
"@tailwindcss/oxide-darwin-arm64": "4.1.11",
"@tailwindcss/oxide-darwin-x64": "4.1.11",
"@tailwindcss/oxide-freebsd-x64": "4.1.11",
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11",
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.11",
"@tailwindcss/oxide-linux-arm64-musl": "4.1.11",
"@tailwindcss/oxide-linux-x64-gnu": "4.1.11",
"@tailwindcss/oxide-linux-x64-musl": "4.1.11",
"@tailwindcss/oxide-wasm32-wasi": "4.1.11",
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.11",
"@tailwindcss/oxide-win32-x64-msvc": "4.1.11"
}
},
"node_modules/@tailwindcss/oxide-android-arm64": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.7.tgz",
"integrity": "sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz",
"integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==",
"cpu": [
"arm64"
],
@ -455,9 +444,9 @@
}
},
"node_modules/@tailwindcss/oxide-darwin-arm64": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.7.tgz",
"integrity": "sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz",
"integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==",
"cpu": [
"arm64"
],
@ -471,9 +460,9 @@
}
},
"node_modules/@tailwindcss/oxide-darwin-x64": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.7.tgz",
"integrity": "sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz",
"integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==",
"cpu": [
"x64"
],
@ -487,9 +476,9 @@
}
},
"node_modules/@tailwindcss/oxide-freebsd-x64": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.7.tgz",
"integrity": "sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz",
"integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==",
"cpu": [
"x64"
],
@ -503,9 +492,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.7.tgz",
"integrity": "sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz",
"integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==",
"cpu": [
"arm"
],
@ -519,9 +508,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.7.tgz",
"integrity": "sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz",
"integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==",
"cpu": [
"arm64"
],
@ -535,9 +524,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.7.tgz",
"integrity": "sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz",
"integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==",
"cpu": [
"arm64"
],
@ -551,9 +540,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.7.tgz",
"integrity": "sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz",
"integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==",
"cpu": [
"x64"
],
@ -567,9 +556,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.7.tgz",
"integrity": "sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz",
"integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==",
"cpu": [
"x64"
],
@ -583,9 +572,9 @@
}
},
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.7.tgz",
"integrity": "sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz",
"integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==",
"bundleDependencies": [
"@napi-rs/wasm-runtime",
"@emnapi/core",
@ -603,7 +592,7 @@
"@emnapi/core": "^1.4.3",
"@emnapi/runtime": "^1.4.3",
"@emnapi/wasi-threads": "^1.0.2",
"@napi-rs/wasm-runtime": "^0.2.9",
"@napi-rs/wasm-runtime": "^0.2.11",
"@tybys/wasm-util": "^0.9.0",
"tslib": "^2.8.0"
},
@ -612,9 +601,9 @@
}
},
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.7.tgz",
"integrity": "sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
"integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==",
"cpu": [
"arm64"
],
@ -628,9 +617,9 @@
}
},
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.7.tgz",
"integrity": "sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz",
"integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==",
"cpu": [
"x64"
],
@ -652,6 +641,43 @@
"node": ">=8"
}
},
"node_modules/autoprefixer": {
"version": "10.4.21",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
"integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/autoprefixer"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"browserslist": "^4.24.4",
"caniuse-lite": "^1.0.30001702",
"fraction.js": "^4.3.7",
"normalize-range": "^0.1.2",
"picocolors": "^1.1.1",
"postcss-value-parser": "^4.2.0"
},
"bin": {
"autoprefixer": "bin/autoprefixer"
},
"engines": {
"node": "^10 || ^12 || >=14"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
@ -664,6 +690,58 @@
"node": ">=8"
}
},
"node_modules/browserslist": {
"version": "4.25.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
"integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"caniuse-lite": "^1.0.30001726",
"electron-to-chromium": "^1.5.173",
"node-releases": "^2.0.19",
"update-browserslist-db": "^1.1.3"
},
"bin": {
"browserslist": "cli.js"
},
"engines": {
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001727",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz",
"integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "CC-BY-4.0"
},
"node_modules/chownr": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
@ -685,10 +763,16 @@
"node": ">=0.10"
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.181",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.181.tgz",
"integrity": "sha512-+ISMj8OIQ+0qEeDj14Rt8WwcTOiqHyAB+5bnK1K7xNNLjBJ4hRCQfUkw8RWtcLbfBzDwc15ZnKH0c7SNOfwiyA==",
"license": "ISC"
},
"node_modules/enhanced-resolve": {
"version": "5.18.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
"integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
"version": "5.18.2",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz",
"integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==",
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.4",
@ -698,6 +782,15 @@
"node": ">=10.13.0"
}
},
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@ -710,6 +803,19 @@
"node": ">=8"
}
},
"node_modules/fraction.js": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
"integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
"license": "MIT",
"engines": {
"node": "*"
},
"funding": {
"type": "patreon",
"url": "https://github.com/sponsors/rawify"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@ -1059,12 +1165,45 @@
"node": ">=4"
}
},
"node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/node-addon-api": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
"license": "MIT"
},
"node_modules/node-releases": {
"version": "2.0.19",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
"license": "MIT"
},
"node_modules/normalize-range": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
"integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@ -1083,6 +1222,40 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/postcss": {
"version": "8.5.6",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"license": "MIT"
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@ -1093,9 +1266,9 @@
}
},
"node_modules/tailwindcss": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.7.tgz",
"integrity": "sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==",
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz",
"integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==",
"license": "MIT"
},
"node_modules/tapable": {
@ -1136,6 +1309,36 @@
"node": ">=8.0"
}
},
"node_modules/update-browserslist-db": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
"integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"escalade": "^3.2.0",
"picocolors": "^1.1.1"
},
"bin": {
"update-browserslist-db": "cli.js"
},
"peerDependencies": {
"browserslist": ">= 4.21.0"
}
},
"node_modules/yallist": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",

View File

@ -1,6 +1,8 @@
{
"dependencies": {
"@tailwindcss/cli": "^4.1.7",
"tailwindcss": "^4.1.7"
"autoprefixer": "^10.4.21",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.10"
}
}

View File

@ -0,0 +1,135 @@
use crate::Route;
use dioxus::prelude::*;
#[component]
pub fn BottomSheetMenu(show: bool, on_close: EventHandler<()>) -> Element {
rsx! {
// Overlay - positioned behind the menu
if show {
div {
class: "bottom-sheet-overlay",
onclick: move |_| on_close.call(()),
}
}
// Menu Body
div {
class: format_args!(
"bottom-sheet-menu {}",
if show { "visible" } else { "hidden" }
),
onclick: move |evt| {
evt.stop_propagation();
},
// Menu Header
div {
class: "menu-header",
label {
class: "flex items-center",
div {
class: "menu-handle"
}
}
p {
class: "menu-title",
"Menu"
}
button {
class: "menu-close",
onclick: move |_| on_close.call(()),
title: "Close",
div {
class: "menu-close-icon"
}
}
}
// Menu Links
div {
class: "menu-links",
Link {
class: "menu-link",
to: Route::Home{},
"Home"
}
Link {
class: "menu-link",
to: Route::Skills {},
"Skills"
}
Link {
class: "menu-link",
to: Route::Experiences{},
"Experiences"
}
}
// Menu Contact
div {
class: "menu-contact",
a {
class: "menu-contact-item",
href: "tel:+639",
svg {
class: "menu-contact-icon",
xmlns: "http://www.w3.org/2000/svg",
fill: "currentColor",
height: "24",
view_box: "0 0 24 24",
width: "24",
path {
d: "M0 0h24v24H0z",
fill: "none"
}
path {
d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"
}
}
span {
"Call"
}
}
a {
class: "menu-contact-item",
href: "mailto:portfolio.dc@sent.com",
svg {
class: "menu-contact-icon",
xmlns: "http://www.w3.org/2000/svg",
fill: "currentColor",
height: "24",
view_box: "0 0 24 24",
width: "24",
path {
d: "M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"
}
path {
d: "M0 0h24v24H0z",
fill: "none"
}
}
span {
"Email"
}
}
}
}
}
}
#[component]
pub fn QuickMenuButton(on_click: EventHandler<()>) -> Element {
rsx! {
button {
class: "quick-menu-button",
onclick: move |_| on_click.call(()),
div {
class: "quick-menu-hamburger",
div {
class: "quick-menu-hamburger-line"
}
}
"Quick Menu"
}
}
}

View File

@ -0,0 +1,271 @@
use crate::components::{
skill_data::{self},
Skill, SkillDisplayMode, SkillList,
};
use dioxus::prelude::*;
#[derive(Clone, Debug)]
struct Experience {
title: &'static str,
company: &'static str,
location: &'static str,
employment_type: &'static str,
start_date: &'static str,
end_date: &'static str,
duration: &'static str,
description: &'static str,
skills: Vec<Skill>,
border_color: &'static str,
drop_color: &'static str,
bg_color: &'static str,
}
#[component]
pub fn ExperienceList() -> Element {
let experiences = vec![
Experience {
title: " Senior Full Stack Developer ",
company: "Startechup Inc.",
location: "Cebu, Philippines ",
employment_type: "Full Time ",
start_date: " September 2022",
end_date: "Present",
duration: " 2 yrs & 10 months",
description: "Successfully managed projects on schedule, optimized AWS for 50% cost savings, modernized backend systems, enhanced security, and promoted technical excellence through mentoring and code reviews.",
skills: vec![
skill_data::php_skill(),
skill_data::python_skill(),
skill_data::sql_skill(),
skill_data::html_skill(),
skill_data::css_skill(),
skill_data::javascript_skill(),
skill_data::laravel_skill(),
skill_data::fastapi_skill(),
skill_data::tailwindcss_skill(),
skill_data::aws_skill(),
skill_data::gcp_skill(),
skill_data::git_skill(),
skill_data::docker_skill(),
skill_data::terraform_skill(),
],
border_color: "#EF5A6A",
drop_color: "#EF5A6A",
bg_color: "#EF5A6A",
},
Experience {
title: "Technical Lead/Full Stack Developer",
company: "Herohub Inc.",
location: "San Juan, Philippines",
employment_type: "Full Time",
start_date: "April 2017",
end_date: "January 2021",
duration: "3 yrs & 10 months ",
description: "Aligned technology with business goals, implemented low-code platforms for rapid app development, maintained core infrastructure, mentored teams, and collaborated on the long-term roadmap.",
skills: vec![
skill_data::javascript_skill(),
skill_data::php_skill(),
skill_data::sql_skill(),
skill_data::html_skill(),
skill_data::css_skill(),
skill_data::laravel_skill(),
skill_data::reactjs_skill(),
skill_data::bootstrap_skill(),
skill_data::semanticui_skill(),
skill_data::aws_skill(),
skill_data::gcp_skill(),
skill_data::git_skill(),
skill_data::outsystem_skill(),
skill_data::plsql_skill(),
skill_data::docker_skill(),
],
border_color: "#E88F4D",
drop_color: "#E88F4D",
bg_color: "#E88F4D",
},
Experience {
title: "Full Stack Developer",
company: "Fountainhead Technologies Inc.",
location: "Quezon City, Philippines",
employment_type: "Full Time",
start_date: "December 2013",
end_date: "January 2017",
duration: "3 yrs & 2 months ",
description: "Managed and motivated developers for project success. Handled large SQL databases, owned the development lifecycle, gathered requirements, created flow proposals, coded and tested modules, and integrated APIs.",
skills: vec![
skill_data::javascript_skill(),
skill_data::php_skill(),
skill_data::sql_skill(),
skill_data::html_skill(),
skill_data::css_skill(),
skill_data::laravel_skill(),
skill_data::reactjs_skill(),
skill_data::bootstrap_skill(),
skill_data::semanticui_skill(),
skill_data::aws_skill(),
skill_data::git_skill(),
skill_data::phaserio_skill(),
skill_data::plsql_skill(),
skill_data::sass_skill(),
],
border_color: "#7CB768",
drop_color: "#7CB768",
bg_color: "#7CB768",
},
Experience {
title: "Web Developer",
company: "Mindblow Internet Ideas",
location: "Mandaluyong, Philippines",
employment_type: "Full Time",
start_date: "May 2012",
end_date: "August 2013",
duration: "1 yr & 4 months ",
description: "Participated in client meetings to understand project requirements. Managed small-to-medium projects, including CMS and e-commerce deployments, integrated APIs, collaborated with teams, trained interns, and applied SEO best practices",
skills: vec![
skill_data::javascript_skill(),
skill_data::php_skill(),
skill_data::sql_skill(),
skill_data::html_skill(),
skill_data::css_skill(),
skill_data::codeigniter_skill(),
skill_data::bootstrap_skill(),
],
border_color: "#4EA232",
drop_color: "#4EA232",
bg_color: "#4EA232",
},
];
rsx! {
div {
class: "col items-center relative mt-10 flex-1",
// Vertical timeline line
// div {
// class: "w-[0.5px] hidden lg:flex top-0 bottom-0 py-50px bg-[var(--border)] absolute rounded justify-center "
// }
// Experience Items
for (index, experience) in experiences.iter().enumerate() {
div {
class: "relative items-center w-full my-[10px]",
// Left/Right spacer
div {
class: "flex-1 hidden lg:flex timeline-spacer ",
style: "flex: 0 0 15%;"
}
// Timeline dot
// div {
// class: "hidden lg:inline p-15px bg-[var(--main)] rounded ",
// i {
// class: "i-carbon-condition-point "
// }
// }
// Experience Card
div {
class: "experience-card ",
style: format!("--border-hover: {}", experience.border_color),
// Header section with avatar and title
div {
class: "flex items-start gap-4",
// Avatar
// div {
// class: "experience-avatar ",
// div {
// class: "experience-avatar-inner "
// }
// }
// Content
div {
class: "col ml-0 md:ml-[20px] gap-3 w-full ",
// Title
div {
class: "col",
h2 {
class: "flex text-[2em] flex-col items-start sm:flex-row sm:items-center justify-between sm:gap-5 md:flex-col md:items-start md:gap-0 lg:flex-row lg:items-center bold",
h2 {
class: "font-[var(--title-f)] text-2em bold",
"{experience.title}"
}
}
}
// Company, Location, Type tags
div {
class: "flex flex-wrap gap-2 mb-3",
// Company tag
span {
class: "flex items-center gap-1 px-2 py-1 bg-[var(--secondary)] border border-[var(--border)] rounded text-xs text-[var(--secondary-text)]",
i { class: "i-carbon-building text-xs " }
span { "{experience.company}" }
}
// Location tag
span {
class: "flex items-center gap-1 px-2 py-1 bg-[var(--secondary)] border border-[var(--border)] rounded text-xs text-[var(--secondary-text)]",
i { class: "i-carbon-location text-xs " }
span { "{experience.location}" }
}
// Employment type tag
span {
class: "flex items-center gap-1 px-2 py-1 bg-[var(--secondary)] border border-[var(--border)] rounded text-xs text-[var(--secondary-text)]",
i { class: "i-carbon-user text-xs " }
span { "{experience.employment_type}" }
}
}
// Date and duration info
div {
class: "text-[var(--text)] text-[0.9em]",
// Date range
div {
class: "row items-center gap-2",
i { class: "i-carbon-calendar text-1.25em" }
"{experience.start_date} - {experience.end_date}"
}
div {
class: "bg-[var(--border)] h-1px m-y-10px"
}
// Duration
div {
class: "row items-center gap-2",
i { class: "i-carbon-time text-1.25em" }
"{experience.duration}"
}
div {
class: "bg-[var(--border)] h-1px m-y-10px"
}
}
// Description
div {
class: "experience-description text-[0.9em] mb-4 mt-4",
"{experience.description}"
}
// Skills
if !experience.skills.is_empty() {
SkillList {
skills: experience.skills.clone(),
display_mode: SkillDisplayMode::Chips
}
}
}
}
}
}
}
}
}
}

View File

@ -3,15 +3,11 @@ use dioxus::prelude::*;
#[component]
pub fn Hero() -> Element {
rsx! {
// We can create elements inside the rsx macro with the element name followed by a block of attributes and children.
div {
class: "content container mb6t29",
div {
class: "col self-center flex-1 md:flex-row md:self-stretch justify-center lg:justify-between items-center p-y-0px p-x-10px",
div {
class: "md:flex-1 gap-10px",
div { class: "content container p-15 mt-10",
div { class: "flex",
div { class: "grid content-center md:flex-1",
h1 {
class: "font-[var(--title-f)] font-black tracking-[4px] text-center text-2.5em sm:text-[3em] md:text-[3.5em] lg:text-[4em] md:text-left",
class: "font-[var(--title-f)] font-black tracking-[4px] text-center text-4em lg:text-[4em] md:text-left",
style: "background-image: ; background-position-x: ; background-position-y: ; background-size: ; background-repeat: ; background-attachment: ; background-origin: ; background-clip: text; background-color: ; -webkit-background-clip: text;",
"Danilo"
" "
@ -19,57 +15,48 @@ pub fn Hero() -> Element {
}
p {
class: "text-[var(--tertiary-text)] text-center md:text-left text-[1.2em] font-extralight",
"Lorem ipsum dolor sit, amet consectetur adipisicing elit. Corrupti, rerum. Debitis accusantium deleniti enim iste dignissimos? Similique, exercitationem! Odit vero, numquam quae ratione maxime sunt reiciendis laudantium quaerat iure ipsum!"
}
}
// h1 {
// class: "text-4xl md:text-6xl font-bold mb-4",
// "Hey, I'm Dan"
// }
// p {
// class: "text-lg md:text-xl text-gray-400",
// "Full Stack Developer"
// }
}
// div {
// class: "p-4 rounded-lg hover:border-cyan-500 transition duration-300",
// p {
// class: "text-gray-400",
// "I'm a passionate software developer with a background in computer science and a keen interest in frontend technologies."
// }
// }
// div {
// class: "row justify-center md:justify-start p-y-15px p-x-0px gap-2",
// a {
// class: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md transition duration-300",
// href: "#contact",
// svg {
// class: "inline-block",
// view_box: "0 0 24 24",
// fill: "var(--accent-text)",
// height: "20px",
// width: "20px",
// path {
// d: "M20.5 2h-17A1.5 1.5 0 002 3.5v17A1.5 1.5 0 003.5 22h17a1.5 1.5 0 001.5-1.5v-17A1.5 1.5 0 0020.5 2zM8 19H5v-9h3zM6.5 8.25A1.75 1.75 0 118.3 6.5a1.78 1.78 0 01-1.8 1.75zM19 19h-3v-4.74c0-1.42-.6-1.93-1.38-1.93A1.74 1.74 0 0013 14.19a.66.66 0 000 .14V19h-3v-9h2.9v1.3a3.11 3.11 0 012.7-1.4c1.55 0 3.36.86 3.36 3.66z"
// }
// }
// }
// a {
// class: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md transition duration-300",
// href: "#contact",
// svg {
// class: "inline-block",
// view_box: "0 0 16 16",
// fill: "var(--accent-text)",
// height: "20px",
// width: "20px",
// path {
// d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
// }
// }
// }
// }
"Dynamic Full Stack Developer with over a decade of experience in
analyzing, designing, developing, and implementing a wide range of
software applications. Proven track record in architecting and
managing systems. Experienced software development lifecycle
and end-to-end project, from concept through to development and
delivery.
"
}
}
}
div { class: "row justify-center md:justify-start p-y-15px p-x-0px gap-2",
a {
class: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md transition duration-300",
target: "_blank",
href: "https://www.linkedin.com/in/danilocesajr",
svg {
class: "inline-block",
view_box: "0 0 24 24",
fill: "var(--accent-text)",
height: "20px",
width: "20px",
path {
d: "M20.5 2h-17A1.5 1.5 0 002 3.5v17A1.5 1.5 0 003.5 22h17a1.5 1.5 0 001.5-1.5v-17A1.5 1.5 0 0020.5 2zM8 19H5v-9h3zM6.5 8.25A1.75 1.75 0 118.3 6.5a1.78 1.78 0 01-1.8 1.75zM19 19h-3v-4.74c0-1.42-.6-1.93-1.38-1.93A1.74 1.74 0 0013 14.19a.66.66 0 000 .14V19h-3v-9h2.9v1.3a3.11 3.11 0 012.7-1.4c1.55 0 3.36.86 3.36 3.66z"
}
}
}
a {
class: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md transition duration-300",
target: "_blank",
href: "https://gitea.dcesa.cc",
svg {
class: "inline-block",
view_box: "0 0 16 16",
fill: "var(--accent-text)",
height: "20px",
width: "20px",
path {
d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
}
}
}
}
}
}
}

View File

@ -7,3 +7,15 @@ pub use hero::Hero;
// mod echo;
// pub use echo::Echo;
mod bottom_sheet_menu;
pub use bottom_sheet_menu::{BottomSheetMenu, QuickMenuButton};
mod experience_list;
pub use experience_list::ExperienceList;
mod skill_components;
pub use skill_components::{
skill_data, Skill, SkillCard, SkillCategory, SkillCategorySection, SkillChip, SkillDisplayMode,
SkillList,
};

View File

@ -0,0 +1,538 @@
use dioxus::prelude::*;
// Skill data structure
#[derive(Clone, Debug, PartialEq)]
pub struct Skill {
pub name: &'static str,
pub abbreviation: &'static str,
pub image: Option<Asset>,
pub bg_color: &'static str,
pub border_color: &'static str,
pub drop_color: &'static str,
}
// Skill category structure
#[derive(Clone, Debug, PartialEq)]
pub struct SkillCategory {
pub name: &'static str,
pub skills: Vec<Skill>,
}
// Individual skill card component for the skills page
#[component]
pub fn SkillCard(skill: Skill) -> Element {
rsx! {
a {
class: "card text-inherit decoration-none inline-flex flex-col border-1 border-solid border-[var(--border)] rounded-lg duration relative cursor-pointer decoration-none d1441skb",
style: format!(
"margin: 0px; --bg-img: url({}); --border-color: {}; --drop-color: {}; --bg-color: {};",
skill.image.map(|img| img.to_string()).unwrap_or_default(),
skill.border_color,
skill.drop_color,
skill.bg_color
),
div {
class: "card-bg-img flex-1 flex flex-col p-5 rounded-lg d1441skb",
div {
class: "text-[var(--tertiary-text)]",
"{skill.name}"
}
}
}
}
}
// Small skill chip component for experience cards
#[component]
pub fn SkillChip(skill: Skill) -> Element {
rsx! {
div {
class: "skill-chip",
style: format!("background-color: {}", skill.bg_color),
title: "{skill.name}",
"{skill.abbreviation}"
}
}
}
// Skill list component for displaying multiple skills
#[component]
pub fn SkillList(skills: Vec<Skill>, display_mode: SkillDisplayMode) -> Element {
let sorted_skills = match display_mode {
SkillDisplayMode::Chips => {
let mut skills = skills;
skills.sort_by(|a, b| a.abbreviation.len().cmp(&b.abbreviation.len()));
skills
}
_ => skills,
};
rsx! {
div {
class: match display_mode {
SkillDisplayMode::Grid => "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 md:gap-3 lg:gap-5 mt-5",
SkillDisplayMode::Chips => "experience-skills",
},
for skill in sorted_skills {
match display_mode {
SkillDisplayMode::Grid => rsx! { SkillCard { skill: skill } },
SkillDisplayMode::Chips => rsx! { SkillChip { skill: skill } },
}
}
}
}
}
// Skill category component for the skills page
#[component]
pub fn SkillCategorySection(category: SkillCategory) -> Element {
rsx! {
div {
class: "col gap-5 mb-7",
div {
class: "flex row items-center gap-5",
div { class: "bg-[var(--main-hover)] h-[1px] w-[20px]" }
p {
class: "text-[var(--main-close)]",
"{category.name}"
}
div { class: "flex-1 bg-[var(--main-hover)] h-[1px]" }
}
SkillList {
skills: category.skills,
display_mode: SkillDisplayMode::Grid
}
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum SkillDisplayMode {
Grid, // For skills page
Chips, // For experience cards
}
// Skill data constants and helper functions
pub mod skill_data {
use super::*;
// Image assets
const JS_IMAGE: Asset = asset!("/assets/images/js.png");
const PHP_IMAGE: Asset = asset!("/assets/images/php.jpg");
const PYTHON_IMAGE: Asset = asset!("/assets/images/python-logo.png");
const SQL_IMAGE: Asset = asset!("/assets/images/sql-logo.jpg");
const PLSQL_IMAGE: Asset = asset!("/assets/images/plsql-logo.png");
const RUST_IMAGE: Asset = asset!("/assets/images/rust-logo.png");
const AUTO_IT_IMAGE: Asset = asset!("/assets/images/autoit-logo.jpg");
const HTML_IMAGE: Asset = asset!("/assets/images/html-logo.png");
const CSS_IMAGE: Asset = asset!("/assets/images/css-logo.png");
const SASS_IMAGE: Asset = asset!("/assets/images/sass-logo.png");
const LARAVEL_IMAGE: Asset = asset!("/assets/images/laravel-logo.png");
const CODEIGNITER_IMAGE: Asset = asset!("/assets/images/codeigniter-logo.png");
const REACTJS_IMAGE: Asset = asset!("/assets/images/reactjs-logo.png");
const SVELTE_IMAGE: Asset = asset!("/assets/images/svelte-logo.png");
const D3JS_IMAGE: Asset = asset!("/assets/images/d3js-logo.png");
const PHASERIO_IMAGE: Asset = asset!("/assets/images/phaser-logo.png");
const FASTAPI_IMAGE: Asset = asset!("/assets/images/fastapi-logo.jpg");
const DIOXUS_IMAGE: Asset = asset!("/assets/images/dioxus-logo.png");
const TAILWINDCSS_IMAGE: Asset = asset!("/assets/images/tailwindcss-logo.png");
const BOOTSTRAP_IMAGE: Asset = asset!("/assets/images/bootstrap-logo.png");
const SEMANTICUI_IMAGE: Asset = asset!("/assets/images/semanticui-logo.png");
const AWS_IMAGE: Asset = asset!("/assets/images/aws-logo.png");
const GCP_IMAGE: Asset = asset!("/assets/images/gcp-logo.png");
const OVH_IMAGE: Asset = asset!("/assets/images/ovh-logo.png");
const CLOUDFLARE_IMAGE: Asset = asset!("/assets/images/cloudflare-logo.png");
const GIT_IMAGE: Asset = asset!("/assets/images/git-logo.png");
const DOCKER_IMAGE: Asset = asset!("/assets/images/docker-logo.png");
const OUTSYSTEMS_IMAGE: Asset = asset!("/assets/images/outsystems-logo.png");
const TERRAFORM_IMAGE: Asset = asset!("/assets/images/terraform-logo.png");
// Helper function to get skill by name/abbreviation
pub fn get_skill_by_name(name: &str) -> Option<Skill> {
match name.to_lowercase().as_str() {
"javascript" | "js" => Some(javascript_skill()),
"html" => Some(html_skill()),
"css" => Some(css_skill()),
"php" => Some(php_skill()),
"python" => Some(python_skill()),
"sql" => Some(sql_skill()),
"rust" => Some(rust_skill()),
"laravel" => Some(laravel_skill()),
_ => None,
}
}
// Programming
pub fn javascript_skill() -> Skill {
Skill {
name: "JAVASCRIPT",
abbreviation: "JS",
image: Some(JS_IMAGE),
bg_color: "#f7df1e",
border_color: "#f7df1e80",
drop_color: "#f7df1e26",
}
}
pub fn php_skill() -> Skill {
Skill {
name: "PHP",
abbreviation: "PHP",
image: Some(PHP_IMAGE),
bg_color: "#777bb4",
border_color: "#777bb480",
drop_color: "#777bb426",
}
}
pub fn python_skill() -> Skill {
Skill {
name: "PYTHON",
abbreviation: "PY",
image: Some(PYTHON_IMAGE),
bg_color: "#3776ab",
border_color: "#3776ab80",
drop_color: "#3776ab26",
}
}
pub fn rust_skill() -> Skill {
Skill {
name: "RUST",
abbreviation: "RS",
image: Some(RUST_IMAGE),
bg_color: "#ce422b",
border_color: "#ce422b80",
drop_color: "#ce422b26",
}
}
pub fn sql_skill() -> Skill {
Skill {
name: "SQL",
abbreviation: "SQL",
image: Some(SQL_IMAGE),
bg_color: "#336791",
border_color: "#33679180",
drop_color: "#33679126",
}
}
pub fn plsql_skill() -> Skill {
Skill {
name: "PL/SQL",
abbreviation: "PLSQL",
image: Some(PLSQL_IMAGE),
bg_color: "#d6393c",
border_color: "#d6393c",
drop_color: "#d6393c",
}
}
pub fn autoit_skill() -> Skill {
Skill {
name: "AUTO IT",
abbreviation: "AIT",
image: Some(AUTO_IT_IMAGE),
bg_color: "#ffff0003",
border_color: "#ffff0080",
drop_color: "#ffff0026",
}
}
// Markup & Style
pub fn html_skill() -> Skill {
Skill {
name: "HTML",
abbreviation: "HTML",
image: Some(HTML_IMAGE),
bg_color: "#e34f26",
border_color: "#e34f2680",
drop_color: "#e34f2626",
}
}
pub fn css_skill() -> Skill {
Skill {
name: "CSS",
abbreviation: "CSS",
image: Some(CSS_IMAGE),
bg_color: "#1572b6",
border_color: "#1572b680",
drop_color: "#1572b626",
}
}
pub fn sass_skill() -> Skill {
Skill {
name: "SASS",
abbreviation: "SASS",
image: Some(SASS_IMAGE),
bg_color: "#B755B1",
border_color: "#B755B1",
drop_color: "#B755B1",
}
}
//Frameworks
pub fn laravel_skill() -> Skill {
Skill {
name: "LARAVEL",
abbreviation: "LARAVEL",
image: Some(LARAVEL_IMAGE),
bg_color: "#f53003",
border_color: "#f53003",
drop_color: "#f53003",
}
}
pub fn codeigniter_skill() -> Skill {
Skill {
name: "CODEIGNITER",
abbreviation: "CI",
image: Some(CODEIGNITER_IMAGE),
bg_color: "#dd4814",
border_color: "#dd4814",
drop_color: "#dd4814",
}
}
pub fn reactjs_skill() -> Skill {
Skill {
name: "REACTJS",
abbreviation: "REACTJS",
image: Some(REACTJS_IMAGE),
bg_color: "#2D89C9",
border_color: "#2D89C9",
drop_color: "#2D89C9",
}
}
pub fn svelte_skill() -> Skill {
Skill {
name: "SVELTE",
abbreviation: "SVELTE",
image: Some(SVELTE_IMAGE),
bg_color: "#FF5100",
border_color: "#FF5100",
drop_color: "#FF5100",
}
}
pub fn d3js_skill() -> Skill {
Skill {
name: "D3.JS",
abbreviation: "D3.JS",
image: Some(D3JS_IMAGE),
bg_color: "#FF7D00",
border_color: "#FF7D00",
drop_color: "#FF7D00",
}
}
pub fn phaserio_skill() -> Skill {
Skill {
name: "PHASER.IO",
abbreviation: "PHASER.IO",
image: Some(PHASERIO_IMAGE),
bg_color: "#62eff7",
border_color: "#62eff7",
drop_color: "#62eff7",
}
}
pub fn fastapi_skill() -> Skill {
Skill {
name: "FAST API",
abbreviation: "FASTAPI",
image: Some(FASTAPI_IMAGE),
bg_color: "#009485",
border_color: "#009485",
drop_color: "#009485",
}
}
pub fn dioxus_skill() -> Skill {
Skill {
name: "DIOXUS",
abbreviation: "DIOXUS",
image: Some(DIOXUS_IMAGE),
bg_color: "#EF7E2B",
border_color: "#EF7E2B",
drop_color: "#EF7E2B",
}
}
pub fn tailwindcss_skill() -> Skill {
Skill {
name: "TAILWIND CSS",
abbreviation: "TAILWINDCSS",
image: Some(TAILWINDCSS_IMAGE),
bg_color: "#4CADDC",
border_color: "#4CADDC",
drop_color: "#4CADDC",
}
}
pub fn bootstrap_skill() -> Skill {
Skill {
name: "BOOTSTRAP",
abbreviation: "BOOTSTRAP",
image: Some(BOOTSTRAP_IMAGE),
bg_color: "#922BEF",
border_color: "#922BEF",
drop_color: "#922BEF",
}
}
pub fn semanticui_skill() -> Skill {
Skill {
name: "SEMANTIC UI",
abbreviation: "SEMANTIC_UI",
image: Some(SEMANTICUI_IMAGE),
bg_color: "#15B5B9",
border_color: "#15B5B9",
drop_color: "#15B5B9",
}
}
// Cloud Platforms
pub fn aws_skill() -> Skill {
Skill {
name: "AMAZON (AWS)",
abbreviation: "AWS",
image: Some(AWS_IMAGE),
bg_color: "#EC8439",
border_color: "#EC8439",
drop_color: "#EC8439",
}
}
pub fn gcp_skill() -> Skill {
Skill {
name: "GOOGLE CLOUD PLATFORM",
abbreviation: "GCP",
image: Some(GCP_IMAGE),
bg_color: "#3984EC",
border_color: "#3984EC",
drop_color: "#3984EC",
}
}
pub fn ovh_skill() -> Skill {
Skill {
name: "OVHCLOUD",
abbreviation: "OVH",
image: Some(OVH_IMAGE),
bg_color: "#1537B9",
border_color: "#1537B9",
drop_color: "#1537B9",
}
}
pub fn cloudflare_skill() -> Skill {
Skill {
name: "CLOUDFLARE",
abbreviation: "CF",
image: Some(CLOUDFLARE_IMAGE),
bg_color: "#ea9f2e",
border_color: "#ea9f2e",
drop_color: "#ea9f2e",
}
}
pub fn git_skill() -> Skill {
Skill {
name: "GIT",
abbreviation: "GIT",
image: Some(GIT_IMAGE),
bg_color: "#DE570D",
border_color: "#DE570D",
drop_color: "#DE570D",
}
}
pub fn docker_skill() -> Skill {
Skill {
name: "DOCKER",
abbreviation: "DOCKER",
image: Some(DOCKER_IMAGE),
bg_color: "#1F95DA",
border_color: "#1F95DA",
drop_color: "#1F95DA",
}
}
pub fn outsystem_skill() -> Skill {
Skill {
name: "OUTSYSTEMS",
abbreviation: "OUTSYSTEMS",
image: Some(OUTSYSTEMS_IMAGE),
bg_color: "#BD2031",
border_color: "#BD2031",
drop_color: "#BD2031",
}
}
pub fn terraform_skill() -> Skill {
Skill {
name: "TERRAFORM",
abbreviation: "TF",
image: Some(TERRAFORM_IMAGE),
bg_color: "#8179ea",
border_color: "#8179ea",
drop_color: "#8179ea",
}
}
// Get all skill categories for the skills page
pub fn get_all_skill_categories() -> Vec<SkillCategory> {
vec![
SkillCategory {
name: "Programming Languages",
skills: vec![
javascript_skill(),
php_skill(),
python_skill(),
sql_skill(),
plsql_skill(),
rust_skill(),
autoit_skill(),
],
},
SkillCategory {
name: "Markup & Style",
skills: vec![html_skill(), css_skill(), sass_skill()],
},
SkillCategory {
name: "Frameworks",
skills: vec![
laravel_skill(),
codeigniter_skill(),
reactjs_skill(),
svelte_skill(),
d3js_skill(),
phaserio_skill(),
fastapi_skill(),
dioxus_skill(),
tailwindcss_skill(),
bootstrap_skill(),
semanticui_skill(),
],
},
SkillCategory {
name: "Cloud Platforms",
skills: vec![aws_skill(), gcp_skill(), ovh_skill(), cloudflare_skill()],
},
SkillCategory {
name: "Other Tools",
skills: vec![
git_skill(),
docker_skill(),
outsystem_skill(),
terraform_skill(),
],
},
]
}
}

View File

@ -2,7 +2,7 @@
// need dioxus
use dioxus::prelude::*;
use views::{Blog, Home, Navbar, Skills, Projects, Experiences};
use views::{Blog, Experiences, Home, Navbar, Projects, Skills};
/// Define a components module that contains all shared components for our app.
mod components;
@ -43,14 +43,17 @@ enum Route {
// We can import assets in dioxus with the `asset!` macro. This macro takes a path to an asset relative to the crate root.
// The macro returns an `Asset` type that will display as the path to the asset in the browser or a local path in desktop bundles.
const FAVICON: Asset = asset!("/assets/favicon.ico");
const FAVICON: Asset = asset!("/assets/favicon/favicon.ico");
const FAVICON_16: Asset = asset!("/assets/favicon/favicon-16x16.png");
const FAVICON_32: Asset = asset!("/assets/favicon/favicon-32x32.png");
const FAVICON_APPLE: Asset = asset!("/assets/favicon/apple-touch-icon.png");
const FAVICON_MANIFEST: Asset = asset!("/assets/favicon/site.webmanifest");
// The asset macro also minifies some assets like CSS and JS to make bundled smaller
const TAILWIND_CSS: Asset = asset!("/assets/tailwind.css");
const MEDIA_CSS: Asset = asset!("/assets/styling/media.css");
const TAILWIND_CSS: Asset = asset!("/assets/styling/tailwind.css");
// const MEDIA_CSS: Asset = asset!("/assets/styling/media.css");
const MAIN_CSS: Asset = asset!("/assets/styling/main.css");
const ICONS_CSS: Asset = asset!("/assets/styling/icons.css");
fn main() {
// The `launch` function is the main entry point for a dioxus app. It takes a component and renders it with the platform feature
// you have enabled
@ -68,16 +71,21 @@ fn App() -> Element {
rsx! {
// In addition to element and text (which we will see later), rsx can contain other components. In this case,
// we are using the `document::Link` component to add a link to our favicon and main CSS file into the head of our app.
document::Link { rel: "apple-touch-icon", sizes: "180x180", href:FAVICON_APPLE}
document::Link { rel: "icon", href: FAVICON }
document::Link { rel: "stylesheet", href: TAILWIND_CSS }
document::Link { rel: "stylesheet", href: MEDIA_CSS }
document::Link { rel: "stylesheet", href: MAIN_CSS }
document::Link { rel: "stylesheet", href: ICONS_CSS }
document::Link { rel: "icon", href: FAVICON_16, sizes:"16x16" }
document::Link { rel: "icon", href: FAVICON_32, sizes:"32x32" }
document::Link { rel: "icon", href: FAVICON_MANIFEST}
document::Stylesheet { rel: "stylesheet", href: TAILWIND_CSS }
// document::Link { rel: "stylesheet", href: MEDIA_CSS }
document::Stylesheet { rel: "stylesheet", href: MAIN_CSS }
document::Stylesheet { rel: "stylesheet", href: ICONS_CSS }
// The router component renders the route enum we defined above. It will handle synchronization of the URL and render
// the layouts and components for the active route.
div {
class: "body contents mb6t29",
class: "body",
"data-Theme": if is_dark_theme { "dark" } else { "light" },
Router::<Route> {}
}

View File

@ -1,134 +1,31 @@
use crate::components::ExperienceList;
use crate::Route;
use dioxus::{html::{div, input}, prelude::*};
use dioxus::prelude::*;
// const SKILL_CSS: Asset = asset!("/assets/styling/blog.css");
const EXPERIENCE_CSS: Asset = asset!("/assets/styling/experience.css");
#[component]
pub fn Experiences() -> Element {
rsx! {
document::Stylesheet { href: EXPERIENCE_CSS }
div {
class: "content container mb6t29",
class: "content",
div {
class: "flex-1 col gap-5 px-2 sm:px-4 md:px-6 py-4 sm:py-8 md:py-12",
// Header
h1 {
class: "font-[var(--title-f)] font-black tracking-[4px] text-center text-2.5em sm:text-[3em] md:text-[3.5em] lg:text-[4em]",
"Experiences"
"Experience"
}
// Timeline Container
div {
class: "col gap-5 flex-1",
div { class: "w-100% col flex-1",
div { class:"col items-center relative mt-10 flex-1",
div {class:"w-[0.5px] hidden lg:flex top-0 bottom-0 py-50px bg-[var(--border)] absolute rounded"}
div { class: "flex flex-row-reverse relative items-center w-full my-[10px]",
div { class: "flex-1 hidden lg:flex"}
div { class: "hidden lg:inline p-15px bg-[var(--main)] rounded",
i { class: "i-carbon-condition-point"}
}
div { class:" flex-1 col items-stretch",
a { class:" card text-inherit decoration-none inline-flex flex-col border-1px border-solid border-[var(--border)] rounded-15px duration relative d1441skb",
style:" margin: 0px 0px 20px; --border-color: #ff000080; --drop-color: #ff000026; --bg-color: #ff000003;",
div { class: "card-bg-img flex-1 flex flex-col p-25px rounded-15px d1441skb",
div { class: "col md:flex-row items-start gap-5 md:gap-1",
div{ class: "col ml-0 md:ml-[20px] gap-3 w-full",
div { class: "col ",
h3 { class: "flex text-[0.9em] flex-col items-start sm:flex-row sm:items-center justify-between sm:gap-5 md:flex-col md:items-start md:gap-0 lg:flex-row lg:items-center",
h3 { class: "font-[var(--title-f)] text-1.25em",
"Experience 1"
}
}
}
div {class: "text-[var(--text)] text-[0.9em]",
div {class: "row items-center gap-2",
i { class: "i-carbon-calendar text-1.25em"}
"Jan 2025 - Present"
}
div { class: "bg-[var(--border)] h-1px m-y-10px"}
div { class: "row items-center gap-2",
i { class: "i-carbon-time text-1.25em" }
"4 Years"
}
div { class: "bg-[var(--border)] h-1px m-y-10px"}
}
div { class: "experience-description text-[0.9em]",
"Creating awesome tools for developers."
}
div { class: "flex flex-row flex-wrap mt-5",
a { class: "chip-icon row-center relative text-inherit decoration-none p-10px m-r-5px m-b-5px border-1px border-solid border-[var(--border)] hover:border-[var(--border-hover)] rounded-10px hover:z-5 cursor-pointer grayscale-65 hover:grayscale-0 d1m94jop",
"data-Help": "Rust",
img {class: "w-15px h-15px d1m94jop",
alt: "Rust"
}
}
}
}
}
}
}
}
}
div { class: "flex flex-row relative items-center w-full my-[10px]",
div { class: "flex-1 hidden lg:flex"}
div { class: "hidden lg:inline p-15px bg-[var(--main)] rounded",
i { class: "i-carbon-condition-point"}
}
div { class:" flex-1 col items-stretch",
a { class:" card text-inherit decoration-none inline-flex flex-col border-1px border-solid border-[var(--border)] rounded-15px duration relative d1441skb",
style:" margin: 0px 0px 20px; --border-color: #ff000080; --drop-color: #ff000026; --bg-color: #ff000003;",
div { class: "card-bg-img flex-1 flex flex-col p-25px rounded-15px d1441skb",
div { class: "col md:flex-row items-start gap-5 md:gap-1",
div{ class: "col ml-0 md:ml-[20px] gap-3 w-full",
div { class: "col ",
h3 { class: "flex text-[0.9em] flex-col items-start sm:flex-row sm:items-center justify-between sm:gap-5 md:flex-col md:items-start md:gap-0 lg:flex-row lg:items-center",
h3 { class: "font-[var(--title-f)] text-1.25em",
"Experience 1"
}
}
}
div {class: "text-[var(--text)] text-[0.9em]",
div {class: "row items-center gap-2",
i { class: "i-carbon-calendar text-1.25em"}
"Jan 2025 - Present"
}
div { class: "bg-[var(--border)] h-1px m-y-10px"}
div { class: "row items-center gap-2",
i { class: "i-carbon-time text-1.25em" }
"4 Years"
}
div { class: "bg-[var(--border)] h-1px m-y-10px"}
}
div { class: "experience-description text-[0.9em]",
"Creating awesome tools for developers."
}
div { class: "flex flex-row flex-wrap mt-5",
a { class: "chip-icon row-center relative text-inherit decoration-none p-10px m-r-5px m-b-5px border-1px border-solid border-[var(--border)] hover:border-[var(--border-hover)] rounded-10px hover:z-5 cursor-pointer grayscale-65 hover:grayscale-0 d1m94jop",
"data-Help": "Rust",
img {class: "w-15px h-15px d1m94jop",
alt: "Rust"
}
}
}
}
}
}
}
}
}
}
class: "col gap-2 flex-1",
div {
class: "w-100% col flex-1",
ExperienceList {}
}
}
}

View File

@ -1,8 +1,10 @@
use crate::components::{BottomSheetMenu, QuickMenuButton};
use crate::Route;
use dioxus::prelude::*;
// use dioxus_logger::tracing::{Level, info};
const NAVBAR_CSS: Asset = asset!("/assets/styling/navbar.css");
const MAIN_CSS: Asset = asset!("/assets/styling/main.css");
/// The Navbar component that will be rendered on all pages of our app since every page is under the layout.
///
@ -11,39 +13,34 @@ const MAIN_CSS: Asset = asset!("/assets/styling/main.css");
/// routes will be rendered under the outlet inside this component
#[component]
pub fn Navbar() -> Element {
let mut show_menu = use_signal(|| false);
rsx! {
document::Link { rel: "stylesheet", href: NAVBAR_CSS }
div {
class: "nav-menu jdc7ud",
nav {
class: "container flex flex-row items-center text-sm",
class: "container md:flex flex-row items-center text-sm hidden",
Link {
to: Route::Home {},
class: "nav-menu-left decoration-none w-auto md:w-150px lg:w-auto row flex flex-row items-center cursor-pointer px-4 text-[var(--secondary-text)] self-stretch hover:bg-[color:var(--main-hover)]",
i {
class: "i-carbon-code text-2em"
class: "i-carbon-code"
}
span {
class: "ml-2 text-md font-bold hidden md:inline overflow-hidden whitespace-nowrap text-ellipsis",
class: "h2 ml-2 text-md font-bold hidden md:inline overflow-hidden whitespace-nowrap text-ellipsis",
"Danilo"
" "
"Cesa"
}
}
div {
class: "flex-1 block overflow-hidden md:hidden whitespace-nowrap text-ellipsis text-center",
"Danilo"
" "
"Cesa"
}
div {
class: "flex-row flex-1 self-center h-full justify-center hidden md:flex",
class: "flex-row flex-1 self-center h-full justify-center md:flex hidden",
Link {
to: Route::Skills {},
class: "nav-menu-item !text-[var(--secondary-text)] jdc7ud",
i {
class: "i-carbon-software-resource-cluster text-1.3em"
class: "i-carbon-software-resource-cluster"
}
span {
class: "nav-menu-item-label jdc7ud",
@ -51,17 +48,17 @@ pub fn Navbar() -> Element {
}
}
Link {
class: "nav-menu-item !text-[var(--secondary-text)] jdc7ud",
to: Route::Projects {},
i {
class: "i-carbon-cube text-1.3em"
}
span {
class: "nav-menu-item-label jdc7ud",
"Projects"
}
}
// Link {
// class: "nav-menu-item !text-[var(--secondary-text)] jdc7ud",
// to: Route::Projects {},
// i {
// class: "i-carbon-cube text-2em"
// }
// span {
// class: "nav-menu-item-label jdc7ud",
// "Projects"
// }
// }
Link {
class: "nav-menu-item !text-[var(--secondary-text)] jdc7ud",
@ -74,48 +71,23 @@ pub fn Navbar() -> Element {
"Experiences"
}
}
}
Link {
class: "nav-menu-item !text-[var(--secondary-text)] jdc7ud",
to: Route::Home {},
i {
class: "i-carbon-result text-1.3em"
}
span {
class: "nav-menu-item-label jdc7ud",
"Resume"
}
}
}
// div {
// class: "row h-full justify-center items-stretch m-l-auto md:m-l-0 w-auto md:w-150px gap-1 text-1.15em",
// div {
// class: "row hidden md:flex",
// // a {
// // class: "text-inherit col-center self-stretch px-2 hover:bg-[color:var(--main-hover)]"
// // }
// // button {
// // class: "bg-transparent text-1em border-none cursor-pointer hover:bg-[color:var(--main-hover)] text-[var(--secondary-text)] px-2",
// // i {
// // class: "i-carbon-moon"
// // }
// // }
// }
// div {
// class: "col-center md:hidden h-full hover:bg-[var(--main-hover)] cursor-pointer",
// div {
// class: "nav-bar-mobile-btn col-center jdc7ud"
// }
// }
// }
if !show_menu() {
QuickMenuButton {
on_click: move |_| show_menu.set(true)
}
}
// Bottom Sheet Menu
BottomSheetMenu {
show: show_menu(),
on_close: move |_| show_menu.set(false)
}
// The `Outlet` component is used to render the next component inside the layout. In this case, it will render either
// the [`Home`] or [`Blog`] component depending on the current route.
Outlet::<Route> {}
}
}

View File

@ -1,7 +1,5 @@
use crate::Route;
use dioxus::{html::input, prelude::*};
// const SKILL_CSS: Asset = asset!("/assets/styling/blog.css");
use dioxus::prelude::*;
#[component]
pub fn Projects() -> Element {

View File

@ -1,68 +1,68 @@
use crate::components::{skill_data, SkillCategorySection};
use crate::Route;
use dioxus::{html::input, prelude::*};
// const SKILL_CSS: Asset = asset!("/assets/styling/blog.css");
use dioxus::prelude::*;
#[component]
pub fn Skills() -> Element {
let skill_categories = skill_data::get_all_skill_categories();
let mut search_query = use_signal(|| String::new());
let filtered_categories = use_memo(move || {
let query = search_query.read().to_lowercase();
if query.is_empty() {
skill_categories.clone()
} else {
skill_categories
.iter()
.map(|category| {
let filtered_skills: Vec<_> = category
.skills
.iter()
.filter(|skill| skill.name.to_lowercase().contains(&query))
.cloned()
.collect();
crate::components::SkillCategory {
name: category.name,
skills: filtered_skills,
}
})
.filter(|category| !category.skills.is_empty()) // Only show categories with matching skills
.collect()
}
});
rsx! {
div {
class: "content container mb6t29",
div {
class: "flex-1 col gap-5 px-2 sm:px-4 md:px-6 py-4 sm:py-8 md:py-12",
div { class: "content",
div { class: "flex-1 col gap-5 px-2 sm:px-4 md:px-6 py-4 sm:py-8 md:py-12",
h1 {
class: "font-[var(--title-f)] font-black tracking-[4px] text-center text-2.5em sm:text-[3em] md:text-[3.5em] lg:text-[4em]",
"Skills"
}
div {
class: "col gap-5 flex-1",
div {
class: "w-100% row",
div { class: "flex-1",
div { class: "w-full row",
input {
class: "text-[inherit] bg-transparent border-[1px] border-solid border-[var(--border)] px-[20px] py-[10px] rounded-[15px] flex-1 text-[1.15em] c0g44u",
class: "text-[inherit] bg-transparent border-[1px] border-solid border-[var(--border)] px-[20px] py-[10px] rounded-[15px] flex-1 text-[1.15em] w-full",
type: "text",
placeholder: "Search skills..."
placeholder: "Search skills...",
value: "{search_query}",
oninput: move |event| {
search_query.set(event.value());
}
}
}
div { class: "w-100% col flex-1",
div { class: "w-full col flex-1",
div { class: "col mt-5 gap-7",
div { class: "col gap-5 mb-7",
div { class: "row items-center gap-5",
div { class: "bg-[var(--main-hover)] h-[1px] w-[20px]"}
p {
class: "text-[var(--main-close)]",
"Programming Languages"
}
div { class: "flex-1 bg-[var(--main-hover)] h-[1px]"}
}
if filtered_categories().is_empty() && !search_query.read().is_empty() {
div {
class: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 md:gap-3 lg:gap-5",
a {
class: "card text-inherit decoration-none inline-flex flex-col border-1px border-solid border-[var(--border)] rounded-15px duration relative cursor-pointer decoration-none d1441skb",
style: "margin: 0px; --bg-img: url(.png); --border-color: #ffff0080; --drop-color: #ffff0026; --bg-color: #ffff0003;",
div {
class: "card-bg-img flex-1 flex flex-col p-25px rounded-15px d1441skb",
div {
class: "text-[var(--tertiary-text)]",
"Javascript"
}
}
}
a {
class: "card text-inherit decoration-none inline-flex flex-col border-1px border-solid border-[var(--border)] rounded-15px duration relative cursor-pointer decoration-none d1441skb",
style: "margin: 0px; --bg-img: url(.png); --border-color: #ffff0080; --drop-color: #ffff0026; --bg-color: #ffff0003;",
div {
class: "card-bg-img flex-1 flex flex-col p-25px rounded-15px d1441skb",
div {
class: "text-[var(--tertiary-text)]",
"PHP"
}
}
class: "text-center py-8 text-[var(--secondary-text)]",
"No skills found matching your search."
}
} else {
for category in filtered_categories() {
SkillCategorySection { category: category }
}
}
}

View File

@ -1,7 +1,7 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
mode: "all",
content: ["./src/**/*.{rs,html,css}", "./dist/**/*.html"],
content: ["./src/**/*.{rs,html,css}", "./assets/**/*.{css,png,jpeg,jpg}"],
theme: {
extend: {},
},