Skip to content

Commit

Permalink
feat(tooltip): rework tooltip and input sizing api
Browse files Browse the repository at this point in the history
  • Loading branch information
dvcol committed Feb 6, 2025
1 parent 5839709 commit 7090740
Show file tree
Hide file tree
Showing 18 changed files with 373 additions and 118 deletions.
15 changes: 5 additions & 10 deletions demo/components/DemoButtons.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import NeoRadioButton from '~/buttons/NeoRadioButton.svelte';
import NeoSwitchButton from '~/buttons/NeoSwitchButton.svelte';
import IconAccount from '~/icons/IconAccount.svelte';
import NeoNativeSelect from '~/inputs/NeoNativeSelect.svelte';
import NeoSelect from '~/inputs/NeoSelect.svelte';
import { Colors } from '~/utils/colors.utils';
const { onClick, loading: isLoading, onLoading } = useButtonState('DemoButtonClick');
Expand Down Expand Up @@ -87,20 +87,15 @@
<NeoButton toggle bind:checked={options.skeleton}>Skeleton</NeoButton>
</NeoButtonGroup>

<NeoNativeSelect
<NeoSelect
label="Color"
placeholder="Select color"
position="left"
floating={false}
size="10"
bind:value={options.color}
containerProps={{ style: 'margin-left: 6rem' }}
options={[
{ value: '', label: 'default' },
{ value: Colors.Primary },
{ value: Colors.Secondary },
{ value: Colors.Success },
{ value: Colors.Warning },
{ value: Colors.Error },
]}
options={[Colors.Primary, Colors.Secondary, Colors.Success, Colors.Warning, Colors.Error]}
/>
</div>
</div>
Expand Down
14 changes: 9 additions & 5 deletions demo/components/DemoInputs.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import type { NeoFilePickerProps } from '~/inputs/neo-file-picker.model.js';
import type { NeoRangeHTMLElement } from '~/inputs/neo-range.model.js';
import type { NeoNativeSelectOption } from '~/inputs/neo-select.model.js';
import type { NeoListItem } from '~/list/neo-list.model.js';
import NeoButton from '~/buttons/NeoButton.svelte';
Expand Down Expand Up @@ -481,6 +482,12 @@
},
];
const nativeSelectOptions: NeoNativeSelectOption[] = [
{ value: 'value 1', label: 'Label for value 1' },
{ value: 'value 2', label: 'Label for value 2' },
'value 3',
];
const items: NeoListItem = [
{ value: 'value 1', label: 'Label for value 1' },
{ value: 'value 2', label: 'Label for value 2' },
Expand Down Expand Up @@ -648,18 +655,15 @@
required
multiple
label="Native Multiple Select"
options={nativeSelectOptions}
bind:ref={selectMultipleState.ref}
bind:touched={selectMultipleState.touched}
bind:dirty={selectMultipleState.dirty}
bind:valid={selectMultipleState.valid}
bind:value={selectMultipleState.value}
{...options}
size={undefined}
>
<option value="value 1">Label for value 1</option>
<option value="value 2">Label for value 2</option>
<option value="value 3">Label for value 3</option>
</NeoNativeSelect>
/>
</SphereBackdrop>
</div>
</div>
Expand Down
138 changes: 87 additions & 51 deletions demo/components/DemoTooltips.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
import { getUUID } from '@dvcol/common-utils/common/string';
import { height } from '@dvcol/svelte-utils/transition';
import type { NeoListSelectedItem } from '~';
import type { NeoTooltipProps } from '~/tooltips/neo-tooltip.model';
import NeoButton from '~/buttons/NeoButton.svelte';
import NeoButtonGroup from '~/buttons/NeoButtonGroup.svelte';
import IconAccount from '~/icons/IconAccount.svelte';
import NeoNativeSelect from '~/inputs/NeoNativeSelect.svelte';
import NeoNumberStep from '~/inputs/NeoNumberStep.svelte';
import NeoSelect from '~/inputs/NeoSelect.svelte';
import NeoInput from '~/inputs/common/NeoInput.svelte';
import NeoListBaseItem from '~/list/NeoListBaseItem.svelte';
import NeoPopSelect from '~/tooltips/NeoPopSelect.svelte';
import NeoTooltip from '~/tooltips/NeoTooltip.svelte';
Expand Down Expand Up @@ -46,50 +48,65 @@
{ value: 'left-end', label: 'Left End' },
];
const items = $state(
[
{ label: 'John Doe', value: 'John', description: '[email protected]' },
{ label: 'Peter Jackson', value: 'Peter', description: '[email protected]' },
{ label: 'John Smith', value: 'Smith', description: '[email protected]' },
{ label: 'Alice Johnson', value: 'Alice', description: '[email protected]' },
{ label: 'Bob Brown', value: 'Bob', description: '[email protected]' },
{ label: 'Charlie Davis', value: 'Charlie', description: '[email protected]' },
{ label: 'Diana Evans', value: 'Diana', description: '[email protected]' },
{ label: 'Eve Foster', value: 'Eve', description: '[email protected]' },
{ label: 'Frank Green', value: 'Frank', description: '[email protected]' },
{ label: 'Grace Harris', value: 'Grace', description: '[email protected]' },
{ label: 'Henry Irving', value: 'Henry', description: '[email protected]' },
{ label: 'Ivy Johnson', value: 'Ivy', description: '[email protected]' },
{ label: 'Jack King', value: 'Jack', description: '[email protected]' },
{ label: 'Karen Lee', value: 'Karen', description: '[email protected]' },
{
label: 'Directors',
divider: true,
sticky: true,
items: [
{ label: 'Denis VVilleneuve', value: 'Denis', description: '+33 1 25 48 45 45' },
{ label: 'Christopher Nolan', value: 'Christopher', description: '+44 2 07 94 60 95' },
{ label: 'Quentin Tarantino', value: 'Quentin', description: '+33 1 05 55 12 34' },
{ label: 'Martin Scorsese', value: 'Martin', description: '+33 1 25 55 56 78' },
{ label: 'Steven Spielberg', value: 'Steven', description: '+33 1 85 55 87 65' },
].map(item => ({ ...item, id: getUUID(), before: avatar })),
},
{
label: 'Actors',
divider: true,
sticky: true,
items: [
{ label: 'Leonardo DiCaprio', value: 'Leonardo', description: '+1 310 555 1234' },
{ label: 'Brad Pitt', value: 'Brad', description: '+1 323 555 5678' },
{ label: 'Meryl Streep', value: 'Meryl', description: '+1 212 555 8765' },
{ label: 'Tom Hanks', value: 'Tom', description: '+1 310 555 4321' },
{ label: 'Natalie Portman', value: 'Natalie', description: '+1 818 555 6789' },
].map(item => ({ ...item, id: getUUID(), before: avatar })),
},
].map(item => ({ ...item, id: getUUID(), before: avatar })),
);
let selected = $state();
const simpleItems = [
'John Doe',
'Peter Jackson',
'John Smith',
'Alice Johnson',
'Bob Brown',
'Charlie Davis',
'Diana Evans',
'Eve Foster',
'Frank Green',
'Grace Harris',
'Henry Irving',
'Ivy Johnson',
];
let simpleSelected = $state<NeoListSelectedItem>();
const complexItems = [
{ label: 'John Doe', value: 'John', description: '[email protected]' },
{ label: 'Peter Jackson', value: 'Peter', description: '[email protected]' },
{ label: 'John Smith', value: 'Smith', description: '[email protected]' },
{ label: 'Alice Johnson', value: 'Alice', description: '[email protected]' },
{ label: 'Bob Brown', value: 'Bob', description: '[email protected]' },
{ label: 'Charlie Davis', value: 'Charlie', description: '[email protected]' },
{ label: 'Diana Evans', value: 'Diana', description: '[email protected]' },
{ label: 'Eve Foster', value: 'Eve', description: '[email protected]' },
{ label: 'Frank Green', value: 'Frank', description: '[email protected]' },
{ label: 'Grace Harris', value: 'Grace', description: '[email protected]' },
{ label: 'Henry Irving', value: 'Henry', description: '[email protected]' },
{ label: 'Ivy Johnson', value: 'Ivy', description: '[email protected]' },
{ label: 'Jack King', value: 'Jack', description: '[email protected]' },
{ label: 'Karen Lee', value: 'Karen', description: '[email protected]' },
{
label: 'Directors',
divider: true,
sticky: true,
items: [
{ label: 'Denis VVilleneuve', value: 'Denis', description: '+33 1 25 48 45 45' },
{ label: 'Christopher Nolan', value: 'Christopher', description: '+44 2 07 94 60 95' },
{ label: 'Quentin Tarantino', value: 'Quentin', description: '+33 1 05 55 12 34' },
{ label: 'Martin Scorsese', value: 'Martin', description: '+33 1 25 55 56 78' },
{ label: 'Steven Spielberg', value: 'Steven', description: '+33 1 85 55 87 65' },
].map(item => ({ ...item, id: getUUID(), before: avatar })),
},
{
label: 'Actors',
divider: true,
sticky: true,
items: [
{ label: 'Leonardo DiCaprio', value: 'Leonardo', description: '+1 310 555 1234' },
{ label: 'Brad Pitt', value: 'Brad', description: '+1 323 555 5678' },
{ label: 'Meryl Streep', value: 'Meryl', description: '+1 212 555 8765' },
{ label: 'Tom Hanks', value: 'Tom', description: '+1 310 555 4321' },
{ label: 'Natalie Portman', value: 'Natalie', description: '+1 818 555 6789' },
].map(item => ({ ...item, id: getUUID(), before: avatar })),
},
].map(item => ({ ...item, id: getUUID(), before: avatar }));
let complexSelected = $state<NeoListSelectedItem>();
</script>

