Skip to content

Commit cd03aa5

Browse files
committed
feat: migrate components in drawer to runes
1 parent 8cc6c77 commit cd03aa5

File tree

6 files changed

+102
-61
lines changed

6 files changed

+102
-61
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ Svelte 5 Runes mode is being migrated to slowly. This is the todo list of compon
162162
- [x] Common
163163
- [ ] Data Table
164164
- [ ] Dialog
165-
- [ ] Drawer
165+
- [x] Drawer
166166
- [ ] Image List
167167
- Inputs and Controls
168168
- [ ] Autocomplete

packages/drawer/src/Drawer.svelte

+61-31
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<svelte:options runes={false} />
1+
<svelte:options runes={true} />
22

33
<aside
44
bind:this={element}
@@ -11,21 +11,21 @@
1111
'smui-drawer__absolute': variant === 'modal' && !fixed,
1212
...internalClasses,
1313
})}
14-
{...$$restProps}
14+
{...restProps}
1515
onkeydown={(e) => {
1616
if (instance) {
1717
instance.handleKeydown(e);
1818
}
19-
$$restProps.onkeydown?.(e);
19+
restProps.onkeydown?.(e);
2020
}}
2121
ontransitionend={(e) => {
2222
if (instance) {
2323
instance.handleTransitionEnd(e);
2424
}
25-
$$restProps.ontransitionend?.(e);
25+
restProps.ontransitionend?.(e);
2626
}}
2727
>
28-
<slot />
28+
{#if children}{@render children()}{/if}
2929
</aside>
3030

3131
<script lang="ts">
@@ -34,6 +34,7 @@
3434
MDCModalDrawerFoundation,
3535
} from '@material/drawer';
3636
import { focusTrap as domFocusTrap } from '@material/dom';
37+
import type { Snippet } from 'svelte';
3738
import { onMount, onDestroy, setContext } from 'svelte';
3839
import type { SmuiAttrs } from '@smui/common';
3940
import type { ActionArray } from '@smui/common/internal';
@@ -42,52 +43,81 @@
4243
const { FocusTrap } = domFocusTrap;
4344
4445
type OwnProps = {
46+
/**
47+
* An array of Action or [Action, ActionProps] to be applied to the element.
48+
*/
4549
use?: ActionArray;
50+
/**
51+
* A space separated list of CSS classes.
52+
*/
4653
class?: string;
54+
/**
55+
* How the drawer opens.
56+
*
57+
* Undefined means it's always open.
58+
*
59+
* Dismissible means it pushes the content over when it opens.
60+
*
61+
* Modal means it uses a scrim to open over the content.
62+
*/
4763
variant?: 'dismissible' | 'modal' | undefined;
64+
/**
65+
* When using a dismissible or modal drawer, controls whether it's open.
66+
*/
4867
open?: boolean;
68+
/**
69+
* Turn this off for non-page-wide drawers.
70+
*
71+
* This controls whether the drawer uses fixed or absolute positioning.
72+
*/
4973
fixed?: boolean;
50-
};
51-
type $$Props = OwnProps & SmuiAttrs<'aside', keyof OwnProps>;
5274
53-
// Remember to update $$Props if you add/remove/rename props.
54-
export let use: ActionArray = [];
55-
let className = '';
56-
export { className as class };
57-
export let variant: 'dismissible' | 'modal' | undefined = undefined;
58-
export let open = false;
59-
export let fixed = true;
75+
children?: Snippet;
76+
};
77+
let {
78+
use = $bindable([]),
79+
class: className = $bindable(''),
80+
variant = $bindable(undefined),
81+
open = $bindable(false),
82+
fixed = $bindable(true),
83+
children,
84+
...restProps
85+
}: OwnProps & SmuiAttrs<'aside', keyof OwnProps> = $props();
6086
6187
let element: HTMLElement;
6288
let instance:
6389
| MDCDismissibleDrawerFoundation
6490
| MDCModalDrawerFoundation
65-
| undefined = undefined;
66-
let internalClasses: { [k: string]: boolean } = {};
67-
let previousFocus: Element | null = null;
91+
| undefined = $state(undefined);
92+
let internalClasses: { [k: string]: boolean } = $state({});
93+
let previousFocus: Element | null = $state(null);
6894
let focusTrap: domFocusTrap.FocusTrap;
69-
let scrim: Element | false = false;
95+
let scrim: Element | false = $state(false);
7096
7197
setContext('SMUI:list:nav', true);
7298
setContext('SMUI:list:item:nav', true);
7399
setContext('SMUI:list:wrapFocus', true);
74100
75-
$: if (instance && instance.isOpen() !== open) {
76-
if (open) {
77-
instance.open();
78-
} else {
79-
instance.close();
101+
$effect(() => {
102+
if (instance && instance.isOpen() !== open) {
103+
if (open) {
104+
instance.open();
105+
} else {
106+
instance.close();
107+
}
80108
}
81-
}
109+
});
82110
83111
let oldVariant = variant;
84-
$: if (oldVariant !== variant) {
85-
oldVariant = variant;
86-
instance && instance.destroy();
87-
internalClasses = {};
88-
instance = getInstance();
89-
instance && instance.init();
90-
}
112+
$effect(() => {
113+
if (oldVariant !== variant) {
114+
oldVariant = variant;
115+
instance && instance.destroy();
116+
internalClasses = {};
117+
instance = getInstance();
118+
instance && instance.init();
119+
}
120+
});
91121
92122
onMount(() => {
93123
focusTrap = new FocusTrap(element, {

packages/drawer/src/Scrim.svelte

+35-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
<svelte:options runes={false} />
1+
<svelte:options runes={true} />
22

3-
<svelte:component
4-
this={component}
3+
<MyComponent
54
{tag}
65
bind:this={element}
76
{use}
@@ -10,16 +9,17 @@
109
'mdc-drawer-scrim': true,
1110
'smui-drawer-scrim__absolute': !fixed,
1211
})}
13-
{...$$restProps}
12+
{...restProps}
1413
onclick={(e: MouseEvent) => {
1514
handleClick(e);
16-
$$restProps.onclick?.(e);
15+
restProps.onclick?.(e);
1716
}}
1817
>
19-
<slot />
20-
</svelte:component>
18+
{#if children}{@render children()}{/if}
19+
</MyComponent>
2120

2221
<script lang="ts" generics="TagName extends SmuiEveryElement = 'div'">
22+
import type { Snippet } from 'svelte';
2323
import type { ActionArray } from '@smui/common/internal';
2424
import { classMap, dispatch } from '@smui/common/internal';
2525
import type {
@@ -31,26 +31,43 @@
3131
import { SmuiElement } from '@smui/common';
3232
3333
type OwnProps = {
34+
/**
35+
* An array of Action or [Action, ActionProps] to be applied to the element.
36+
*/
3437
use?: ActionArray;
38+
/**
39+
* A space separated list of CSS classes.
40+
*/
3541
class?: string;
42+
/**
43+
* Turn this off for non-page-wide drawers.
44+
*
45+
* This controls whether the drawer uses fixed or absolute positioning.
46+
*/
3647
fixed?: boolean;
48+
/**
49+
* The component to use to render the element.
50+
*/
3751
component?: SmuiComponent<SmuiElementMap[TagName]>;
52+
/**
53+
* The tag name of the element to create.
54+
*/
3855
tag?: TagName;
39-
};
40-
type $$Props = OwnProps & SmuiAttrs<TagName, keyof OwnProps>;
4156
42-
// Remember to update $$Props if you add/remove/rename props.
43-
export let use: ActionArray = [];
44-
let className = '';
45-
export { className as class };
46-
export let fixed = true;
57+
children?: Snippet;
58+
};
59+
let {
60+
use = $bindable([]),
61+
class: className = $bindable(''),
62+
fixed = $bindable(true),
63+
component: MyComponent = $bindable(SmuiElement),
64+
tag = $bindable('div' as TagName),
65+
children,
66+
...restProps
67+
}: OwnProps & SmuiAttrs<TagName, keyof OwnProps> = $props();
4768
4869
let element: ReturnType<SmuiComponent<SmuiElementMap[TagName]>>;
4970
50-
export let component: SmuiComponent<SmuiElementMap[TagName]> = SmuiElement;
51-
export let tag: SmuiEveryElement | undefined =
52-
component === SmuiElement ? 'div' : undefined;
53-
5471
function handleClick(event: MouseEvent) {
5572
dispatch(getElement(), 'SMUIDrawerScrimClick', event);
5673
}

packages/site/src/routes/demo/drawer/_Dismissible.svelte

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
<svelte:options runes={false} />
2-
31
<div class="drawer-container">
42
<Drawer variant="dismissible" bind:open>
53
<Header>
@@ -69,8 +67,8 @@
6967
import Button, { Label } from '@smui/button';
7068
import List, { Item, Text } from '@smui/list';
7169
72-
let open = false;
73-
let active = 'Gray Kittens';
70+
let open = $state(false);
71+
let active = $state('Gray Kittens');
7472
7573
function setActive(value: string) {
7674
active = value;

packages/site/src/routes/demo/drawer/_Modal.svelte

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
<svelte:options runes={false} />
2-
31
<div class="drawer-container">
42
<!-- Don't include fixed={false} if this is a page wide drawer.
53
It adds a style for absolute positioning. -->
@@ -101,8 +99,8 @@
10199
import Button, { Label } from '@smui/button';
102100
import List, { Item, Text, Graphic, Separator, Subheader } from '@smui/list';
103101
104-
let open = false;
105-
let active = 'Inbox';
102+
let open = $state(false);
103+
let active = $state('Inbox');
106104
107105
function setActive(value: string) {
108106
active = value;

packages/site/src/routes/demo/drawer/_Permanent.svelte

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
<svelte:options runes={false} />
2-
31
<div class="drawer-container">
42
<Drawer>
53
<Content>
@@ -51,7 +49,7 @@
5149
import Drawer, { AppContent, Content } from '@smui/drawer';
5250
import List, { Item, Text } from '@smui/list';
5351
54-
let clicked = 'nothing yet';
52+
let clicked = $state('nothing yet');
5553
</script>
5654

5755
<style>

0 commit comments

Comments
 (0)