Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
--size-selector: 0.25rem;
--size-field: 0.28125rem;
--border: 1px;
--depth: 0;
--depth: 1;
--noise: 0;
}
@plugin "daisyui/theme" {
Expand Down Expand Up @@ -71,7 +71,7 @@
--size-selector: 0.25rem;
--size-field: 0.28125rem;
--border: 1px;
--depth: 0;
--depth: 1;
--noise: 0;
}

Expand Down Expand Up @@ -127,6 +127,15 @@
* {
font-size: 15px;
}
@media (prefers-color-scheme: dark) {
.select {
&, & select {
&::picker(select) {
border: var(--border) solid var(--color-base-content);
}
}
}
}
}

.dropdown-content {
Expand Down
7 changes: 4 additions & 3 deletions src/lib/components/BlockIfJobsUnavailable.svelte
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
<script lang="ts">
import type { Snippet } from 'svelte';
import type { ClassValue } from 'svelte/elements';
import { page } from '$app/state';
import { m } from '$lib/paraglide/messages';
import { toast } from '$lib/utils';

interface Props {
altContent: Snippet;
children: Snippet;
className?: string;
class?: ClassValue;
}
let { altContent, children, className }: Props = $props();
let { altContent, children, class: classes }: Props = $props();
</script>

{#if page.data.jobsAvailable}
{@render children()}
{:else}
<button
class="{className} opacity-30 cursor-not-allowed"
class={[classes, 'opacity-30 cursor-not-allowed']}
type="button"
onclick={() => toast('warning', m.system_unavailable())}
>
Expand Down
36 changes: 18 additions & 18 deletions src/lib/components/Dropdown.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,24 @@ A simple dropdown menu from DaisyUI.
-->
<script lang="ts">
import type { Snippet } from 'svelte';
import type { ClassValue } from 'svelte/elements';
import { onNavigate } from '$app/navigation';
interface Props {
/** class="dropdown ..." */
dropdownClasses?: string;
/** class="btn btn-ghost ..." */
labelClasses?: string;
/** class="dropdown-content z-10 drop-shadow-lg rounded-md bg-base-200 ..." */
contentClasses?: string;
class?: {
/** class="dropdown ..." */
dropdown?: ClassValue;
/** class="btn btn-ghost ..." */
label?: ClassValue;
/** class="dropdown-content z-10 drop-shadow-lg rounded-md bg-base-200 ..." */
content?: ClassValue;
};
label: Snippet;
content: Snippet;
onclick?: () => void;
open?: boolean;
}

let {
dropdownClasses = '',
labelClasses = '',
contentClasses = '',
label,
content,
onclick,
open = $bindable(false)
}: Props = $props();
let { class: classes, label, content, onclick, open = $bindable(false) }: Props = $props();

onNavigate(() => {
// close opened dropdown when navigating (this is mostly important for the dropdowns in the navbar)
Expand All @@ -48,11 +43,16 @@ A simple dropdown menu from DaisyUI.
}}
/>

<details class="dropdown {dropdownClasses}" bind:open bind:this={dropEl}>
<summary class="btn btn-ghost {labelClasses}" onclick={() => onclick?.()}>
<details class={['dropdown', classes?.dropdown]} bind:open bind:this={dropEl}>
<summary class={['btn btn-ghost', classes?.label]} onclick={() => onclick?.()}>
{@render label()}
</summary>
<div class="dropdown-content z-10 drop-shadow-lg rounded-md bg-base-200 {contentClasses}">
<div
class={[
'dropdown-content z-10 drop-shadow-lg rounded-md bg-base-200 dark:border dark:border-base-content',
classes?.content
]}
>
{@render content()}
</div>
</details>
14 changes: 7 additions & 7 deletions src/lib/components/LanguageCodeTypeahead.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import type { FuseResultMatch } from 'fuse.js';
import type { Snippet } from 'svelte';
import type { HTMLInputAttributes } from 'svelte/elements';
import type { ClassValue, HTMLInputAttributes } from 'svelte/elements';
import TypeaheadInput from './TypeaheadInput.svelte';
import { page } from '$app/state';
import { type LangInfo, l10nMap, localizeTagData } from '$lib/locales.svelte';
Expand Down Expand Up @@ -106,17 +106,18 @@
let typeaheadInput: HTMLInputElement | undefined = $state(undefined);
interface Props {
langCode: string;
dropdownClasses?: string;
inputClasses?: string;
class?: {
dropdown?: ClassValue;
input?: ClassValue;
};
onLangCodeSelected?: (langCode: string) => void;
inputElProps?: HTMLInputAttributes;
validatorHint?: Snippet;
}

let {
langCode = $bindable(),
dropdownClasses = '',
inputClasses = '',
class: classes,
onLangCodeSelected,
inputElProps = {},
validatorHint
Expand Down Expand Up @@ -155,13 +156,12 @@
<TypeaheadInput
inputElProps={{ placeholder: m.project_languageCode(), ...inputElProps }}
getList={(searchValue) => search(searchValue)}
classes="pr-20 {inputClasses}"
class={{ default: ['pr-20', classes?.input], dropdown: classes?.dropdown }}
bind:search={langCode}
onItemClicked={(res) => {
langCode = res.item.tag;
onLangCodeSelected?.(langCode);
}}
{dropdownClasses}
bind:inputElement={typeaheadInput}
>
<!-- This is a convenience option and unnecessary for a11y -->
Expand Down
75 changes: 54 additions & 21 deletions src/lib/components/LocaleSelector.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
<script lang="ts">
import Dropdown from './Dropdown.svelte';
import IconContainer from './IconContainer.svelte';
import { LanguageIcon } from '$lib/icons';
import { l10nMap } from '$lib/locales.svelte';
import { type Locale, getLocale, locales, setLocale } from '$lib/paraglide/runtime';

function getFlag(locale: Locale) {
<script lang="ts" module>
export function getFlag(locale: Locale) {
switch (locale) {
case 'en-US':
return 'us';
Expand All @@ -20,26 +14,65 @@
}
</script>

<script lang="ts">
import type { Snippet } from 'svelte';
import type { ClassValue } from 'svelte/elements';
import Dropdown from './Dropdown.svelte';
import IconContainer from './IconContainer.svelte';
import { LanguageIcon } from '$lib/icons';
import { l10nMap } from '$lib/locales.svelte';
import { type Locale, getLocale, locales, setLocale } from '$lib/paraglide/runtime';

interface Props {
label?: Snippet;
class?: {
dropdown?: ClassValue;
label?: ClassValue;
};
currentLocale?: () => Locale;
onselect?: (lang: Locale) => void;
}

let {
label = globe,
class: classes = {},
currentLocale = getLocale,
onselect = setLocale
}: Props = $props();

let open = $state(false);

function onclick(locale: Locale) {
open = false;
onselect?.(locale);
}
</script>

{#snippet globe()}
<LanguageIcon color="white" />
{/snippet}

{#key getLocale()}
{@const langMap = l10nMap.value.get(getLocale())?.get('languages')}
<Dropdown
dropdownClasses="dropdown-end"
labelClasses="m-2 p-2 rounded-xl items-middle justify-center flex-nowrap"
contentClasses="overflow-y-auto min-w-52"
class={{
...classes,
content: 'overflow-y-auto min-w-52'
}}
bind:open
{label}
>
{#snippet label()}
<LanguageIcon color="white" />
{/snippet}
{#snippet content()}
<ul class="menu menu-compact gap-1 p-2">
<ul class="menu menu-sm gap-1 p-2">
{#each locales as locale}
{@const langMap = l10nMap.value.get(getLocale())?.get('languages')}
<li class="w-full">
<div
class="btn flex-nowrap justify-start pl-2 pr-1"
class:bg-accent={locale === getLocale()}
class:text-accent-content={locale === getLocale()}
onclick={() => setLocale(locale)}
onkeypress={() => setLocale(locale)}
class={[
'btn flex-nowrap justify-start pl-2 pr-1',
locale === currentLocale() && 'bg-accent text-accent-content'
]}
onclick={() => onclick(locale)}
onkeypress={() => onclick(locale)}
role="button"
tabindex="0"
>
Expand Down
8 changes: 4 additions & 4 deletions src/lib/components/OrganizationDropdown.svelte
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<script lang="ts">
import type { HTMLSelectAttributes } from 'svelte/elements';
import type { ClassValue, HTMLSelectAttributes } from 'svelte/elements';
import { org_allOrganizations } from '$lib/paraglide/messages';
import { getLocale } from '$lib/paraglide/runtime';
import { byName } from '$lib/utils/sorting';
interface Props {
organizations: { Id: number; Name: string | null }[];
value: number | null;
className?: string;
class?: ClassValue;
allowNull?: boolean;
selectProperties?: HTMLSelectAttributes;
}

let {
organizations,
value = $bindable(),
className = '',
class: classes,
allowNull = false,
selectProperties = {}
}: Props = $props();
Expand All @@ -26,7 +26,7 @@
});
</script>

<select class="select select-bordered {className}" bind:value {...selectProperties}>
<select class={['select', classes]} bind:value {...selectProperties}>
{#if organizations.length === 1}
<option selected value={organizations[0].Id}>{organizations[0].Name}</option>
{:else}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/Pagination.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
{m.common_total({ total })}
</div>
<div class="grow">&nbsp;</div>
<select class="select select-bordered" name="size" bind:value={size}>
<select class="select" name="size" bind:value={size}>
{#each [10, 25, 50, 100].concat(extraSizeOptions).toSorted((a, b) => a - b) as value}
<option {value}>{value}</option>
{/each}
Expand Down
7 changes: 4 additions & 3 deletions src/lib/components/SearchBar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@

<script lang="ts">
import { onDestroy } from 'svelte';
import type { ClassValue } from 'svelte/elements';
import IconContainer from './IconContainer.svelte';
import { m } from '$lib/paraglide/messages';

interface Props {
className?: string;
class?: ClassValue;
value: string;
requestSubmit?: () => void;
requestDelay?: number;
}

let {
className = '',
class: classes,
value = $bindable(),
requestSubmit,
requestDelay = 1_000
Expand All @@ -33,7 +34,7 @@
});
</script>

<div class={className} data-html="true">
<div class={[classes]} data-html="true">
<label class="input input-bordered flex items-center gap-2 w-full">
<input
type="search"
Expand Down
11 changes: 6 additions & 5 deletions src/lib/components/SortTable.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
-->
<script lang="ts" generics="RowItem extends Record<string, unknown>">
import type { Snippet } from 'svelte';
import type { ClassValue } from 'svelte/elements';
import { ArrowDownIcon, ArrowUpIcon } from '$lib/icons';

interface Props {
Expand All @@ -19,9 +20,9 @@
* If `serverSide` is `true`, just use a dummy function like `() => 0`
*/
compare?: (a: RowItem, b: RowItem) => number;
className?: string;
class?: ClassValue;
}[];
className?: string;
class?: ClassValue;
/** If this is true, will defer sorting to the server instead */
serverSide?: boolean;
onSort?: (field: string, direction: 'asc' | 'desc') => void;
Expand All @@ -32,7 +33,7 @@
let {
data = $bindable(),
columns,
className = '',
class: classes,
serverSide = false,
onSort,
row,
Expand Down Expand Up @@ -76,13 +77,13 @@
}
</script>

<div class="overflow-y {className}">
<div class={[classes]}>
<table class="table" class:table-fixed={fixedLayout}>
<thead>
<tr>
{#each columns as c}
<th
class={c.className ?? ''}
class={[c.class]}
onclick={() => {
if (c.compare) {
sortColByDirection(c);
Expand Down
Loading
Loading