// Image -- a framed image with a reserved aspect ratio. // // Dashboard // // 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 {
{alt}
} 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; } } }