Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat/dynamic-transitions #1533

Merged
merged 71 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
f6852d8
switched accordion transition to In/Out dynamic transition
Mahmoud-zino May 21, 2023
54b4dd8
Merge branch 'dev' of https://github.com/Mahmoud-zino/skeleton into f…
Mahmoud-zino May 23, 2023
9976ca8
added TransitionSettings and removed 'any'
Mahmoud-zino May 23, 2023
5638736
deleted transition in favor of transitionIn/Out
Mahmoud-zino May 24, 2023
1ff7c0f
chagned transition types
Mahmoud-zino May 27, 2023
5444f73
foramted
Mahmoud-zino May 27, 2023
9387fdb
Merge branch 'skeletonlabs:dev' into feat/dynamic-animations
Mahmoud-zino May 27, 2023
acc9afc
changed Record value to any
Mahmoud-zino May 27, 2023
7bfe8ba
added prefersReducedMotion store
Mahmoud-zino May 28, 2023
34af502
added false to Transition type
Mahmoud-zino May 29, 2023
8508590
changed transition Types
Mahmoud-zino May 31, 2023
ea14ccb
merged dev
Mahmoud-zino May 31, 2023
ab642e7
imported Transition type
Mahmoud-zino May 31, 2023
6fc34ee
destructing Transition objects
Mahmoud-zino May 31, 2023
4649b9b
added chagneset
Mahmoud-zino May 31, 2023
e3bc2cb
moved types to types.ts, included duration in accordion transitions t…
Mahmoud-zino May 31, 2023
e99e73b
reordered duration in params
Mahmoud-zino Jun 1, 2023
1a9fc89
changed changeset message, updated imports
Mahmoud-zino Jun 1, 2023
a8cdcb7
Merge branch 'feat/dynamic-animations' of https://github.com/Mahmoud-…
Mahmoud-zino Jun 1, 2023
45b4d9d
exported transition types
Mahmoud-zino Jun 5, 2023
515dc16
Merge branch 'feat/dynamic-animations' of https://github.com/Mahmoud-…
Mahmoud-zino Jun 5, 2023
21fe122
format
Mahmoud-zino Jun 5, 2023
73fefd2
added generics attribute
AdrianGonz97 Jun 7, 2023
c55ca8a
Merge remote-tracking branch 'upstream/dev' into feat/dynamic-animations
AdrianGonz97 Jun 7, 2023
8d2f371
removed duration
AdrianGonz97 Jun 7, 2023
88defd7
exported types must be named
AdrianGonz97 Jun 7, 2023
354cdbc
oops
AdrianGonz97 Jun 7, 2023
0e79f78
added dynamicTransition function wrapper
Mahmoud-zino Jun 8, 2023
5a38990
moved dynamic-transitions types to seperate directory
Mahmoud-zino Jun 8, 2023
79cdb36
moved transition types to src/lib/types.ts
Mahmoud-zino Jun 9, 2023
bd21e34
added part of the docs
Mahmoud-zino Jun 10, 2023
dd009e6
rearrange
AdrianGonz97 Jun 14, 2023
b7524ac
Merge remote-tracking branch 'upstream/dev' into feat/dynamic-animations
AdrianGonz97 Jun 14, 2023
265bfb1
fixed jsdoc types
AdrianGonz97 Jun 14, 2023
a59bed1
Updated transition docs, added Transition tag to DocShell
endigo9740 Jun 14, 2023
379398f
Merge branch 'feat/dynamic-animations' of https://github.com/Mahmoud-…
endigo9740 Jun 14, 2023
d17a114
added prefersReducedMotion store
Mahmoud-zino Jun 14, 2023
6c6ab7d
readded AdditionalTransitionProps
Mahmoud-zino Jun 14, 2023
e1f03e9
set prefersReducedMotionStore to transitions prop
Mahmoud-zino Jun 14, 2023
c59e82f
added reducedMotion to docs
Mahmoud-zino Jun 14, 2023
995000f
added jsdoc comment to store
AdrianGonz97 Jun 14, 2023
3e53632
fixed flickering when reduced motion was on
AdrianGonz97 Jun 14, 2023
96213ba
Doc updates, props reordered, DocShell updates
endigo9740 Jun 15, 2023
105d832
switched autocomplete to dynamic transitions
Mahmoud-zino Jun 16, 2023
2f831f8
switched InputChip to dynamic transitions
Mahmoud-zino Jun 16, 2023
54b595b
switched Stepper,Step to dynamic transitions
Mahmoud-zino Jun 16, 2023
dfc6937
switched TableOfContents to dynamic transitions
Mahmoud-zino Jun 16, 2023
f0e09b1
switched Drawer to dynamic transitions
Mahmoud-zino Jun 16, 2023
1640d38
switched Modal to dynamic transitions
Mahmoud-zino Jun 16, 2023
82ad5f4
reverted drawer dynamic transitions
Mahmoud-zino Jun 16, 2023
577f634
reverted modal backdrop dynamic transition
Mahmoud-zino Jun 16, 2023
cce19d1
reverted modal backdrop dynamic transition
Mahmoud-zino Jun 16, 2023
15f3767
updated changeset
Mahmoud-zino Jun 16, 2023
4131ac1
Merge branch 'v2' into feat/dynamic-animations
Mahmoud-zino Jun 20, 2023
9f43613
deleted durations from tests
Mahmoud-zino Jun 21, 2023
56647ce
added transition style-guid
Mahmoud-zino Jun 21, 2023
dfbbfea
disable drawer opacity on demand
Mahmoud-zino Jun 23, 2023
aedd888
fixed opacityTransition type
Mahmoud-zino Jun 23, 2023
af56c60
Merge branch 'v2' into feat/dynamic-animations
Mahmoud-zino Jul 1, 2023
ea968fc
resolved conflicts, supressed a11y warnings and added todos to them
Mahmoud-zino Jul 1, 2023
30259cd
Contributor transition doc updates
endigo9740 Jul 5, 2023
25b0f2e
Note supported and non supported transitions
endigo9740 Jul 5, 2023
46d46f6
changed toast transition to fly
Mahmoud-zino Jul 6, 2023
b33b14f
removed duration from toast
Mahmoud-zino Jul 6, 2023
8aaf1ca
disable flip animation on transitions prop
Mahmoud-zino Jul 6, 2023
2c8b08f
moved SvelteEvent to types.ts
Mahmoud-zino Jul 6, 2023
59c2dd8
format
Mahmoud-zino Jul 6, 2023
f2c6cec
reapplied local to transitions to support backwards compatibility
Mahmoud-zino Jul 6, 2023
a167c32
Merge remote-tracking branch 'upstream/v2' into feat/dynamic-animations
AdrianGonz97 Jul 6, 2023
e4e93d9
chagned toast transition to global
Mahmoud-zino Jul 14, 2023
6df83bf
reordered opacityTransition to transition props
Mahmoud-zino Jul 14, 2023
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
22 changes: 19 additions & 3 deletions packages/skeleton/src/lib/components/Accordion/Accordion.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,24 @@

