kopia lustrzana https://github.com/learn-awesome/learndb
conflict resolved
commit
1004a2a4d7
|
@ -12,10 +12,11 @@
|
||||||
import ItemDetail from "./ItemDetail.svelte"
|
import ItemDetail from "./ItemDetail.svelte"
|
||||||
import ItemList from "./ItemList.svelte"
|
import ItemList from "./ItemList.svelte"
|
||||||
import AdvancedSearch from "./AdvancedSearch.svelte"
|
import AdvancedSearch from "./AdvancedSearch.svelte"
|
||||||
import { SearchIcon } from "@rgossiaux/svelte-heroicons/outline";
|
import { SearchIcon, CogIcon, BookmarkAltIcon, BookmarkIcon } from "@rgossiaux/svelte-heroicons/outline";
|
||||||
|
|
||||||
let currentView = "/topics";
|
let currentView = "/topics";
|
||||||
let randomItemId;
|
let randomItemId;
|
||||||
|
let alltopics = [];
|
||||||
|
|
||||||
function getRandomItemId(){
|
function getRandomItemId(){
|
||||||
fetch('/learn.json?_shape=array&sql=select+rowid+from+items+order+by+random()+limit+1').then(r => r.json())
|
fetch('/learn.json?_shape=array&sql=select+rowid+from+items+order+by+random()+limit+1').then(r => r.json())
|
||||||
|
@ -24,6 +25,12 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: fetch(`/learn/topics.json?_shape=array&_size=5000`)
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
alltopics = data;
|
||||||
|
});
|
||||||
|
|
||||||
async function hashchange() {
|
async function hashchange() {
|
||||||
// the poor man's router!
|
// the poor man's router!
|
||||||
const path = window.location.hash.slice(1);
|
const path = window.location.hash.slice(1);
|
||||||
|
@ -46,14 +53,14 @@
|
||||||
|
|
||||||
<svelte:window on:hashchange={hashchange}/>
|
<svelte:window on:hashchange={hashchange}/>
|
||||||
|
|
||||||
<TailwindUI.AppShell>
|
<TailwindUI.AppShell {alltopics}>
|
||||||
<svelte:fragment slot="content">
|
<svelte:fragment slot="content">
|
||||||
{#if currentView === "/home" || currentView === "/"}
|
{#if currentView === "/home" || currentView === "/"}
|
||||||
<Home/>
|
<Home/>
|
||||||
{:else if currentView === "/game"}
|
{:else if currentView === "/game"}
|
||||||
<SkillTree/>
|
<SkillTree/>
|
||||||
{:else if currentView === "/topics"}
|
{:else if currentView === "/topics"}
|
||||||
<TopicList/>
|
<TopicList {alltopics}/>
|
||||||
{:else if currentView.startsWith("/topic/")}
|
{:else if currentView.startsWith("/topic/")}
|
||||||
<TopicDetail topicname={currentView.split("/").slice(2).join("/")}/>
|
<TopicDetail topicname={currentView.split("/").slice(2).join("/")}/>
|
||||||
{:else if currentView === "/formats"}
|
{:else if currentView === "/formats"}
|
||||||
|
@ -93,18 +100,19 @@
|
||||||
Search
|
Search
|
||||||
</a>
|
</a>
|
||||||
<hr/>
|
<hr/>
|
||||||
<a href="#/wanttolearn" class={(currentView === "/wanttolearn" ? 'bg-gray-900' : '') + " text-white w-full hover:bg-gray-900 group flex items-center px-2 py-2 text-sm font-medium rounded-md"}>
|
<a href="#/wanttolearn" class={(currentView === "/wanttolearn" ? 'bg-indigo-800' : '') + " text-white w-full hover:bg-indigo-600 group flex items-center px-2 py-2 text-sm font-medium rounded-md"}>
|
||||||
<SearchIcon class="mr-4 flex-shrink-0 h-6 w-6 text-indigo-300"/>
|
<BookmarkIcon class="mr-4 flex-shrink-0 h-6 w-6 text-indigo-300"/>
|
||||||
Want to learn
|
Want to learn
|
||||||
</a>
|
</a>
|
||||||
<a href="#/finishedlearning" class={(currentView === "/finishedlearning" ? 'bg-gray-900' : '') + " text-white w-full hover:bg-gray-900 group flex items-center px-2 py-2 text-sm font-medium rounded-md"}>
|
<a href="#/finishedlearning" class={(currentView === "/finishedlearning" ? 'bg-indigo-800' : '') + " text-white w-full hover:bg-indigo-600 group flex items-center px-2 py-2 text-sm font-medium rounded-md"}>
|
||||||
<SearchIcon class="mr-4 flex-shrink-0 h-6 w-6 text-indigo-300"/>
|
<BookmarkAltIcon class="mr-4 flex-shrink-0 h-6 w-6 text-indigo-300"/>
|
||||||
Finished learning
|
Finished learning
|
||||||
</a>
|
</a>
|
||||||
<hr/>
|
<hr/>
|
||||||
<a href="/learn" class="text-indigo-100 hover:bg-gray-900 w-full group flex items-center px-2 py-2 text-sm font-medium rounded-md">
|
<a href="/learn" class="text-indigo-100 hover:bg-indigo-600 w-full group flex items-center px-2 py-2 text-sm font-medium rounded-md">
|
||||||
<SearchIcon class="mr-4 flex-shrink-0 h-6 w-6 text-indigo-300"/>
|
<CogIcon class="mr-4 flex-shrink-0 h-6 w-6 text-indigo-300"/>
|
||||||
Datasette
|
Datasette
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</TailwindUI.AppShell>
|
</TailwindUI.AppShell>
|
|
@ -1,90 +1,78 @@
|
||||||
<script>
|
<script>
|
||||||
import ZoomSvg from '@svelte-parts/zoom/svg'
|
import { scale } from 'svelte/transition';
|
||||||
import { fly } from 'svelte/transition';
|
import { cubicIn } from 'svelte/easing';
|
||||||
|
|
||||||
|
let graph = {
|
||||||
let sidePanelShown = true;
|
name: "Top",
|
||||||
let currentNode = null;
|
children: [
|
||||||
let nodes = [
|
{name: "first", children: [
|
||||||
{id: 1, name: "test", x: 100, y: 200, size: 50, color: "#ff3e00"},
|
{name: "first -> A", children: [], color: "red-500"},
|
||||||
{id: 2, name: "second", x: 400, y: 300, size: 30, color: "#ff3eff"}
|
{name: "first -> B", children: [], color: "green-500"},
|
||||||
]
|
{name: "first -> c", children: [], color: "yellow-500"},
|
||||||
|
{name: "first -> d", children: [], color: "blue-500"},
|
||||||
let edges = [
|
], pos: [], size: 35, color: "green-300"},
|
||||||
{id: 1, from: nodes[0], to: nodes[1]}
|
{name: "second", children: [], pos: [], size: 35, color: "red-500"},
|
||||||
]
|
{name: "third", children: [], pos: [], size: 35, color: "yellow-500"},
|
||||||
|
{name: "fourth", children: [], pos: [], size: 35, color: "teal-400"},
|
||||||
function handleNodeMouseEnter(ev){
|
]
|
||||||
ev.target.style.fill = "#aa3e00"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleNodeMouseLeave(ev){
|
let currentParent = null;
|
||||||
ev.target.style.fill = "#ff3e00"
|
let currentChild = graph;
|
||||||
}
|
|
||||||
|
function findParent(child, tree){
|
||||||
function handleNodeClick(ev){
|
if(graph == child) return null;
|
||||||
sidePanelShown = true;
|
if(tree.children.indexOf(child) > -1) return tree;
|
||||||
currentNode = ev.target;
|
// Will have to look at grandchildren
|
||||||
}
|
tree.children.forEach(c => {
|
||||||
|
let x = findParent(child, c);
|
||||||
|
if (x != -1) return c;
|
||||||
|
});
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function switchTo(parent, child){
|
||||||
|
[currentParent, currentChild] = [parent, child];
|
||||||
|
}
|
||||||
|
|
||||||
|
function siblings(parent, child){
|
||||||
|
if(!parent) return [];
|
||||||
|
return parent.children.filter(n => n != child)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-col">
|
||||||
|
|
||||||
<ZoomSvg viewBox="0 0 1200 900">
|
{#if currentParent}<div class="flex flex-row justify-center mb-4">
|
||||||
|
<span>
|
||||||
|
<button type="button" on:click="{ e => switchTo(findParent(currentParent, graph), currentParent) }" class="inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
|
||||||
|
{currentParent.name}
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>{/if}
|
||||||
|
|
||||||
{#each edges as edge}
|
<h2 class="text-3xl my-4 text-center font-extrabold tracking-tight sm:text-4xl">{currentChild.name}</h2>
|
||||||
<line x1={edge.from.x} y1={edge.from.y} x2={edge.to.x} y2={edge.to.y} stroke="black" stroke-width="5" />
|
|
||||||
{/each}
|
|
||||||
|
|
||||||
{#each nodes as node}
|
|
||||||
<circle cx={node.x} cy={node.y} r={node.size} fill={node.color} on:mouseenter={handleNodeMouseEnter} on:mouseleave={handleNodeMouseLeave} on:click={handleNodeClick}/>
|
|
||||||
{/each}
|
|
||||||
|
|
||||||
<g>
|
<div class="flex flex-row justify-center my-4">
|
||||||
<rect x="120" y="320" width="100" height="100" fill="none" stroke="black" rx="15" />
|
<span class="relative z-0 inline-flex shadow-sm rounded-md">
|
||||||
<text x="400" y="150" font-family="Verdana" font-size="85" fill="green" stroke="yellow">Hello</text>
|
{#each siblings(currentParent, currentChild) as sibling}
|
||||||
</g>
|
<button type="button" on:click="{ e => switchTo(currentParent, sibling) }" class="relative inline-flex items-center px-4 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:z-10 focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500">
|
||||||
|
{sibling.name}
|
||||||
</ZoomSvg>
|
</button>
|
||||||
|
{/each}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="relative z-10" aria-labelledby="slide-over-title" role="dialog" aria-modal="true">
|
<div class="grid grid-cols-1 gap-y-0 sm:grid-cols-2 mt-4">
|
||||||
<!-- Background backdrop, show/hide based on slide-over state. -->
|
{#each currentChild.children as grandchild, i (grandchild)}
|
||||||
{#if sidePanelShown}
|
<button on:click="{ e => switchTo(currentChild, grandchild) }" class="h-96 bg-{grandchild.color} hover:opacity-80 hover:scale-105">
|
||||||
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"></div>
|
<h3>{grandchild.name}</h3>
|
||||||
{/if}
|
</button>
|
||||||
|
{/each}
|
||||||
<div class="fixed inset-0 overflow-hidden">
|
</div>
|
||||||
<div class="absolute inset-0 overflow-hidden">
|
|
||||||
<div class="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10">
|
|
||||||
{#if sidePanelShown}
|
|
||||||
<div class="pointer-events-auto w-screen max-w-md" transition:fly="{{ x: 200, duration: 600 }}">
|
|
||||||
<div class="flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl">
|
|
||||||
<div class="px-4 sm:px-6">
|
|
||||||
<div class="flex items-start justify-between">
|
|
||||||
<h2 class="text-lg font-medium text-gray-900" id="slide-over-title">Panel title</h2>
|
|
||||||
<div class="ml-3 flex h-7 items-center">
|
|
||||||
<button on:click="{e => sidePanelShown = false}" type="button" class="rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
|
|
||||||
<span class="sr-only">Close panel</span>
|
|
||||||
<!-- Heroicon name: outline/x -->
|
|
||||||
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="relative mt-6 flex-1 px-4 sm:px-6">
|
|
||||||
<!-- Replace with your content -->
|
|
||||||
<div class="absolute inset-0 px-4 sm:px-6">
|
|
||||||
<div class="h-full border-2 border-dashed border-gray-200" aria-hidden="true"></div>
|
|
||||||
</div>
|
|
||||||
<!-- /End replace -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import TopicMasonryGrid from "./TopicMasonryGrid.svelte"
|
import TopicMasonryGrid from "./TopicMasonryGrid.svelte"
|
||||||
|
export let alltopics;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<TopicMasonryGrid />
|
<TopicMasonryGrid {alltopics}/>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
export let topicname; // undefined for top level
|
export let topicname; // undefined for top level
|
||||||
let topic;
|
let topic;
|
||||||
let alltopics = [];
|
export let alltopics;
|
||||||
let map = new Map();
|
let map = new Map();
|
||||||
|
|
||||||
function capitalize(str){
|
function capitalize(str){
|
||||||
|
@ -59,12 +59,7 @@
|
||||||
return tempmap;
|
return tempmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
$: fetch(`/learn/topics.json?_shape=array&_size=5000`)
|
$: topic = alltopics.find(t => t.name == topicname)
|
||||||
.then(r => r.json())
|
|
||||||
.then(data => {
|
|
||||||
topic = data.find(t => t.name == topicname)
|
|
||||||
alltopics = data;
|
|
||||||
});
|
|
||||||
|
|
||||||
$: map = hierarchy(alltopics, topic?.name || "")
|
$: map = hierarchy(alltopics, topic?.name || "")
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
let isNavDrawerOpen = false
|
let isNavDrawerOpen = false
|
||||||
export let showNotificationBell = false;
|
export let showNotificationBell = false;
|
||||||
export let showProfileMenu = false;
|
export let showProfileMenu = false;
|
||||||
|
export let alltopics;
|
||||||
|
import SearchForm from "./SearchForm.svelte"
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -87,12 +89,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="md:pl-64 flex flex-col flex-1">
|
<div class="md:pl-64 flex flex-col flex-1">
|
||||||
<div class="sticky top-0 z-10 flex-shrink-0 flex h-16 bg-cyan-900 text-white shadow">
|
<div class="sticky top-0 z-10 flex-shrink-0 flex bg-cyan-900 text-white shadow">
|
||||||
<button on:click={e => isNavDrawerOpen = true} type="button" class="px-4 border-r border-gray-200 text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500 md:hidden">
|
<button on:click={e => isNavDrawerOpen = true} type="button" class="px-4 border-r border-gray-200 text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500 md:hidden">
|
||||||
<span class="sr-only">Open sidebar</span>
|
<span class="sr-only">Open sidebar</span>
|
||||||
<Icon kind="menu"/>
|
<Icon kind="menu"/>
|
||||||
</button>
|
</button>
|
||||||
<div class="flex-1 px-4 flex justify-between">
|
<div class="flex-1 flex justify-between">
|
||||||
|
<SearchForm {alltopics}/>
|
||||||
{#if showNotificationBell || showProfileMenu}
|
{#if showNotificationBell || showProfileMenu}
|
||||||
<div class="ml-4 flex items-center md:ml-6">
|
<div class="ml-4 flex items-center md:ml-6">
|
||||||
{#if showNotificationBell}
|
{#if showNotificationBell}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
<script>
|
||||||
|
export let options = [];
|
||||||
|
export let selected = {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="relative ml-2">
|
||||||
|
<input type="text" class="w-full rounded-md border border-gray-300 bg-white py-2 pl-3 pr-12 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 sm:text-sm" role="combobox" aria-controls="options" aria-expanded="false" value={selected && selected.label}>
|
||||||
|
<button type="button" class="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none">
|
||||||
|
<!-- Heroicon name: solid/selector -->
|
||||||
|
<svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||||
|
<path fill-rule="evenodd" d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<ul class="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm" id="options" role="listbox">
|
||||||
|
{#each options as option}
|
||||||
|
<!--
|
||||||
|
Combobox option, manage highlight styles based on mouseenter/mouseleave and keyboard navigation.
|
||||||
|
|
||||||
|
Active: "text-white bg-indigo-600", Not Active: "text-gray-900"
|
||||||
|
-->
|
||||||
|
<li class="relative cursor-default select-none py-2 pl-3 pr-9 text-gray-900" role="option" tabindex="-1">
|
||||||
|
<!-- Selected: "font-semibold" -->
|
||||||
|
<span class={(selected && selected.value == option.value ? 'font-semibold' : '') + ' block truncate'}>{option.label}</span>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Checkmark, only display for selected option.
|
||||||
|
|
||||||
|
Active: "text-white", Not Active: "text-indigo-600"
|
||||||
|
-->
|
||||||
|
{#if selected && selected.value == option.value}
|
||||||
|
<span class="absolute inset-y-0 right-0 flex items-center pr-4 text-indigo-600">
|
||||||
|
<!-- Heroicon name: solid/check -->
|
||||||
|
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||||
|
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,6 +1,15 @@
|
||||||
<script>
|
<script>
|
||||||
import Icon from "./Icon.svelte"
|
import Icon from "./Icon.svelte"
|
||||||
let query;
|
import ComboBox from "./ComboBox.svelte"
|
||||||
|
export let alltopics;
|
||||||
|
|
||||||
|
let query = {
|
||||||
|
text: "some text",
|
||||||
|
topic: "algebra",
|
||||||
|
format: "book",
|
||||||
|
level: "beginner",
|
||||||
|
sortby: ""
|
||||||
|
};
|
||||||
let results = [];
|
let results = [];
|
||||||
|
|
||||||
function handleSubmit(ev){
|
function handleSubmit(ev){
|
||||||
|
@ -8,31 +17,35 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<form class="w-full flex md:ml-0" on:submit|preventDefault={handleSubmit}>
|
<form class="w-full bg-gray-100 p-2 inline-flex" on:submit|preventDefault={handleSubmit}>
|
||||||
<label for="search-field" class="sr-only">Search</label>
|
<sl-input type="search" placeholder="Type something to search items by keywords" size="medium" clearable class="flex-1 border-0 p-0 focus:ring-0" value={query.text} on:sl-input="{e => query.text = e.target.value}">
|
||||||
<div class="relative w-full text-gray-400 focus-within:text-gray-600">
|
<sl-icon name="search" slot="prefix"></sl-icon>
|
||||||
<div class="absolute inset-y-0 left-0 flex items-center pointer-events-none">
|
</sl-input>
|
||||||
<Icon kind="search"/>
|
|
||||||
</div>
|
<ComboBox options={alltopics.map(t => { return {label: t.display_name, value: t.name}; }).sort((a,b) => a.label.localeCompare(b.label))} selected={null}/>
|
||||||
<input bind:value={query} class="block w-full h-full pl-8 pr-3 py-2 border-transparent text-gray-900 placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-0 focus:border-transparent sm:text-sm" placeholder="Search" type="search" name="search">
|
|
||||||
</div>
|
<sl-select class="ml-2 w-44" on:sl-change="{e => query.format = e.target.value}" value={query.format}>
|
||||||
|
<sl-menu-item value="">Any format</sl-menu-item>
|
||||||
|
<sl-menu-item value="book">Books</sl-menu-item>
|
||||||
|
<sl-menu-item value="video">Videos</sl-menu-item>
|
||||||
|
<sl-menu-item value="audio">Podcasts</sl-menu-item>
|
||||||
|
</sl-select>
|
||||||
|
|
||||||
|
<sl-select class="ml-2 w-44" on:sl-change="{e => query.level = e.target.value}" value={query.level}>
|
||||||
|
<sl-menu-item value="">Any level</sl-menu-item>
|
||||||
|
<sl-menu-item value="childlike">Childlike</sl-menu-item>
|
||||||
|
<sl-menu-item value="beginner">Beginner</sl-menu-item>
|
||||||
|
<sl-menu-item value="intermediate">Intermediate</sl-menu-item>
|
||||||
|
<sl-menu-item value="advanced">Advanced</sl-menu-item>
|
||||||
|
<sl-menu-item value="research">Research</sl-menu-item>
|
||||||
|
</sl-select>
|
||||||
|
|
||||||
|
<sl-select class="ml-2 w-44" on:sl-change="{e => query.sortby = e.target.value}" value={query.sortby}>
|
||||||
|
<sl-icon name="sort-down-alt" slot="prefix"></sl-icon>
|
||||||
|
<sl-menu-item value="">Sort by</sl-menu-item>
|
||||||
|
<sl-menu-item value="rating">Rating</sl-menu-item>
|
||||||
|
<sl-menu-item value="year">Year</sl-menu-item>
|
||||||
|
<sl-menu-item value="name">Name</sl-menu-item>
|
||||||
|
</sl-select>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<ul class="max-h-80 scroll-pt-11 scroll-pb-2 space-y-2 overflow-y-auto pb-2" id="options" role="listbox">
|
|
||||||
<li>
|
|
||||||
<h2 class="bg-gray-100 py-2.5 px-4 text-xs font-semibold text-gray-900">Clients</h2>
|
|
||||||
<ul class="mt-2 text-sm text-gray-800">
|
|
||||||
<!-- Active: "bg-indigo-600 text-white" -->
|
|
||||||
<li class="cursor-default select-none px-4 py-2" id="option-1" role="option" tabindex="-1">Workflow Inc.</li>
|
|
||||||
<li class="cursor-default select-none px-4 py-2" id="option-2" role="option" tabindex="-1">Multinational LLC.</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h2 class="bg-gray-100 py-2.5 px-4 text-xs font-semibold text-gray-900">Projects</h2>
|
|
||||||
<ul class="mt-2 text-sm text-gray-800">
|
|
||||||
<!-- Active: "bg-indigo-600 text-white" -->
|
|
||||||
<li class="cursor-default select-none px-4 py-2" id="option-3" role="option" tabindex="-1">Workflow Inc. / Website Redesign</li>
|
|
||||||
<li class="cursor-default select-none px-4 py-2" id="option-3" role="option" tabindex="-1">Multinational LLC. / Animation</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
Ładowanie…
Reference in New Issue