{#snippet avatar()}
Expand All @@ -116,13 +133,16 @@
<NeoButton toggle bind:checked={options.closeOnDismiss}>Dismiss</NeoButton>
</NeoButtonGroup>

<NeoNativeSelect
<NeoSelect
label="Placement"
placeholder="Select placement"
position="left"
floating={false}
bind:value={options.placement}
rounded={options.rounded}
containerProps={{ style: 'margin-left: 6.75rem' }}
options={position}
size="15"
/>

<NeoNumberStep
Expand Down Expand Up @@ -177,19 +197,35 @@
</div>

<div class="row">
<div class="column content">
<span class="label">Simple hover Select</span>
<NeoPopSelect
bind:selected={simpleSelected}
items={simpleItems}
rounded={options.rounded}
height={'20rem'}
tooltipProps={options}
onselect={e => console.info('selected', e)}
>
<NeoButton text rounded={options.rounded}>Hover select: {simpleSelected?.item?.value ?? 'none selected'}</NeoButton>
</NeoPopSelect>
</div>

<div class="column content">
<span class="label">PopSelect</span>
<NeoPopSelect
search
bind:selected
{items}
bind:selected={complexSelected}
items={complexItems}
rounded={options.rounded}
height={{
min: '20rem',
max: '30rem',
}}
tooltipProps={options}
height={{ max: '20rem' }}
width={{ min: '15.5rem' }}
onselect={e => console.info('selected', e)}
>
<NeoButton text rounded={options.rounded}>Hover select: {selected?.item?.label ?? 'none selected'}</NeoButton>
<NeoListBaseItem item={complexSelected?.item || complexItems[0]} />
</NeoPopSelect>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/icons/IconDoubleChevron.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@

<style lang="scss">
.neo-icon-double-chevron {
transition: translate 0.3s ease;
transition: translate 0.5s var(--neo-easing-overshoot-smooth, ease);
}
</style>
18 changes: 8 additions & 10 deletions src/lib/inputs/NeoNativeSelect.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
<script lang="ts">
import { wait } from '@dvcol/common-utils/common/promise';
import type { NeoButtonProps } from '~/buttons/neo-button.model.js';
import type { NeoNativeSelectProps } from '~/inputs/neo-select.model.js';
Expand Down Expand Up @@ -38,6 +36,8 @@
}: NeoNativeSelectProps = $props();
/* eslint-enable prefer-const */
const items = $derived(options?.map(i => (typeof i === 'object' ? i : { value: i })));
const elevation = $derived(coerce(rest?.elevation ?? getDefaultElevation(rest?.pressed)));
const text = $derived(elevation >= 0 || !rest.pressed);
const style = $derived(computeButtonShadows(elevation, text));
Expand All @@ -60,19 +60,17 @@
class: ['neo-select-toggle', buttonProps?.class],
});
let space = $state(7);
let space = $state(6);
const onpointerdown = () => {
space = 6;
space = 8;
};
let timeout: ReturnType<typeof setTimeout>;
const onpointerup = async () => {
clearTimeout(timeout);
timeout = setTimeout(async () => {
space = 8;
await wait(300);
space = 7;
}, 200);
space = 6;
}, 250);
};
</script>

