Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
62 changes: 62 additions & 0 deletions src/lib/components/Dropdown/Dropdown.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<script lang="ts">
import Fa from 'svelte-fa';
import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
import { dropdownVariants, type DropdownProps } from '../../../styles/tailwind/dropdown';
import DropdownList from '$lib/components/Dropdown/DropdownList.svelte';
import { onMount } from 'svelte';

export let items: string[] = [];
export let currentChoice: string | null = null;
export let outerClass: string = '';
let isOpen = false;
let hasSelected = false;
let currentVariant: DropdownProps['variant'] = 'transparent';
let placeholder: string = 'Select Item';
let saveChoice: string | null = null;

onMount(() => {
currentChoice = items[0] || placeholder;
saveChoice = currentChoice;
});

$: {
if (isOpen) {
currentVariant = 'focus';
} else if (hasSelected) {
currentVariant = 'default';
} else {
currentVariant = 'transparent';
}
}

$: dropdownClass = dropdownVariants({ variant: currentVariant });

$: if (currentChoice) {
isOpen = false;
if (currentChoice !== saveChoice) {
hasSelected = true;
}
}

function handleClickOpen() {
isOpen = !isOpen;
}

$: console.log(isOpen);
</script>

<div class={`relative w-full ${outerClass}`}>
<button
class={`w-full px-4 py-3 flex flex-row justify-between items-center rounded-sm ${dropdownClass}`}
on:click={handleClickOpen}
>
<span>{currentChoice || placeholder}</span>
<Fa icon={faChevronDown} class={`w-6 h-6 transition-transform ${isOpen && 'rotate-180'}`} />
</button>