import { writable, type Writable } from 'svelte/store';
import { setContext } from 'svelte';
import { slide } from 'svelte/transition';

// Types
import type { CssClasses } from '../..';
import type { CssClasses, TransitionSettings } from '../..';

// Props
/** Set the auto-collapse mode. */
export let autocollapse = false;
/** Set the drawer animation duration in milliseconds. */
export let duration = 200; // ms
/**
* Provide the transition to use when values move in.
* @type {TransitionSettings}
*/
export let transitionIn: TransitionSettings = { transition: slide, params: { duration: 200 } };
/**
* Provide the transition to use when values move out.
* @type {TransitionSettings}
*/
export let transitionOut: TransitionSettings = { transition: slide, params: { duration: 200 } };

// Props (parent)
/** Provide classes to set the accordion width. */
Expand Down Expand Up @@ -44,13 +53,20 @@
/** Provide arbitrary classes to the caret icon region. */
export let regionCaret: CssClasses = '';

/** DEPRECATED: use transition or transitionIn, transitionOut instead. */
export let duration = 200; // ms
// Silence warning about unused props:
const deprecated = [duration];
Mahmoud-zino marked this conversation as resolved.
Show resolved Hide resolved

// Local
const active: Writable<string | null> = writable(null);

// Context API
setContext('active', active);
setContext('autocollapse', autocollapse);
setContext('duration', duration);
setContext('transitionIn', transitionIn);
setContext('transitionOut', transitionOut);
setContext('disabled', disabled);
setContext('padding', padding);
setContext('hover', hover);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
import { getContext } from 'svelte';
import { createEventDispatcher } from 'svelte/internal';
import type { Writable } from 'svelte/store';
import { slide } from 'svelte/transition';

