-
-
Notifications
You must be signed in to change notification settings - Fork 331
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/Modal component - better typing support #2064
feat/Modal component - better typing support #2064
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
@HugeLetters I've made a minor edit to the tagged issue above. Make sure to remove the |
@endigo9740 could you clear something up for me please? Is the purpose of the modalStore is to just track a queue of modals if a multiple of them has been triggered (like here)? Is it also for nested modals or those are not supported? Or is there some other purpose? |
@HugeLetters in simplest terms the modal system is implemented globally in your app. It's implemented on-demand page to page. We use a singleton pattern for this. There's a single instance of We ship with a handful of canned options that replace native dialogs, such as alert, prompt, confirm. Then provide a means for creating your own custom modals via custom components. You can either pass them on-demand (when triggering) or register them ahead of time for reuse. |
@endigo9740 Yeah, I am asking specifically about this - so it's just to keep track of a modal queue? What's the purpose of queue? Is it just for sequential modals like in the link in my previous message? |
Correct, the role of the modal/drawer/toast stores are each to maintain their respective reactive list (read: queue) of modal instances. If multiple portions of the app trigger multiple dialogs, then they need to queue. For example, if a dialog is triggered while another dialog is being displayed.
Also FYI, the way these stores are initialized changed in v2 in order to prevent some known issues with SvelteKit SSR. This change was implemented by @AdrianGonz97, who worked with us on your last PR, so he would be the guy to ask if you have any questions about this. |
@endigo9740 I see there is an issue that you need to keep a track of properties to pass on - here. We can do this to at least ensure we didn't forget to pass on any props to parent but it seems not all props should be passed on - what's the criteria? Anything that's not not related to Backdrop or Transition Layer? import type Modal from './Modal.svelte'; // you can import a module from itself
type ModalProps = Required<ComponentProps<Modal>>; // add Omit here to exclude unrelated props.
$: parent: ModalProps = { ... }; Docs claim that any Modal prop is available on the parent object - so maybe pass all of them through? |
@HugeLetters per the inquiry around I'm not sure if you've looked at the changes Svelte 5 is introducing, but my gut is telling me there will be a better way to handle this than what we're doing now. Typing for |
@@ -187,7 +176,14 @@ | |||
</svelte:head> | |||
|
|||
<!-- Overlays --> | |||
<Modal components={modalComponentRegistry} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stuff "has" to be moved inline - otherwise you don't get the convenience of generics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't particularly mind inlining props like this, but @endigo9740 may find this sacrilegious 😄. I'm fine with either.
@AdrianGonz97 I think I'm more or less done for now - I've listed things I've done & considered. |
@AdrianGonz97 I'd welcome your review for this. If you give the thumbs up I'm happy to merge. |
@endigo9740 I think Adrian gave his thumbs up with a reaction 😅 |
@HugeLetters heh, sorry not quite - I'll give it a review today! 😄 |
@AdrianGonz97 I'm running through and reviews all pending PRs today, so I'll keep an eye out for your response! Thanks! |
@HugeLetters sorry for the delay on this one - I think @AdrianGonz97 and myself have both been swamped. We do still intend to review this, but given the larger scope of changes this will be a bit more involved. Thanks for your patience in the meantime. |
…eat/Modal-better-typing
It's alright, no hurry :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, I really like the changes! While I pushed some really minor changes, this PR is pretty good as-is.
Unfortunately, I believe that this PR may break some of the types for our users. For instance, in our example component ModalExampleForm.svelte
, the following check needed to be added to discriminate on the Modal type, otherwise, we'd get a type-error when we try to pass flavor
to response
:
function onFormSubmit(): void {
// 👇
if ($modalStore[0].response && $modalStore[0].type === 'component')
$modalStore[0].response(flavor);
modalStore.close();
}
Now, whether changes to types should be considered 'breaking' is certainly a contentious topic, I believe that they should be. So while this PR is great as it is, I would hold off from merging until the next major version of Skeleton.
@@ -153,18 +161,22 @@ | |||
} | |||
|
|||
function onClose(): void { | |||
if ($modalStore[0].response) $modalStore[0].response(false); | |||
if (currentModal.response) currentModal.response(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is more of an aside than anything else:
In hindsight, it would've been preferable to return a string literal of CLOSED
(or some other equivalent) instead of false
. false
isn't explicit enough for my liking. But alas, it would be a breaking change to change it now.
if (currentModal.response) currentModal.response(false); | |
if (currentModal.response) currentModal.response('CLOSED'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with either - I leave it up to you guys.
if ($modalStore[0].response) $modalStore[0].response(true); | ||
if (currentModal.type !== 'confirm') return; | ||
|
||
if (currentModal.response) currentModal.response(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel the same way about this one too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is one isn't breaking change actually per se since this function is only called if modalType is "confirm" - unless we consider that it's type gets mutated somewhere between rerender and a callback call(impossible basically).
We could articulate this better if we introduce Modal internal sub-components to break-up the code a little bit - and this would eliminate the need to make this check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is one isn't breaking change actually per se since this function is only called if modalType is "confirm"
Sorry, I should've been more specific on this one. I meant that feel the same way as I did for the aside I wrote for using string literals instead of true
or false
for onClose
and onConfirm
. We would respond with CLOSED
and CONFIRMED
, respectively.
@@ -187,7 +176,14 @@ | |||
</svelte:head> | |||
|
|||
<!-- Overlays --> | |||
<Modal components={modalComponentRegistry} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't particularly mind inlining props like this, but @endigo9740 may find this sacrilegious 😄. I'm fine with either.
@@ -19,7 +19,7 @@ | |||
|
|||
// We've created a custom submit function to pass the response and close the modal. | |||
function onFormSubmit(): void { | |||
if ($modalStore[0].response) $modalStore[0].response(formData); | |||
if ($modalStore[0].response && $modalStore[0].type === 'component') $modalStore[0].response(formData); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid this may be the point where this change demonstrates that it's a breaking one for types.
@AdrianGonz97 @HugeLetters Not to be the bearer of bad news, but if we need to treat this as a breaking change, we might not be able to move forward with this PR (yet). Skeleton v2 -> v3 will likely involve a major rewrite of this feature. If that's the case, we can continue to make updates, but only as reference for how we might handle this for the rewrite. @HugeLetters if you would like to like to be a part of the rewrite for v3, I'm happy to bring you in for that. You and Adrian can help shape the feature as it's being written, if that makes sense. No pressure obviously, but consider it an open offer. |
…eat/Modal-better-typing
I'm fine if this needs to be postponed until v3 - I'm not that familiar with what should be considered breaking and not. On one hand it is since there might exist a code base which would require some minor code changes with this update to avoid TS compilation errors(nothing changes behavior-wise). As for the my participating in implementing this feature for v3 - I would be glad to help but can't say for certain if I would have the time since I finally landed my first job so it's really hard for me to say how much spare time would I have. |
Fair points @HugeLetters. FYI part of the reason for the v3 rewrite is Svelte 5 support. Our hope is the new features provided will greatly simplify a lot of things, which should make introducing better type safety a bit easier. At least in theory. Fingers crossed :) |
@HugeLetters @AdrianGonz97 Just a quick update after sleeping on this. I think we'll go ahead and close the PR. But keep this handy as reference to inform the design process for our v3 iteration of modals. Given all the other changes coming down the pipeline, I think we'll be in for a really nice update. Huge, sorry for this taking so long. I suspected this might be the way this goes but wanted to make sure we vetted it properly to confirm. Your contribution is appreciated and I'll definitely ping you when we get to the new modal system. If you have time to jump in and review we would sure appreciate it! Thanks guys! |
Linked Issue
Closes #1813
Description
This PR aims to improve typing on a modal component.
input type="number"
can be provided throughvallueAttr
- Svelte will not parse its value as a number because its compiler only seestype="text"
specified in the Modal component.HTMLInputAttributes
Changsets
Instructions: Changesets automate our changelog. If you modify files in
/packages/skeleton
, runpnpm changeset
in the root of the monorepo, follow the prompts, then commit the markdown file. Changes that add features should beminor
while chores and bugfixes should bepatch
. Please prefix the changeset message withfeat:
,bugfix:
orchore:
.Checklist
Please read and apply all contribution requirements.
dev
branch (NEVERmaster
)docs/
,feat/
,chore/
,bugfix/
pnpm check
pnpm format
pnpm test