{#if isOpen}
<div class="absolute top-[calc(100%+8px)] w-full">
<DropdownList bind:items bind:currentChoice />
</div>
{/if}
</div>
51 changes: 51 additions & 0 deletions src/lib/components/Dropdown/DropdownItem.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<script lang="ts">
import {
dropdownItemVariants,
type DropdownItemProps
} from '../../../styles/tailwind/dropdownItem';

export let text: string;
export let disabled: boolean = false;
export let currentSelectedChoice: string | null = null;

let currentVariant: DropdownItemProps['variant'] = 'default';
let isHover: boolean = false;
let isSelected = false;

$: isSelected = currentSelectedChoice === text;

$: {
if (disabled) {
currentVariant = 'disabled';
} else if (isHover) {
currentVariant = 'hover';
} else if (isSelected) {
currentVariant = 'pressed';
} else {
currentVariant = 'default';
}
}

function handleClick() {
isHover = false;
currentSelectedChoice = text;
}
function handleMouseEnter() {
if (currentVariant === 'default') isHover = true;
}
function handleMouseLeave() {
isHover = false;
}

$: dropdownClass = dropdownItemVariants({ variant: isHover ? 'hover' : currentVariant });
</script>

<button
class={dropdownClass}
on:click={handleClick}
on:mouseenter={handleMouseEnter}
on:mouseleave={handleMouseLeave}
{disabled}
>
{text}
</button>
14 changes: 14 additions & 0 deletions src/lib/components/Dropdown/DropdownList.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script lang="ts">
import DropdownItem from '$lib/components/Dropdown/DropdownItem.svelte';

export let items: string[] = ['Hi', 'jpoas', 'adfsd', 'asdafsds'];
export let currentChoice: string | null = null;
</script>

<div
class="flex flex-col outline outline-1 outline-sucu-gray rounded-sm gap-1 overflow-hidden bg-white"
>
{#each items as item}
<DropdownItem text={item} bind:currentSelectedChoice={currentChoice} />
{/each}
</div>
45 changes: 45 additions & 0 deletions src/lib/components/Playground.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
import TabCapsuleItem from './TabCapsule.svelte';
import Modal from '$lib/components/Modal/Modal.svelte';
import { modalShow } from './Modal/store';
import DropdownItem from '$lib/components/Dropdown/DropdownItem.svelte';
import SearchBar from '$lib/components/SearchBar.svelte';
import DropdownList from '$lib/components/Dropdown/DropdownList.svelte';
import Dropdown from '$lib/components/Dropdown/Dropdown.svelte';

modalShow.set(false);

Expand Down Expand Up @@ -54,6 +58,11 @@
? [...selectedTabs, tab.label]
: selectedTabs.filter((label) => label !== tab.label);
}

let searchValue = '';
let listValue: string | null = null;
let dropdownValue: string | null = null;
let choiceList: string[] = ['ล่าสุด', 'ปี 2567', 'ปี 2566', 'ปี 2565', 'ปี 2564'];
</script>

<div>
Expand Down Expand Up @@ -158,6 +167,42 @@
<Modal />
{/if}
</section>

<section class="section">
<h2 class="font-bold text-2xl mb-4">Search & Dropdown</h2>

<div class="flex flex-col gap-4">
<div class="flex flex-col gap-2">
<h3 class="font-semibold text-xl">SearchBar</h3>
<SearchBar bind:value={searchValue} />
<p>Search Value : {searchValue == '' ? 'no value' : searchValue}</p>
</div>

<div class="flex flex-col gap-2">
<h3 class="font-semibold text-xl mb-2">DropdownItem</h3>

<div>
<DropdownItem text="Hello"></DropdownItem>
<DropdownItem text="Hello" disabled></DropdownItem>
</div>
</div>

<div class="flex flex-col gap-2">
<h3 class="font-semibold text-xl mb-2">DropdownList</h3>

<DropdownList bind:currentChoice={listValue} items={choiceList} />
<p>List Value : {listValue || 'no value'}</p>
</div>

<div class="flex flex-col gap-2">
<h3 class="font-semibold text-xl mb-2">Dropdown</h3>

<Dropdown items={choiceList} bind:currentChoice={dropdownValue} outerClass="w-64" />

<p>Dropdown Value : {dropdownValue || 'no value'}</p>
</div>
</div>
</section>
</div>

<style>
Expand Down
36 changes: 36 additions & 0 deletions src/lib/components/SearchBar.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script lang="ts">
import { faSearch } from '@fortawesome/free-solid-svg-icons';
import Fa from 'svelte-fa';

export let value: string;
let inputRef: HTMLInputElement;
let isFocus = false;
function handleFocus() {
isFocus = true;
}
function handleBlur() {
isFocus = false;
}

function handleClickIcon() {
inputRef.focus();
}
</script>

<div
class={`w-full flex flex-row items-center gap-3 px-4 py-3 rounded-sm border ${isFocus ? 'border-sucu-pink-03' : 'border-sucu-gray-light'}`}
>
<button on:click={handleClickIcon}>
<Fa icon={faSearch} class="w-5 h-5" />
</button>

<input
type="text"
class="w-full text-black focus:border-none focus:outline-none"
placeholder="ค้นหา"
bind:value
bind:this={inputRef}
on:focus={handleFocus}
on:blur={handleBlur}
/>
</div>
22 changes: 22 additions & 0 deletions src/styles/tailwind/dropdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { tv, type VariantProps } from 'tailwind-variants';
import { typography } from './typography';

export const dropdownVariants = tv({
base: `w-full ${typography({ variant: 'body-normal' })} transition-colors duration-200 px-4 py-2 text-left`,
variants: {
variant: {
default: `text-sucu-gray-dark border border-sucu-gray`,
focus: `text-sucu-gray border border-sucu-pink-03`,
transparent: `text-sucu-gray-light border border-sucu-gray-light`
}
},
defaultVariants: {
variant: 'default'
}
});

export type Variant = VariantProps<typeof dropdownVariants>['variant'];

export type DropdownProps = {
variant?: Variant;
};
23 changes: 23 additions & 0 deletions src/styles/tailwind/dropdownItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { tv, type VariantProps } from 'tailwind-variants';
import { typography } from './typography';

export const dropdownItemVariants = tv({
base: `w-full ${typography({ variant: 'body-normal' })} transition-colors duration-200 px-4 py-2 text-left`,
variants: {
variant: {
default: `bg-white text-black`,
hover: `bg-sucu-pink-05 text-sucu-pink-01`,
pressed: `bg-sucu-pink-01 text-white`,
disabled: `bg-white text-sucu-gray-dark`
}
},
defaultVariants: {
variant: 'default'
}
});

export type Variant = VariantProps<typeof dropdownItemVariants>['variant'];

export type DropdownItemProps = {
variant?: Variant;
};
Loading