Expand the paradigm of Child to all components #1330
Replies: 3 comments 1 reply
-
Yeah I believe every component except button does this currently, but I can make button do the same 😃 |
Beta Was this translation helpful? Give feedback.
-
I needed this very same thing - https://gist.github.com/BigWillie/4a94c8ccd7824896ec7ccd9140467a35 <script lang="ts">
import { mergeProps } from "svelte-toolbelt";
import type { ButtonRootProps } from "../types.js";
let {
href,
type,
children,
child,
disabled = false,
ref = $bindable(),
...restProps
}: ButtonRootProps = $props();
const mergedProps = $derived(mergeProps(restProps, { disabled }));
</script>
{#if child}
{@render child({ props: mergedProps })}
{:else}
<svelte:element
this={href ? "a" : "button"}
data-button-root
type={href ? undefined : type}
href={href && !disabled ? href : undefined}
disabled={href ? undefined : disabled}
aria-disabled={href ? disabled : undefined}
role={href && disabled ? "link" : undefined}
tabindex={href && disabled ? -1 : 0}
bind:this={ref}
{...restProps}
>
{@render children?.()}
</svelte:element>
{/if} I don't know if this satisfies the exact requirements, however, it means I can do things like this: <script lang="ts">
import { Button } from 'bits-ui';
let {
em = 'primary',
tone = 'neutral',
size = 'medium',
icon = undefined,
label = 'foooooo',
onclick = undefined,
children = undefined,
disabled = false,
...rest
} = $props<{
em?: 'primary' | 'secondary' | 'tertiary';
tone?: 'neutral' | 'brand' | 'danger' | 'inverse';
size?: 'small' | 'medium' | 'large';
icon?: {
component: string;
props: Record<string, string>;
};
label?: string;
onclick?: (e: MouseEvent) => void;
children?: () => any;
[key: string]: unknown;
}>();
function handleClick(e: MouseEvent) {
console.log('clicked')
}
</script>
<Button.Root
onclick={handleClick}
icon={icon}
label={label}
disabled={disabled}
{...rest}
>
{#snippet child({ props })}
<button class='button {em} {tone} {size}' {...props} {disabled}>
<div class="inner">
{#if icon}
<icon.component {...icon.props} role="presentation" />
{/if}
<div class="label">
{#if label}
{label}
{:else}
{@render children?.()}
{/if}
</div>
</div>
</button>
{/snippet}
</Button.Root>
<style>
/* component scope styles now work! */
</style> If this is suitable, happy to make a branch and PR. |
Beta Was this translation helpful? Give feedback.
-
Was about to ask a question about this, but I guess Button.Root just doesn't support scoped styles. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Is it possible/practical to have the Child snippet available for all components e.g. Button as in my case it would be handy to pass in a list of classnames and have Svelte scope the outcome to the component instance. We we're doing this in Melt-UI version of our library and were looking to switch over to Bits-UI
Beta Was this translation helpful? Give feedback.
All reactions