// Event Dispatcher
const dispatch = createEventDispatcher();

// Types
import type { CssClasses } from '../..';
import type { CssClasses, TransitionSettings } from '../..';

// Props (state)
/** Set open by default on load. */
Expand All @@ -41,8 +40,10 @@
export let autocollapse: boolean = getContext('autocollapse');
/** The writable store that houses the auto-collapse active item UUID. */
export let active: Writable<string | null> = getContext('active');
/** Set the drawer animation duration. */
export let duration: number = getContext('duration');
/** Provide the transition to use when values move in. */
export let transitionIn: TransitionSettings = getContext('transitionIn');
/** Provide the transition to use when values move out. */
export let transitionOut: TransitionSettings = getContext('transitionOut');
// ---
/** Set the disabled state for this item. */
export let disabled: boolean = getContext('disabled');
Expand All @@ -64,6 +65,15 @@
export let regionPanel: CssClasses = getContext('regionPanel');
/** Provide arbitrary classes caret icon region. */
export let regionCaret: CssClasses = getContext('regionCaret');
// ---
/** DEPRECATED: use transition or transitionIn, transitionOut instead. */
export let duration: number = getContext('duration');
// Silence warning about unused props:
const deprecated = [duration];

// Local
const { transition: trIn, params: trInParams } = transitionIn;
const { transition: trOut, params: trOutParams } = transitionOut;
Mahmoud-zino marked this conversation as resolved.
Show resolved Hide resolved

