webspace/src/lib/components/tiles/Tile.svelte

83 lines
1.7 KiB
Svelte
Raw Normal View History

2025-11-30 22:44:47 +05:00
<!--
@component
Metro-like tile. Must be in a group to display correctly.
-->
<script lang="ts">
import { cva } from "class-variance-authority";
// Base size for a icon in pixels.
const ICON_BASE_SIZE = 45;
2025-11-30 22:44:47 +05:00
let {
size,
row,
column,
children,
2025-11-30 22:44:47 +05:00
}: {
/**
* Size.
*/
size: "small" | "medium" | "wide" | "large";
/**
* Row index. Must be in a small tiles.
*/
row: number;
/**
* Column index. Must be in a small tiles.
*/
column: number;
/**
* Pages.
2025-11-30 22:44:47 +05:00
*/
children: () => any;
2025-11-30 22:44:47 +05:00
} = $props();
/**
* Tile style.
**/
const style = cva(["bg-(--tile-color)", "overflow-y-hidden"], {
2025-11-30 22:44:47 +05:00
variants: {
size: {
small: ["row-span-1", "col-span-1"],
medium: ["row-span-2", "col-span-2"],
wide: ["row-span-4", "col-span-2"],
large: ["row-span-4", "col-span-4"],
2025-11-30 22:44:47 +05:00
},
},
});
/**
* Icon size. Based on tile's size.
*/
let iconSize: string = $state("0");
switch (size) {
case "small":
iconSize = `${ICON_BASE_SIZE}px`;
break;
case "medium":
case "wide":
iconSize = `${ICON_BASE_SIZE * 2}px`;
break;
case "large":
iconSize = `${ICON_BASE_SIZE * 4}px`;
break;
}
2025-11-30 22:44:47 +05:00
</script>
<div
class={style({ size })}
style="
--tile-icon-size: {iconSize};
--tile-name-display: {size !== 'small' ? 'inline' : 'none'};
2025-11-30 22:44:47 +05:00
grid-row-start: {row};
grid-column-start: {column};
2025-11-30 22:44:47 +05:00
"
>
{@render children()}
</div>