Expand All @@ -89,7 +87,7 @@
{/snippet}

{#snippet content()}
{#each options as { label, ...option }}
{#each items as { label, ...option }}
<option {...option} value={option.value}>{label ?? option.value}</option>
{/each}
{@render children?.()}
Expand All @@ -111,7 +109,7 @@
{multiple}
floating={multiple ? false : floating}
after={multiple ? undefined : after}
children={options?.length ? content : children}
children={items?.length ? content : children}
{onpointerdown}
{onpointerup}
{...rest}
Expand Down
20 changes: 11 additions & 9 deletions src/lib/inputs/NeoSelect.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import NeoButton from '~/buttons/NeoButton.svelte';
import IconDoubleChevron from '~/icons/IconDoubleChevron.svelte';
import NeoInput from '~/inputs/common/NeoInput.svelte';
import { displayValue, type NeoSelectProps } from '~/inputs/neo-select.model.js';
import { type NeoSelectProps, transformValue } from '~/inputs/neo-select.model.js';
import NeoPopSelect from '~/tooltips/NeoPopSelect.svelte';
import { coerce, computeButtonShadows, getDefaultElevation } from '~/utils/shadow.utils.js';
Expand All @@ -17,8 +17,8 @@
icon: customIcon,
// State
options = [],
display = displayValue,
options: items = [],
transform = transformValue,
// Input Props
ref = $bindable(),
Expand All @@ -32,6 +32,7 @@
multiple,
floating,
rounded,
readonly,
// Pop Select Props
listRef = $bindable(),
Expand Down Expand Up @@ -76,11 +77,11 @@
class: ['neo-select-toggle', buttonProps?.class],
});
const space = $derived(open ? 9 : 6);
const space = $derived(open ? 8 : 6);
watch(
() => {
value = display(selected);
value = transform(selected);
touched = true;
},
() => selected,
Expand All @@ -90,11 +91,11 @@
},
);
// TODO - disaply input ???
// TODO - rework focus highlights
// implement readonly
// TODO - custom render trigger popselect ?
// TODO - pill
// make clearable work
// list padding ?
// validation
</script>

{#snippet after()}
Expand Down Expand Up @@ -139,7 +140,8 @@
bind:tooltipRef
bind:triggerRef
bind:open
items={options}
{readonly}
{items}
multiple={!!multiple}
{rounded}
{search}
Expand Down
Loading

0 comments on commit 7090740

Please sign in to comment.