Skip to content

Commit

Permalink
melt accordion
Browse files Browse the repository at this point in the history
  • Loading branch information
huntabyte committed Aug 2, 2023
1 parent 5ac57c3 commit a04c14d
Show file tree
Hide file tree
Showing 10 changed files with 195 additions and 51 deletions.
3 changes: 3 additions & 0 deletions apps/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
},
"devDependencies": {
"@huntabyte/mdsvex": "^0.16.8",
"@melt-ui/pp": "^0.1.0",
"@playwright/test": "^1.36.2",
"@sveltejs/adapter-vercel": "^3.0.3",
"@sveltejs/kit": "^1.22.4",
Expand All @@ -47,6 +48,7 @@
"svelte": "^4.1.2",
"svelte-check": "^3.4.6",
"svelte-preprocess": "^5.0.4",
"svelte-sequential-preprocessor": "^2.0.1",
"tailwindcss": "^3.3.3",
"tailwindcss-animate": "^1.0.6",
"tslib": "^2.6.1",
Expand All @@ -57,6 +59,7 @@
},
"type": "module",
"dependencies": {
"@melt-ui/svelte": "^0.30.1",
"class-variance-authority": "^0.6.0",
"clsx": "^2.0.0",
"d3-scale": "^4.0.2",
Expand Down
55 changes: 52 additions & 3 deletions apps/www/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
} from "$components/ui/accordion";
</script>

<Accordion type="single" collapsible class="w-full">
<Accordion class="w-full">
<AccordionItem value="item-1">
<AccordionTrigger>Is it accessible?</AccordionTrigger>
<AccordionContent>
Expand Down
22 changes: 16 additions & 6 deletions apps/www/src/lib/components/ui/accordion/Accordion.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
<script lang="ts">
import { Accordion as AccordionPrimitive } from "radix-svelte";
import { setAccordion, melt, type CreateAccordionProps } from ".";
// Remove the any when radix-svelte is updated to properly satisfy the types
// https://www.radix-svelte.com/docs/accordion
export let value: any = undefined;
export let multiple: CreateAccordionProps["multiple"] = false;
export let disabled: CreateAccordionProps["disabled"] = false;
export let defaultValue: CreateAccordionProps["defaultValue"] = undefined;
export let value: CreateAccordionProps["value"] = undefined;
export let onValueChange: CreateAccordionProps["onValueChange"] = undefined;
const root = setAccordion({
value,
multiple,
disabled,
defaultValue,
onValueChange
});
</script>

<AccordionPrimitive.Root bind:value {...$$restProps}>
<div use:melt={$root} {...$$restProps}>
<slot />
</AccordionPrimitive.Root>
</div>
24 changes: 13 additions & 11 deletions apps/www/src/lib/components/ui/accordion/AccordionContent.svelte
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
<script lang="ts">
import type { AccordionContentProps } from "radix-svelte";
import { Accordion as AccordionPrimitive } from "radix-svelte";
import { cn } from "$lib/utils";
import { getContent, melt } from ".";
let className: string | undefined | null = undefined;
export { className as class };
export let transition: AccordionContentProps["transition"] = true;
const { content, isSelected, props } = getContent();
</script>