// Change open behavior based on auto-collapse mode
function setActive(event?: Event): void {
Expand Down Expand Up @@ -140,7 +150,8 @@
<div
class="accordion-panel {classesPanel}"
id="accordion-panel-{id}"
transition:slide|local={{ duration }}
in:trIn|local={{ ...trInParams }}
out:trOut|local={{ ...trOutParams }}
Mahmoud-zino marked this conversation as resolved.
Show resolved Hide resolved
role="region"
aria-hidden={!openState}
aria-labelledby="accordion-control-{id}"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { render } from '@testing-library/svelte';
import { describe, it, expect } from 'vitest';
import { slide } from 'svelte/transition';

import AccordionItem from '$lib/components/Accordion/AccordionItem.svelte';

describe('AccordionItem.svelte', () => {
it('Renders with minimal props', async () => {
const { getByTestId } = render(AccordionItem);
const { getByTestId } = render(AccordionItem, {
transitionIn: { transition: slide, params: { duration: 200 } },
transitionOut: { transition: slide, params: { duration: 200 } }
});
expect(getByTestId('accordion-item')).toBeTruthy();
});

Expand All @@ -17,7 +21,9 @@ describe('AccordionItem.svelte', () => {
rounded: 'rounded-container-token',
regionControl: '',
regionPanel: 'space-y-4',
regionCaret: ''
regionCaret: '',
transitionIn: { transition: slide, params: { duration: 200 } },
transitionOut: { transition: slide, params: { duration: 200 } }
});
expect(getByTestId('accordion-item')).toBeTruthy();
expect(getByTestId('accordion-item').querySelector('.accordion-control')?.className).to.contain('py-2 px-4');
Expand Down
6 changes: 6 additions & 0 deletions packages/skeleton/src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// This file defines the short path imports for the package (ex: @skeletonlabs/skeleton/*)
import type { TransitionConfig, slide } from 'svelte/transition';

// Types ---

Expand All @@ -14,6 +15,11 @@ export type { PopupSettings } from './utilities/Popup/types';
// This type alias is to identify CSS classes within component props, which enables Tailwind IntelliSense
export type CssClasses = string;

export interface TransitionSettings {
transition: (...args: Parameters<typeof slide>) => TransitionConfig;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ryceg I like that @Mahmoud-zino has created a global shared type for reuse, but I'v noted we're using slide here as the default. Is there a more generic value we can use here? I believe transitions are just functions by default - do we provide a generic function here?

This may tie into another issue I'll raise in the PR thread in regards to removing animations.

Copy link
Sponsor Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@endigo9740 yeah I looked into it, this will work with most transitions but not draw or crossfade because they take different parameters. I think the only way to make it really generic is by using any...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use a union type;

transition: (...args: Parameters<typeof blur | fade | fly | slide | scale>) => TransitionConfig

It's not pretty, and it doesn't support custom transitions that include additional params (although you could slap a | Record<string | any> on the end to accommodate that) but it does work

Copy link
Sponsor Contributor Author

@Mahmoud-zino Mahmoud-zino May 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@endigo9740 @ryceg Is using object a bad idea? I achieved the same functionality by changing the params to object and it works.

export interface TransitionSettings {
	transition: (node: HTMLElement, params: object) => TransitionConfig;
	params: object;
}

and like this, we are not dependent on slide anymore.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typescript works by narrowing wider types; the object type simply tells Typescript that it's not one of the other primitives. Both are technically "correct", but you're going to be more accurate with a union type (accuracy in the sense of trying to make your types resemble the corresponding data).

Try it out- with the union type you'll get intellisense on the object, and it'll narrow down the possible choices as you add props that don't exist on some of the interfaces.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Mahmoud-zino I'm not sure another prop would help since the transition directives are still applied to the elements. We need to alter the value passed to the transition:in and transition:out, correct?

Copy link
Sponsor Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes and no, we can do something like this repl.

Copy link
Contributor

@endigo9740 endigo9740 May 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I like it, but there's a lot of boilerplate. We definitely don't want that to live within every component. It would need to be abstracted for reuse by all components.

I'm was thinking something more like how we handle dynamic actions:
https://github.com/skeletonlabs/skeleton/blob/dev/packages/skeleton/src/lib/components/Avatar/Avatar.svelte#L20

If the action is not present, we still need to pass something to use: directive, so we pass an empty function:
https://github.com/skeletonlabs/skeleton/blob/dev/packages/skeleton/src/lib/components/Avatar/Avatar.svelte#L59

In practice that would look something like this:

<SomeComponent
    transitionIn={{transition: () => {}, params: {}}}
    transitionOut={{transition: () => {}, params: {}}}
/>

I don't like this though, we're then forcing end users to pass a bunch of extra noise.

This makes me wonder if we build in and include our own custom transition called disabled:

function disabled(node, { duration }) {
    return { duration: 0, css: t => `` };
}

Then allow users to provide this like so:

<SomeComponent
    transitionIn={{transition: disabled, params: {}}}
    transitionOut={{transition: disabled, params: {}}}
/>

Then if we can make params optional, it could be:

<SomeComponent
    transitionIn={{transition: disabled}}
    transitionOut={{transition: disabled}}
/>

But this requires importing disabled to use it and I'm not sure this guarantees there won't be a performance hit, even if it's minor.

Really stumped on this one, it's a tough one to figure out. The limitation here is that Svelte doesn't seem to support dynamic transitions well - so in some ways it's an upstream issue.

Copy link
Sponsor Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@endigo9740
I like the disabled Idea, but we don't have to return anything from it. Svelte only cares about the function parameters having the correct type.
I don't know how yet but I will try to benchmark both approaches and check the performance.
This might take some time, but I will report back when I have something.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a huge fan of disabled being a function- traditionally disabled is a boolean, and there's less friction if we don't require them to import the disabled function just to pass it in. We could always add in a disabled flag in an extended interface very easily, and this would also afford the ability to toggle it.

params: object;
}

Mahmoud-zino marked this conversation as resolved.
Show resolved Hide resolved
// Stores ---

export { storeHighlightJs } from './utilities/CodeBlock/stores';
Expand Down