Open justind000 opened 7 months ago
I think this is definitely something we can/should do!
My initial thoughts are we want this to be type-safe and flexible. I think taking inspiration from SMUI is a good idea to see how they handle it. It appears as though they accept an array of actions, but I need to investigate further how they go about handling/typing the params in that way.
We could also accept a single action, since actions are just functions, you can apply multiple "actions" within a single action, for example:
import externalAction from 'wherever'
function myCustomAction(node) {
const actReturn = externalAction(node)
return {
destroy() {
if (actReturn?.destroy) {
actReturn.destroy()
}
}
}
}
i would like to contribute on this if thats ok @huntabyte
edit: i also think is worth looking at the smui approach
How do you plan to implement/type this and how will update
s to the actions be handled?
How do you plan to implement/type this and how will
update
s to the actions be handled?
i was planning on doing some proof of concept first regarding the types, im aware that typesafety is a must
regarding the update i was going to ask for guidance on the discord channel but links are expired but my idea was on updating component per component
@huntabyte i was just checking on this issue and of course i tried first to add an action to the Button component
this is the shadcn-svelte Button
<script lang="ts">
import { Button as ButtonPrimitive } from "bits-ui";
import { cn } from "$lib/utils";
import { buttonVariants, type Props, type Events } from ".";
type $$Props = Props;
type $$Events = Events;
let className: $$Props["class"] = undefined;
export let variant: $$Props["variant"] = "default";
export let size: $$Props["size"] = "default";
export let builders: $$Props["builders"] = []; //<----------
export { className as class };
</script>
<ButtonPrimitive.Root
{builders} //<------------
class={cn(buttonVariants({ variant, size, className }))}
type="button"
{...$$restProps}
on:click
on:keydown
>
<slot />
</ButtonPrimitive.Root>
and this builder
prop catched my eye so i digged into it a little
the type Builder is an object with an action
attribute and this action
is of type { Action } from "svelte/action"
in this case the shadcn-svelte Button is taking a Builder array so its possible to pass actions to the component... just not by using use:
<script lang="ts">
import { Button } from "$lib/components/ui/button";
const myAction = (node: HTMLElement) => {
console.log({ node });
};
</script>
<Button builders={[{ action: myAction }]}>Hello world</Button>
or pass extra arguments
<script lang="ts">
import { Button } from "$lib/components/ui/button";
interface ExtraArgs {
a?: string;
b?: boolean;
}
const myAction = (node: HTMLElement, { a = "", b }: ExtraArgs) => {
console.log({ node, a, b });
};
</script>
<Button builders={[{ action: (node) => myAction(node, { a: "This is an extra", b: true }) }]}>
Hello world
</Button>
though i think there could be an implementation to use the use
directive or at least as a prop, this works for the meantime
some components like <Card>
(and card slots) dont use bits-ui, are just styled divs and
maybe adding it to those components is a start?
Describe the feature in detail (code, mocks, or screenshots encouraged)
I was adding in addResizedColumns to the Data Table and needed to pass
use:props.resize
to theTable.Head
component.<Table.Head {...attrs} use:props.resize>
. This gives an error, "Actions can only be applied to DOM elements, not componentssvelte(invalid-action)".To fix it, I modified table-head.svelte to this:
Now you can pass props.resize like so:
<Table.Head {...attrs} action={props.resize}>
SMUI and I'm assuming others, do something similar to this for all the components.
What type of pull request would this be?
New Feature
Provide relevant links or additional information.
No response