<script lang="ts">
import type { Snippet } from "svelte";
import {
LANGUAGE_COLORS,
LANGUAGE_COLOR_FALLBACK
} from "#lib/components/repo/languageColors.ts";
import ColorBall from "#lib/components/ui/ColorBall.svelte";
import QueryToken from "#lib/components/search/QueryToken.svelte";
import SearchTabs, { searchUrl } from "#lib/components/search/SearchTabs.svelte";
import { POPULAR_LANGUAGES } from "#lib/repoQuery.ts";
import { quoteValue } from "#lib/ticketQuery.ts";
interface Props {
query: string;
active: string;
class?: string;
/** tab-specific result metadata, rendered under the filters */
children?: Snippet;
}
let { query, active, class: className, children }: Props = $props();
const languageKey = $derived(active === "code" ? "lang" : "language");
const withLang = (lang: string) => {
const token = `${languageKey}:${quoteValue(lang)}`;
return query.split(/\s+/).includes(token) ? query.trim() : `${token} ${query}`.trim();
};
const langColor = (lang: string) => LANGUAGE_COLORS[lang] ?? LANGUAGE_COLOR_FALLBACK;
</script>
<div class={["flex flex-col gap-xl md:sticky md:top-2 md:self-start", className]}>
<div>
<h2 class="mb-sm typography-paragraph-small font-semibold text-foreground-muted">
Filter by
</h2>
<SearchTabs {query} {active} />
</div>
<div>
<h2 class="mb-sm typography-paragraph-small font-semibold text-foreground-muted">
Languages
</h2>
<div class="flex flex-wrap gap-xs">
{#each POPULAR_LANGUAGES as lang (lang)}
<a
href={searchUrl(active, withLang(lang))}
class="flex w-fit shrink-0 items-center gap-xs rounded-md border border-border-default bg-background-default px-xs py-2xs typography-paragraph-regular text-foreground-default transition-colors hover:bg-background-subtle"
>
<ColorBall color={langColor(lang)} class="size-2.5" />
<span>{lang}</span>
</a>
{/each}
</div>
<p class="mt-sm typography-paragraph-small text-foreground-subtle">
Selecting a language adds <QueryToken>{languageKey}:Rust</QueryToken> to your search.
</p>
</div>
{@render children?.()}
</div>