[READ-ONLY] Mirror of https://github.com/flo-bit/ui-kit. 🦊 fox ui, svelte 5 and tailwind 4 flo-bit.dev/ui-kit/
svelte tailwindcss ui-components
0

Configure Feed

Select the types of activity you want to include in your feed.

improve api

Florian (Mar 6, 2026, 6:14 AM +0100) 733134c9 0976248f

+186 -82
+182 -82
apps/docs/src/lib/site-components/API.svelte
··· 1 1 <script lang="ts"> 2 - import type { APISchema } from '$lib/types/schema'; 2 + import type { APISchema, PropSchema } from '$lib/types/schema'; 3 3 import { Button, Popover, Badge } from '@foxui/all'; 4 4 5 - const { props }: { props: APISchema } = $props(); 5 + const { props: schema }: { props: APISchema } = $props(); 6 + 7 + let entries = $derived(Object.entries(schema.props ?? {}) as [string, PropSchema][]); 8 + 9 + function isComponent(value: unknown): value is import('svelte').Component { 10 + return typeof value === 'function'; 11 + } 6 12 </script> 7 13 8 - <h4 class="not-prose text-base-900 dark:text-base-50 mt-12 mb-2 text-lg font-semibold"> 9 - {props.title} 10 - </h4> 14 + {#snippet infoIcon()} 15 + <svg 16 + xmlns="http://www.w3.org/2000/svg" 17 + fill="none" 18 + viewBox="0 0 24 24" 19 + stroke-width="1.5" 20 + stroke="currentColor" 21 + class="size-4" 22 + > 23 + <path 24 + stroke-linecap="round" 25 + stroke-linejoin="round" 26 + d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" 27 + /> 28 + </svg> 29 + {/snippet} 11 30 12 - <table 13 - class="text-base-900 dark:text-base-50 not-prose divide-base-200 dark:divide-base-900 min-w-full divide-y" 14 - > 15 - <thead> 16 - <tr> 17 - <th scope="col" class="hidden px-1 py-3.5 text-left text-sm font-semibold md:table-cell" 18 - >Property</th 19 - > 20 - <th scope="col" class="hidden px-5 py-3.5 text-left text-sm font-semibold md:table-cell" 21 - >Type</th 22 - > 23 - <th scope="col" class="hidden px-1 py-3.5 text-left text-sm font-semibold md:table-cell" 24 - >Description</th 25 - > 26 - </tr> 27 - </thead> 28 - <tbody class="divide-base-200 dark:divide-base-900 divide-y text-sm"> 29 - {#each Object.entries(props.props ?? {}) as [key, prop]} 30 - <tr class="flex flex-col py-2 md:table-row"> 31 - <td class="my-2 table-cell px-1 py-3 align-top"> 32 - <div class="flex flex-row gap-1 md:flex-col md:gap-1"> 33 - <span class="text-base-900 dark:text-base-100 text-base font-semibold md:text-sm" 34 - >{key}</span 35 - > 36 - {#if prop.required} 37 - <Badge variant="primary" class="w-fit">required</Badge> 38 - {:else if prop.bindable} 39 - <Badge variant="primary_shift" class="w-fit">bindable</Badge> 40 - {/if} 41 - </div> 42 - </td> 43 - <td class="table-cell px-2 py-3 align-top md:px-6"> 44 - <span class="text-base-800 dark:text-base-200 mb-1 block font-medium md:hidden">Type</span 45 - > 31 + {#snippet tagBadges(prop: PropSchema)} 32 + {#if prop.required} 33 + <Badge variant="primary" class="w-fit">required</Badge> 34 + {/if} 35 + {#if prop.bindable} 36 + <Badge variant="primary_shift" class="w-fit">$bindable</Badge> 37 + {/if} 38 + {/snippet} 46 39 47 - <span class="text-base-600 dark:text-base-400 flex flex-row items-center gap-1"> 48 - {#if typeof prop.type === 'string'} 49 - <span>{prop.type}</span> 50 - {:else} 51 - <span class="hidden md:block">{prop.type.type}</span> 52 - <Popover> 53 - {#snippet child({ props })} 54 - <Button {...props} variant="link" class="hidden p-0 md:block"> 55 - <svg 56 - xmlns="http://www.w3.org/2000/svg" 57 - fill="none" 58 - viewBox="0 0 24 24" 59 - stroke-width="1.5" 60 - stroke="currentColor" 61 - class="size-6" 62 - > 63 - <path 64 - stroke-linecap="round" 65 - stroke-linejoin="round" 66 - d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" 67 - /> 68 - </svg> 69 - </Button> 70 - {/snippet} 71 - {prop.type.definition} 72 - </Popover> 73 - <span class="block md:hidden">{prop.type.definition}</span> 74 - {/if} 75 - </span> 76 - 77 - {#if prop.default} 78 - <Badge variant="primary_shift_2" class="w-fit">default: {prop.default}</Badge> 40 + {#snippet typeDisplay(prop: PropSchema)} 41 + {#if typeof prop.type === 'string'} 42 + <span class="font-mono text-sm text-base-500 dark:text-base-400">{prop.type}</span> 43 + {:else} 44 + <span class="flex items-center gap-1"> 45 + <span class="font-mono text-sm text-base-500 dark:text-base-400">{prop.type.type}</span> 46 + <Popover side="top" sideOffset={8}> 47 + {#snippet child({ props: popoverProps })} 48 + <Button {...popoverProps} variant="ghost" size="iconSm" class="text-base-400 hover:text-base-600 dark:text-base-500 dark:hover:text-base-300 size-5 p-0"> 49 + {@render infoIcon()} 50 + </Button> 51 + {/snippet} 52 + <div class="max-w-xs text-sm"> 53 + {#if typeof prop.type.definition === 'string'} 54 + <pre class="overflow-x-auto rounded-lg bg-base-800/50 dark:bg-base-900/50 p-2.5 font-mono text-xs text-base-200">{prop.type.definition}</pre> 55 + {:else if isComponent(prop.type.definition)} 56 + {@const DefinitionComponent = prop.type.definition} 57 + <DefinitionComponent /> 79 58 {/if} 80 - </td> 81 - <td class="table-cell px-2 py-3 align-top"> 82 - <span class="text-base-800 dark:text-base-200 mb-1 block font-medium md:hidden" 83 - >Description</span 84 - > 85 - <span class="text-base-600 dark:text-base-400">{prop.description}</span> 86 - </td> 87 - </tr> 88 - {/each} 89 - </tbody> 90 - </table> 59 + </div> 60 + </Popover> 61 + </span> 62 + {/if} 63 + {/snippet} 64 + 65 + {#snippet defaultValue(prop: PropSchema)} 66 + {#if !prop.required} 67 + <span class="mt-1 text-xs text-base-500 dark:text-base-400"> 68 + Default: {#if prop.default}<code class="font-mono text-xs">{prop.default}</code>{:else}<span class="text-base-400 dark:text-base-500">&mdash;</span>{/if} 69 + </span> 70 + {/if} 71 + {/snippet} 72 + 73 + <div class="not-prose mt-10"> 74 + <!-- Title --> 75 + <div class="mb-4"> 76 + <h4 class="text-base-900 dark:text-base-50 text-lg font-semibold">{schema.title}</h4> 77 + {#if schema.description} 78 + <p class="mt-1 text-sm text-base-500 dark:text-base-400">{schema.description}</p> 79 + {/if} 80 + </div> 81 + 82 + {#if entries.length > 0} 83 + <!-- Desktop: 3-column grid (md+) --> 84 + <div class="hidden md:block"> 85 + <!-- Header --> 86 + <div class="grid grid-cols-[1fr_1fr_1.5fr] gap-4 border-b border-base-200/50 dark:border-base-800/50 pb-2"> 87 + <span class="text-xs font-medium uppercase tracking-wide text-base-500 dark:text-base-400">Property</span> 88 + <span class="text-xs font-medium uppercase tracking-wide text-base-500 dark:text-base-400">Type</span> 89 + <span class="text-xs font-medium uppercase tracking-wide text-base-500 dark:text-base-400">Description</span> 90 + </div> 91 + 92 + <!-- Rows --> 93 + {#each entries as [key, prop] (key)} 94 + <div class="grid grid-cols-[1fr_1fr_1.5fr] gap-4 border-b border-base-200/50 dark:border-base-800/50 py-3"> 95 + <!-- Property --> 96 + <div class="flex flex-col gap-1.5"> 97 + <span class="text-sm font-semibold font-mono text-base-900 dark:text-base-100">{key}</span> 98 + {@render tagBadges(prop)} 99 + </div> 100 + 101 + <!-- Type --> 102 + <div class="flex items-start pt-0.5"> 103 + {@render typeDisplay(prop)} 104 + </div> 105 + 106 + <!-- Description --> 107 + <div class="flex flex-col"> 108 + <span class="text-sm text-base-600 dark:text-base-400">{prop.description}</span> 109 + {@render defaultValue(prop)} 110 + </div> 111 + </div> 112 + {/each} 113 + </div> 114 + 115 + <!-- Mobile: compact list (below md) --> 116 + <div class="block md:hidden"> 117 + <!-- Header --> 118 + <div class="border-b border-base-200/50 dark:border-base-800/50 pb-2"> 119 + <span class="text-xs font-medium uppercase tracking-wide text-base-500 dark:text-base-400">Property</span> 120 + </div> 121 + 122 + <!-- Rows --> 123 + {#each entries as [key, prop] (key)} 124 + <div class="flex items-center justify-between border-b border-base-200/50 dark:border-base-800/50 py-3"> 125 + <span class="text-sm font-semibold font-mono text-base-900 dark:text-base-100">{key}</span> 126 + 127 + <Popover side="left" sideOffset={8}> 128 + {#snippet child({ props: popoverProps })} 129 + <Button {...popoverProps} variant="ghost" size="icon" class="text-base-400 hover:text-base-600 dark:text-base-500 dark:hover:text-base-300"> 130 + <svg 131 + xmlns="http://www.w3.org/2000/svg" 132 + fill="none" 133 + viewBox="0 0 24 24" 134 + stroke-width="1.5" 135 + stroke="currentColor" 136 + class="size-5" 137 + > 138 + <path 139 + stroke-linecap="round" 140 + stroke-linejoin="round" 141 + d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" 142 + /> 143 + </svg> 144 + </Button> 145 + {/snippet} 146 + <div class="w-64 space-y-3 text-sm"> 147 + <!-- Property name + tags --> 148 + <div class="flex items-center justify-between"> 149 + <span class="font-mono font-semibold text-base-900 dark:text-base-50">{key}</span> 150 + <div class="flex gap-1"> 151 + {@render tagBadges(prop)} 152 + </div> 153 + </div> 154 + 155 + <!-- Type --> 156 + <div class="rounded-lg bg-base-800/50 dark:bg-base-900/50 p-2.5"> 157 + {#if typeof prop.type === 'string'} 158 + <code class="font-mono text-xs text-base-200">{prop.type}</code> 159 + {:else} 160 + <code class="font-mono text-xs text-base-200">{prop.type.type}</code> 161 + {#if typeof prop.type.definition === 'string'} 162 + <pre class="mt-1 overflow-x-auto font-mono text-xs text-base-300">{prop.type.definition}</pre> 163 + {:else if isComponent(prop.type.definition)} 164 + {@const DefinitionComponent = prop.type.definition} 165 + <div class="mt-1"> 166 + <DefinitionComponent /> 167 + </div> 168 + {/if} 169 + {/if} 170 + </div> 171 + 172 + <!-- Description --> 173 + <div> 174 + <span class="mb-1 block text-xs font-medium uppercase tracking-wide text-base-500 dark:text-base-400">Description</span> 175 + <span class="text-base-600 dark:text-base-300">{prop.description}</span> 176 + </div> 177 + 178 + <!-- Default --> 179 + {#if !prop.required} 180 + <div class="text-xs text-base-500 dark:text-base-400"> 181 + Default: {#if prop.default}<code class="font-mono">{prop.default}</code>{:else}<span>&mdash;</span>{/if} 182 + </div> 183 + {/if} 184 + </div> 185 + </Popover> 186 + </div> 187 + {/each} 188 + </div> 189 + {/if} 190 + </div>
+1
apps/docs/src/lib/types/schema.ts
··· 22 22 23 23 export type APISchema<T = Record<string, unknown>> = { 24 24 title: string; 25 + description?: string; 25 26 props?: PropObj<T>; 26 27 };
+3
apps/docs/src/routes/(main)/components/core/accordion/Props.svelte
··· 5 5 <Api 6 6 props={{ 7 7 title: 'Accordion', 8 + description: 9 + 'A vertically stacked set of interactive headings that each reveal a section of content.', 8 10 props: { 9 11 children: { 10 12 type: 'Snippet', ··· 49 51 <Api 50 52 props={{ 51 53 title: 'AccordionItem', 54 + description: 'A single collapsible section within the accordion.', 52 55 props: { 53 56 title: { 54 57 type: 'string',