summaryrefslogtreecommitdiffstats
path: root/src/ui/layouts
diff options
context:
space:
mode:
authorVolpeon <git@volpeon.ink>2026-07-22 19:40:59 +0200
committerVolpeon <git@volpeon.ink>2026-07-22 19:40:59 +0200
commitc1e28224aa2e1450031669d9a7e359b63e04687d (patch)
tree68f3d8905c763a91f68001d868197effa92adafa /src/ui/layouts
downloadcorvos-website-c1e28224aa2e1450031669d9a7e359b63e04687d.tar.gz
corvos-website-c1e28224aa2e1450031669d9a7e359b63e04687d.tar.bz2
corvos-website-c1e28224aa2e1450031669d9a7e359b63e04687d.zip
Init
Diffstat (limited to 'src/ui/layouts')
-rw-r--r--src/ui/layouts/CardList.tsx52
-rw-r--r--src/ui/layouts/Container.tsx33
-rw-r--r--src/ui/layouts/EmojiGrid.tsx40
-rw-r--r--src/ui/layouts/HList.tsx44
-rw-r--r--src/ui/layouts/SplitView.tsx27
-rw-r--r--src/ui/layouts/SplitViewPanel.tsx33
6 files changed, 229 insertions, 0 deletions
diff --git a/src/ui/layouts/CardList.tsx b/src/ui/layouts/CardList.tsx
new file mode 100644
index 0000000..96ae642
--- /dev/null
+++ b/src/ui/layouts/CardList.tsx
@@ -0,0 +1,52 @@
1import type { HTMLAttributes } from "corvos/plugins/jsx.ts";
2
3export type Props = HTMLAttributes<"ul"> & {
4 "layout"?:
5 | "merge"
6 | "grid"
7 | "grid-sm"
8 | "grid-xs"
9 | "flex"
10 | "flex-sm"
11 | "flex-xs"
12 | "masonry"
13 | "masonry-h"
14 | "masonry-h-sm";
15 "quiet"?: boolean;
16 "border"?: boolean;
17 "interactive"?: boolean;
18 "no-shadow"?: boolean;
19 "no-flush"?: boolean;
20 "keyboard-nav"?: boolean;
21};
22
23export const CardList = ({
24 layout,
25 quiet,
26 border,
27 interactive,
28 "no-shadow": noShadow,
29 "no-flush": noFlush,
30 "keyboard-nav": keyboardNav,
31 class: cls,
32 ...props
33}: Props) => (
34 <div
35 class:list={[
36 "l-card-list",
37 {
38 [`l-card-list--${layout}`]: layout,
39 "l-card-list--interactive": interactive,
40 "l-card-list--no-flush": noFlush,
41 "l-card-list--quiet": quiet,
42 "l-card-list--borderless": !border,
43 "l-card-list--shadow": layout === "merge" && !noShadow,
44 "js-keyboard-nav": keyboardNav,
45 },
46 cls,
47 ]}
48 data-keyboard-nav-item=".l-card-list__card"
49 data-keyboard-nav-mode="grid"
50 {...props}
51 />
52);
diff --git a/src/ui/layouts/Container.tsx b/src/ui/layouts/Container.tsx
new file mode 100644
index 0000000..7ce7ed5
--- /dev/null
+++ b/src/ui/layouts/Container.tsx
@@ -0,0 +1,33 @@
1import type { HTMLTag, Polymorphic } from "corvos/plugins/jsx.ts";
2
3export type Props<Tag extends HTMLTag> = Polymorphic<{
4 "as": Tag;
5 "pad-inline"?: boolean;
6 "pad-block"?: boolean;
7 "size"?: "sm";
8 "fixed"?: boolean | "150" | "200";
9}>;
10
11export const Container = <T extends HTMLTag = "div">({
12 as: Tag = "div" as T,
13 class: cls,
14 "pad-inline": padInline,
15 "pad-block": padBlock,
16 fixed,
17 size,
18 ...props
19}: Props<T>) => (
20 <Tag
21 class:list={[
22 "l-container",
23 {
24 "l-container--pad-i": padInline,
25 "l-container--pad-b": padBlock,
26 [`l-container--${size}`]: size,
27 [`l-container--fixed${typeof fixed === "boolean" ? "" : `-${fixed}`}`]: fixed,
28 },
29 cls,
30 ]}
31 {...props}
32 />
33);
diff --git a/src/ui/layouts/EmojiGrid.tsx b/src/ui/layouts/EmojiGrid.tsx
new file mode 100644
index 0000000..5dc9266
--- /dev/null
+++ b/src/ui/layouts/EmojiGrid.tsx
@@ -0,0 +1,40 @@
1import type { HTMLAttributes } from "corvos/plugins/jsx.ts";
2
3export type Props = HTMLAttributes<"ul"> & {
4 id: string;
5 sprite: {
6 variants: { size: number; space: number }[];
7 wrap: number;
8 };
9 count: number;
10};
11
12export const EmojiGrid = ({ id, sprite, count, class: cls, ...props }: Props) => {
13 const size = sprite.variants[0]?.size ?? 48;
14 const space = sprite.variants[0]?.space ?? 2;
15 const { wrap } = sprite;
16
17 const src = `/emojis/${id}/sprite48.avif`;
18 const srcset = `/emojis/${id}/sprite48.avif 1x, /emojis/${id}/sprite96.avif 2x`;
19
20 const offsetX = (i: number) => -1 * (size + space) * (i % wrap);
21 const offsetY = (i: number) => -1 * (size + space) * Math.floor(i / wrap);
22
23 return (
24 <ul class:list={["l-emoji-grid", cls]} style={{ "--emoji-size": `${size}px` }} {...props}>
25 {[...Array(count).keys()].map((i) => (
26 <li>
27 <img
28 alt=""
29 class="l-emoji-grid__emoji"
30 src={src}
31 srcset={srcset}
32 width={size}
33 height={size}
34 style={{ "object-position": `${offsetX(i)}px ${offsetY(i)}px` }}
35 />
36 </li>
37 ))}
38 </ul>
39 );
40};
diff --git a/src/ui/layouts/HList.tsx b/src/ui/layouts/HList.tsx
new file mode 100644
index 0000000..c1d870a
--- /dev/null
+++ b/src/ui/layouts/HList.tsx
@@ -0,0 +1,44 @@
1import type { HTMLTag, Polymorphic } from "corvos/plugins/jsx.ts";
2
3import type { Props as ActionButtonProps } from "../objects/ActionButton.tsx";
4
5export type Props<Tag extends HTMLTag> = Polymorphic<{
6 "as"?: Tag;
7 "pill"?: boolean;
8 "icon"?: boolean;
9 "separated"?: boolean;
10 "size"?: "gapless" | "sm" | "lg" | "xl";
11 "buttons-size"?: ActionButtonProps<Tag>["size"];
12 "buttons"?: boolean;
13}>;
14
15export const HList = <T extends HTMLTag = "ul">({
16 as: Tag = "ul" as T,
17 pill,
18 icon,
19 separated,
20 size,
21 "buttons-size": buttonsSize,
22 buttons,
23 class: cls,
24 ...props
25}: Props<T>) => (
26 <Tag
27 class:list={[
28 "l-hlist",
29 {
30 "l-hlist--pill": pill,
31 "l-hlist--icon": icon,
32 "l-hlist--separated": separated,
33 [`l-hlist--${size}`]: size,
34 [`l-hlist--buttons-${buttonsSize}`]: buttonsSize,
35 "l-hlist--buttons": buttons,
36 },
37 "js-keyboard-nav",
38 cls,
39 ]}
40 data-keyboard-nav-item="li > :first-child"
41 data-keyboard-nav-mode="nav"
42 {...props}
43 />
44);
diff --git a/src/ui/layouts/SplitView.tsx b/src/ui/layouts/SplitView.tsx
new file mode 100644
index 0000000..81a55d1
--- /dev/null
+++ b/src/ui/layouts/SplitView.tsx
@@ -0,0 +1,27 @@
1import type { HTMLTag, Polymorphic } from "corvos/plugins/jsx.ts";
2
3export type Props<Tag extends HTMLTag> = Polymorphic<{
4 "as": Tag;
5 "gapless"?: boolean;
6 "wrap-reverse"?: boolean;
7}>;
8
9export const SplitView = <T extends HTMLTag = "div">({
10 as: Tag = "div" as T,
11 gapless,
12 "wrap-reverse": wrapReverse,
13 class: cls,
14 ...props
15}: Props<T>) => (
16 <Tag
17 class:list={[
18 "l-split-view",
19 {
20 "l-split-view--gapless": gapless,
21 "l-split-view--wrap-reverse": wrapReverse,
22 },
23 cls,
24 ]}
25 {...props}
26 />
27);
diff --git a/src/ui/layouts/SplitViewPanel.tsx b/src/ui/layouts/SplitViewPanel.tsx
new file mode 100644
index 0000000..7f04b44
--- /dev/null
+++ b/src/ui/layouts/SplitViewPanel.tsx
@@ -0,0 +1,33 @@
1import type { HTMLTag, Polymorphic } from "corvos/plugins/jsx.ts";
2
3export type Props<Tag extends HTMLTag> = Polymorphic<{
4 as: Tag;
5 sticky?: boolean;
6 side?: "25";
7 min?: "50" | "100" | "200";
8 fill?: boolean;
9}>;
10
11export const SplitViewPanel = <T extends HTMLTag = "div">({
12 as: Tag = "div" as T,
13 sticky,
14 side,
15 min,
16 fill,
17 class: cls,
18 ...props
19}: Props<T>) => (
20 <Tag
21 class:list={[
22 "l-split-view__panel",
23 {
24 "l-split-view__panel--sticky": sticky,
25 [`l-split-view__panel--side-${side}`]: side,
26 [`l-split-view__panel--min-${min}`]: min,
27 "l-split-view__panel--fill": fill,
28 },
29 cls,
30 ]}
31 {...props}
32 />
33);