Files
Clintchiz 2c960fc1dc
Quality / quality (ubuntu-latest) (push) Failing after 9m49s
Quality / quality (windows-latest) (push) Canceled after 0s
refactor: migrate legacy wire namespace to wrn
2026-08-12 18:51:15 +05:30

128 lines
2.8 KiB
Plaintext

// Image -- a framed image with a reserved aspect ratio.
//
// <Image src="/hero.jpg" alt="Dashboard" size="video" rounded={true} />
//
// The frame keeps its ratio whether or not the image has loaded, so the page
// does not jump when it arrives. Without a src it renders a labelled
// placeholder of the same shape rather than collapsing.
//
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
// and silently swallows the rule that follows it.
component Image {
props {
size: string = "default"
color: string = "primary"
src: string = ""
alt: string = ""
width: string = ""
height: string = ""
loading: string = "lazy"
fit: string = "cover"
rounded: boolean = false
class: string = ""
}
view {
<figure
{...attrs}
data-ui-component="Image"
class='wrn-image {class}'
data-size='{size}'
data-color='{color}'
data-fit='{fit}'
data-rounded='{rounded}'
>
<img
class="wrn-image__img"
data-show="src"
src='{src}'
alt='{alt}'
width='{width}'
height='{height}'
loading='{loading}'
decoding="async"
/>
<div
class="wrn-image__placeholder"
data-show="!src"
role="img"
aria-label='{alt || "Image placeholder"}'
>
<span class="icon-[lucide--image] wrn-image__placeholder-icon" aria-hidden="true"></span>
</div>
<slot></slot>
</figure>
}
style {
.wrn-image {
position: relative;
margin: 0;
overflow: hidden;
width: 100%;
min-width: 0;
background: var(--wrn-color-surface-soft);
}
.wrn-image[data-rounded="true"] {
border-radius: var(--wrn-radius-lg);
}
/*
* The ratio sits on the frame rather than the image, so the space is
* reserved before the file arrives and the page does not jump.
*/
.wrn-image[data-size="square"] {
aspect-ratio: 1 / 1;
}
.wrn-image[data-size="video"] {
aspect-ratio: 16 / 9;
}
.wrn-image[data-size="landscape"] {
aspect-ratio: 4 / 3;
}
.wrn-image[data-size="portrait"] {
aspect-ratio: 3 / 4;
}
.wrn-image__img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
.wrn-image[data-fit="contain"] .wrn-image__img {
object-fit: contain;
}
.wrn-image[data-fit="fill"] .wrn-image__img {
object-fit: fill;
}
.wrn-image[data-size="default"] .wrn-image__img {
height: auto;
}
.wrn-image__placeholder {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
min-height: 12rem;
height: 100%;
color: var(--wrn-color-text-muted);
}
.wrn-image__placeholder-icon {
width: 2rem;
height: 2rem;
}
}
}