<AccordionPrimitive.Content
class={cn("overflow-hidden text-sm", className)}
{...$$restProps}
{transition}
>
<div class="pb-4 pt-0">
<slot />
{#if $isSelected(props)}
<div
use:melt={$content(props)}
class={cn("overflow-hidden text-sm", className)}
{...$$restProps}
>
<div class="pb-4 pt-0">
<slot />
</div>
</div>
</AccordionPrimitive.Content>
{/if}
14 changes: 6 additions & 8 deletions apps/www/src/lib/components/ui/accordion/AccordionItem.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
<script lang="ts">
import type { AccordionItemProps } from "radix-svelte";
import { Accordion as AccordionPrimitive } from "radix-svelte";
import { cn } from "$lib/utils";
import { setAccordionItem, type AccordionItemProps, melt } from ".";
let className: string | undefined | null = undefined;
export { className as class };
export let value: AccordionItemProps["value"];
export let disabled: AccordionItemProps["disabled"] = false;
const { item, props } = setAccordionItem({ value, disabled });
</script>

<AccordionPrimitive.Item
{value}
class={cn("border-b", className)}
{...$$restProps}
>
<div use:melt={$item(props)} class={cn("border-b", className)} {...$$restProps}>
<slot />
</AccordionPrimitive.Item>
</div>
16 changes: 10 additions & 6 deletions apps/www/src/lib/components/ui/accordion/AccordionTrigger.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
<script lang="ts">
import { ChevronDown } from "lucide-svelte";
import { Accordion as AccordionPrimitive } from "radix-svelte";
import { cn } from "$lib/utils";
import { melt, getTriggerAndHeading, type AccordionHeadingProps } from ".";
let className: string | undefined | null = undefined;
export { className as class };
export let level: AccordionHeadingProps["level"] = 3;
const { heading, trigger, props } = getTriggerAndHeading(level);
</script>

<AccordionPrimitive.Header class="flex">
<AccordionPrimitive.Trigger
<div {...$heading(props.heading)} use:heading class="flex">
<button
use:melt={$trigger(props.trigger)}
class={cn(
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className
Expand All @@ -17,5 +21,5 @@
>
<slot />
<ChevronDown class="h-4 w-4 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
</button>
</div>
77 changes: 77 additions & 0 deletions apps/www/src/lib/components/ui/accordion/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,81 @@
import {
createAccordion,
type Accordion,
type AccordionItemProps as ItemProps,
type CreateAccordionProps,
type AccordionHeadingProps as HeadingProps
} from "@melt-ui/svelte";
import { getContext, setContext } from "svelte";

export { default as Accordion } from "./Accordion.svelte";
export { default as AccordionContent } from "./AccordionContent.svelte";
export { default as AccordionItem } from "./AccordionItem.svelte";
export { default as AccordionTrigger } from "./AccordionTrigger.svelte";
export { melt, type CreateAccordionProps } from "@melt-ui/svelte";

type ObjectVariation<T> = T extends object ? T : never;
export type AccordionItemProps = ObjectVariation<ItemProps>;
export type AccordionTriggerProps = AccordionItemProps;
export type AccordionHeadingProps = ObjectVariation<HeadingProps>;

export type AccordionElements = {
item: AccordionItemProps;
content: AccordionItemProps;
trigger: AccordionTriggerProps;
heading: AccordionHeadingProps;
};

const ITEM_PROPS = "accordion_itemProps";
const COMPONENT_NAME = "accordion";

export function setAccordion(props: CreateAccordionProps) {
setContext(COMPONENT_NAME, createAccordion({ ...props }));
const {
elements: { root }
} = getContext<Accordion>(COMPONENT_NAME);
return root;
}

export function getAccordion() {
return getContext<Accordion>(COMPONENT_NAME);
}

export function setAccordionItem(props: AccordionItemProps) {
setContext(ITEM_PROPS, props);
const {
elements: { item }
} = getAccordion();
return { item, props: getContext<AccordionItemProps>(ITEM_PROPS) };
}

export function getItemProps() {
const itemProps = getContext<AccordionItemProps>(ITEM_PROPS);
return itemProps;
}

export function getContent() {
const {
elements: { content },
helpers: { isSelected },
states: { value }
} = getAccordion();
const { value: props } = getItemProps();
return { content, props, isSelected, value };
}

export function getTriggerAndHeading(level: AccordionHeadingProps["level"]) {
const {
elements: { trigger, heading },
states: { value }
} = getAccordion();
const props = getItemProps();
return {
trigger,
heading,
props: {
heading: { level },
trigger: props
},
value
};
}
26 changes: 12 additions & 14 deletions apps/www/src/lib/components/ui/alert/Alert.svelte
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
<script lang="ts">
import type { VariantProps } from "class-variance-authority";
import { cva } from "class-variance-authority";
import { tv } from "tailwind-variants";
import { cn } from "$lib/utils";
const alertVariants = cva(
"relative w-full rounded-lg border p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11",
{
variants: {
variant: {
default: "bg-background text-foreground",
destructive:
"text-destructive border-destructive/50 dark:border-destructive [&>svg]:text-destructive text-destructive"
}
},
defaultVariants: {
variant: "default"
const alertVariants = tv({
base: "relative w-full rounded-lg border p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11",
variants: {
variant: {
default: "bg-background text-foreground",
destructive:
"text-destructive border-destructive/50 dark:border-destructive [&>svg]:text-destructive text-destructive"
}
},
defaultVariants: {
variant: "default"
}
);
});
let className: string | undefined | null = undefined;
export { className as class };
Expand Down
Loading

0 comments on commit a04c14d

Please sign in to comment.