justin.deal/src/components/common/ServiceCard.astro

115 lines
2.3 KiB
Plaintext
Raw Normal View History

2025-04-27 20:43:15 -07:00
---
/**
* ServiceCard component displays a service with an icon and name
* @component
* @example
* ```astro
* <ServiceCard
* name="Gitea"
* href="https://code.justin.deal"
* img="https://cdn.jsdelivr.net/gh/selfhst/icons/svg/gitea.svg"
* alt="Gitea"
* />
* ```
*/
interface Props {
/**
* The name of the service to display
*/
name: string;
/**
* The URL to link to when the service card is clicked
*/
href: string;
/**
* The URL of the service icon
*/
img: string;
/**
* Alternative text for the service icon
*/
alt: string;
}
2025-04-27 20:43:15 -07:00
const { name, href, img, alt } = Astro.props;
---
<a
href={href}
class="service-card flex items-center transition-all duration-300 hover:opacity-90"
2025-04-27 20:43:15 -07:00
target="_blank"
rel="noopener noreferrer"
>
<div class="service-icon-container flex-shrink-0">
<img
src={img}
alt={alt}
class="service-icon w-16 h-16 transition-all duration-300"
loading="lazy"
decoding="async"
/>
</div>
<p class="service-name mt-2 text-center transition-all duration-300">{name}</p>
2025-04-27 20:43:15 -07:00
</a>
<style>
/* Default (grid) view */
.service-card {
flex-direction: column;
justify-content: center;
}
/* List view adjustments applied via JS */
:global(.view-mode-list) .service-card {
flex-direction: row;
justify-content: flex-start;
padding: 0.5rem;
border-radius: 0.375rem;
}
:global(.view-mode-list) .service-name {
margin-top: 0;
margin-left: 1rem;
text-align: left;
}
/* Icon size adjustments with CSS variables for fine-grained control */
:global(#app-list) {
--icon-scale: 2; /* Default medium size */
--icon-base-size: 1rem;
}
.service-icon {
width: calc(var(--icon-base-size) * var(--icon-scale) * 2);
height: calc(var(--icon-base-size) * var(--icon-scale) * 2);
}
/* Fallback discrete sizes for browsers that don't support calc */
:global(.icon-size-small) .service-icon {
width: 2rem;
height: 2rem;
}
:global(.icon-size-medium) .service-icon {
width: 4rem;
height: 4rem;
}
:global(.icon-size-large) .service-icon {
width: 6rem;
height: 6rem;
}
/* Hover effect */
.service-card:hover {
transform: translateY(-2px);
}
:global(.view-mode-list) .service-card:hover {
transform: translateX(2px);
}
</style>