diff --git a/README.md b/README.md index e69de29b..352cac15 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,13 @@ +![github-banner](https://github.com/skeletonlabs/floating-ui-svelte/assets/1509726/46b00221-9088-4986-86c8-60a480d9213f) + +# Floating UI Svelte + +Svelte bindings for [Floating UI](https://github.com/floating-ui/floating-ui). Based on [Floating UI React](https://floating-ui.com/docs/react). + +## Attribution + +Maintained by [Hugo Korte](https://github.com/Hugos68), [Skeleton Labs](https://www.skeletonlabs.co/), and the [Svelte community](https://svelte.dev/). + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/packages/docs/package.json b/packages/docs/package.json index e1c19e50..3d6f152b 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "dev": "vite dev", - "build": "vite build", + "build": "vite build && pagefind", "preview": "vite preview", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch" @@ -15,11 +15,13 @@ "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0", "autoprefixer": "^10.4.20", + "pagefind": "^1.3.0", "svelte": "^5.0.0", "svelte-check": "^4.0.0", "tailwindcss": "^3.4.9", "typescript": "^5.0.0", - "vite": "^5.4.11" + "vite": "^5.4.11", + "vite-plugin-pagefind": "^0.3.0" }, "dependencies": { "@tailwindcss/forms": "^0.5.9", diff --git a/packages/docs/pagefind.json b/packages/docs/pagefind.json new file mode 100644 index 00000000..e35145bc --- /dev/null +++ b/packages/docs/pagefind.json @@ -0,0 +1,9 @@ +{ + "site": "build", + "exclude_selectors": [".expressive-code"], + "vite_plugin_pagefind": { + "assets_dir": "static", + "build_command": "pnpm build", + "dev_strategy": "lazy" + } +} diff --git a/packages/docs/src/app.css b/packages/docs/src/app.css index 76fcadcc..d424fa74 100644 --- a/packages/docs/src/app.css +++ b/packages/docs/src/app.css @@ -1,3 +1,246 @@ -@import "tailwindcss/base"; -@import "tailwindcss/components"; -@import "tailwindcss/utilities"; +/* Write your global styles here, in PostCSS syntax */ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* Theme --- */ + +@layer base { + :root { + /* Colors */ + --color-surface-50: 255 255 255; + --color-surface-100: 243 243 247; + --color-surface-200: 220 223 236; + --color-surface-300: 176 178 195; + --color-surface-400: 191 195 217; + --color-surface-500: 87 89 105; + --color-surface-600: 45 46 58; + --color-surface-700: 39 41 53; + --color-surface-800: 31 32 40; + --color-surface-900: 24 25 31; + --color-surface-950: 18 18 21; + } + /* Gradients */ + /* .light-xxx-gradient { + background-image: linear-gradient(45deg, #eff6ff, #ecfeff, #cffafe, #f0fdfa, #faf5ff); + } + .dark-xxx-gradient { + background-image: linear-gradient( + 45deg, + rgba(255, 100, 255, 0.2), + rgba(100, 100, 255, 0.2), + rgba(50, 200, 255, 0.25) + ); + } */ + .dark-nav-gradient { + background-image: linear-gradient( + 195deg, + hsl(348deg 10% 90%) 0%, + hsl(351deg 31% 80%) 2%, + hsl(325deg 45% 69%) 6%, + hsl(330deg 32% 57%) 12%, + hsl(320deg 22% 48%) 19%, + hsl(285deg 22% 33%) 27%, + hsl(240deg 20% 22%) 38%, + hsl(232deg 18% 17%) 50%, + hsl(232deg 13% 14%) 68%, + hsl(233deg 15% 14%) 100% + ); + } + .light-nav-gradient { + background-image: linear-gradient( + 195deg, + rgb(245, 245, 255) 0%, + rgb(245, 200, 255) 2%, + rgb(255 210 225) 6%, + rgb(255 227 225) 12%, + rgb(249, 246, 248) 19%, + rgb(240, 240, 255) 27%, + rgb(245, 245, 255) 38%, + rgb(240, 252, 253) 50%, + rgb(252, 252, 253) 68%, + rgb(255, 255, 255) 100% + ); + } +} + +/* Globals --- */ + +body { + @apply text-surface-700 dark:text-surface-300; + @apply bg-surface-200 dark:bg-surface-800; +} + +/* Typography --- */ + +/* Headings */ +.h1 { + @apply text-rose-500 font-bold text-5xl; +} +.h1 span { + @apply bg-gradient-to-br from-rose-400 to-purple-400/90 bg-clip-text text-transparent box-decoration-clone; +} +.h2 { + @apply text-black dark:text-white font-bold text-3xl; +} +.h3 { + @apply text-black dark:text-white font-bold text-xl; +} + +/* Anchors */ +#page-container .anchor { + @apply underline; + @apply text-rose-700 hover:text-black; + @apply dark:text-rose-300 hover:dark:text-white; +} +footer .anchor { + @apply text-blue-600 dark:text-blue-400 underline; +} + +/* Highlight */ +.highlight { + @apply text-black dark:text-white; +} + +/* Pre & Code */ +.pre { + @apply bg-black text-white p-4 rounded; +} +.code { + @apply bg-surface-50/50 dark:bg-surface-600 px-2 py-1 rounded; + @apply text-sm text-emerald-500 dark:text-emerald-300; +} + +/* Keyboard */ +.kbd { + @apply text-sm bg-surface-50/50 dark:bg-surface-600 px-2 py-1 rounded; +} + +/* Unordered List */ +.ul { + @apply list-disc list-outside ml-7 space-y-4; +} + +/* Utility Classes */ + +/* Preview Examples */ +.preview { + @apply bg-surface-100 dark:bg-surface-900 ring-inset p-10 flex justify-center items-center rounded-lg; +} + +/* Floating (required) */ +.floating { + @apply w-max absolute top-0 left-0 z-10; +} + +.popover-neutral { + @apply bg-surface-500 text-white p-8 max-w-sm rounded shadow-xl; +} + +/* Buttons */ +.btn-gradient { + @apply flex items-center gap-2; + @apply py-3 px-6 rounded shadow-lg; + @apply bg-gradient-to-br from-red-300 via-violet-300 to-cyan-400; + @apply text-black font-bold; +} +.btn-neutral { + @apply flex items-center gap-2; + @apply py-3 px-6 rounded shadow-lg; + @apply bg-neutral-950 hover:bg-neutral-900 dark:bg-surface-50 hover:dark:bg-surface-100; + @apply text-white dark:text-black font-bold; +} +.btn-rose-sm { + @apply flex items-center gap-2; + @apply bg-rose-500 hover:bg-rose-600 text-white text-sm font-medium py-1 px-4 rounded shadow-lg; +} + +/* Cards */ +.card { + @apply p-8 lg:p-12 rounded-3xl; +} +.card-gradient { + @apply bg-white dark:bg-surface-700 bg-gradient-to-br; + @apply from-blue-50 to-surface-50; + @apply dark:from-purple-700/10 dark:to-cyan-700/10; +} + +/* Alerts */ +.alert { + @apply bg-blue-500 text-white p-8 rounded-lg space-y-4; +} + +/* Tables */ +.table-wrap { + @apply w-full overflow-auto; +} +.table { + @apply relative w-full; +} +.table thead { + @apply border-b border-surface-500/50; +} +.table th { + @apply text-left font-bold; +} +.table tbody { + @apply divide-y divide-surface-500/50; +} +.table th, +.table td { + @apply p-2 py-4 align-top; +} +.table .meta-type { + @apply inline-block bg-surface-50/50 dark:bg-surface-600 px-2 py-1 rounded; + @apply text-xs text-purple-500 dark:text-purple-300; +} +.table .meta-default { + @apply inline-block bg-surface-50/50 dark:bg-surface-600 px-2 py-1 rounded; + @apply text-xs italic text-blue-500 dark:text-blue-300; +} + +/* Scrollbars --- */ + +:root { + scrollbar-color: rgba(128, 128, 128, 0.5) rgba(0, 0, 0, 0.1); /* thumb / track */ + scrollbar-width: thin; +} + +/* Chrome, Safari and Opera */ +.no-scrollbar::-webkit-scrollbar { + display: none; +} +/* IE, Edge and Firefox */ +.no-scrollbar { + -ms-overflow-style: none; + scrollbar-width: none; +} + +/* Animations --- */ + +.anim-float { + animation-name: animFloat; + animation-duration: 5s; + animation-iteration-count: infinite; + animation-timing-function: ease-in-out; +} + +@keyframes animFloat { + 0% { + transform: translateY(0px); + } + 50% { + transform: translateY(15px); + } + 100% { + transform: translateY(0px); + } +} + +/* Shiki Highlighting --- */ + +html.dark .shiki, +html.dark .shiki span { + color: var(--shiki-dark) !important; + background-color: var(--shiki-dark-bg) !important; +} diff --git a/packages/docs/src/lib/components/CodeBlock/CodeBlock.svelte b/packages/docs/src/lib/components/CodeBlock/CodeBlock.svelte new file mode 100644 index 00000000..89ce8ec4 --- /dev/null +++ b/packages/docs/src/lib/components/CodeBlock/CodeBlock.svelte @@ -0,0 +1,99 @@ + + + +
+ + + {lang} + + +
{@html renderedCode}
+
+ + + + diff --git a/packages/docs/src/lib/components/Dialog/Dialog.svelte b/packages/docs/src/lib/components/Dialog/Dialog.svelte new file mode 100644 index 00000000..585aaf71 --- /dev/null +++ b/packages/docs/src/lib/components/Dialog/Dialog.svelte @@ -0,0 +1,78 @@ + + + + {#if open} +
+ + {/if} +
diff --git a/packages/docs/src/lib/components/Dialog/SearchDialog.svelte b/packages/docs/src/lib/components/Dialog/SearchDialog.svelte new file mode 100644 index 00000000..78722602 --- /dev/null +++ b/packages/docs/src/lib/components/Dialog/SearchDialog.svelte @@ -0,0 +1,100 @@ + + + + + +
+
+ + +
+
+ {#if query === ''} +

What can we help you find?

+ {:else} + {#await searchPromise} +

+ +

+ {:then results} + {#if results.length > 0} + + {:else if query !== ''} +

No results found for "{query}"

+ {/if} + {/await} + {/if} +
+
+
+ + diff --git a/packages/docs/src/lib/components/Logo/Logo.svelte b/packages/docs/src/lib/components/Logo/Logo.svelte new file mode 100644 index 00000000..40b18d6c --- /dev/null +++ b/packages/docs/src/lib/components/Logo/Logo.svelte @@ -0,0 +1,16 @@ + + Svelte + + + diff --git a/packages/docs/src/lib/components/Navigation/Navigation.svelte b/packages/docs/src/lib/components/Navigation/Navigation.svelte new file mode 100644 index 00000000..75b4291a --- /dev/null +++ b/packages/docs/src/lib/components/Navigation/Navigation.svelte @@ -0,0 +1,113 @@ + + +
+ +
+ + + +
+ +
+ {#each navigation as section} + + {/each} +
+
+ + diff --git a/packages/docs/src/lib/components/Overlay/Overlay.svelte b/packages/docs/src/lib/components/Overlay/Overlay.svelte new file mode 100644 index 00000000..b5441ea0 --- /dev/null +++ b/packages/docs/src/lib/components/Overlay/Overlay.svelte @@ -0,0 +1,15 @@ + + +
+ +
+ {@render children()} +
diff --git a/packages/docs/src/lib/components/PageFooter/PageFooter.svelte b/packages/docs/src/lib/components/PageFooter/PageFooter.svelte new file mode 100644 index 00000000..604ea32a --- /dev/null +++ b/packages/docs/src/lib/components/PageFooter/PageFooter.svelte @@ -0,0 +1,16 @@ + + + diff --git a/packages/docs/src/lib/components/PageHeader/PageHeader.svelte b/packages/docs/src/lib/components/PageHeader/PageHeader.svelte new file mode 100644 index 00000000..e53122bd --- /dev/null +++ b/packages/docs/src/lib/components/PageHeader/PageHeader.svelte @@ -0,0 +1,45 @@ + + +
+
+
+ + Floating UI Svelte +
+ + +
+
diff --git a/packages/docs/src/lib/components/Portal/Portal.svelte b/packages/docs/src/lib/components/Portal/Portal.svelte new file mode 100644 index 00000000..2c621dac --- /dev/null +++ b/packages/docs/src/lib/components/Portal/Portal.svelte @@ -0,0 +1,31 @@ + + +
+ {@render children()} +
diff --git a/packages/docs/src/lib/components/Preview/Preview.svelte b/packages/docs/src/lib/components/Preview/Preview.svelte new file mode 100644 index 00000000..28fb5ada --- /dev/null +++ b/packages/docs/src/lib/components/Preview/Preview.svelte @@ -0,0 +1,42 @@ + + +
+ + + +
+ {#if activeTab === 'preview' && preview}
{@render preview()}
{/if} + {#if activeTab === 'code' && code}{@render code()}{/if} +
+
diff --git a/packages/docs/src/lib/components/Table/Table.svelte b/packages/docs/src/lib/components/Table/Table.svelte new file mode 100644 index 00000000..fdcaaf8f --- /dev/null +++ b/packages/docs/src/lib/components/Table/Table.svelte @@ -0,0 +1,37 @@ + + +
+ + + {#each data as row} + + + + + + {/each} + +
+
+ {row.property} + + {#if row.required} +
+ {/if} +
+
+ +

{row.description}

+ +
+ {#if row.type}

{row.type}

{/if} + {#if row.default}

{row.default}

{/if} +
+
+
diff --git a/packages/docs/src/lib/index.ts b/packages/docs/src/lib/index.ts deleted file mode 100644 index 856f2b6c..00000000 --- a/packages/docs/src/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -// place files you want to import through the `$lib` alias in this folder. diff --git a/packages/docs/src/lib/stores.svelte.ts b/packages/docs/src/lib/stores.svelte.ts new file mode 100644 index 00000000..fa4e43ca --- /dev/null +++ b/packages/docs/src/lib/stores.svelte.ts @@ -0,0 +1,11 @@ +import { getContext, setContext } from 'svelte'; + +// Reusable State Stores + +// Navigation Drawer --- +type Drawer = { open: boolean }; + +const drawerKey = Symbol('drawer'); + +export const getDrawer = () => getContext(drawerKey); +export const setDrawer = (drawer: Drawer) => setContext(drawerKey, drawer); diff --git a/packages/docs/src/lib/themes/moonlight-dark.json b/packages/docs/src/lib/themes/moonlight-dark.json new file mode 100644 index 00000000..288230e9 --- /dev/null +++ b/packages/docs/src/lib/themes/moonlight-dark.json @@ -0,0 +1,960 @@ +{ + "name": "moonlight-ii", + "type": "dark", + "colors": { + "foreground": "#c8d3f5", + "focusBorder": "#82aaff", + "contrastBorder": "#191a2a", + "editorCursor.foreground": "#82aaff", + "editorRuler.foreground": "#444a73bb", + "scrollbar.shadow": "#00000022", + "tree.indentGuidesStroke": "#828bb866", + "editorLink.activeForeground": "#c8d3f5", + "selection.background": "#c8d3f5", + "progressBar.background": "#82aaff", + "textLink.foreground": "#65bcff", + "textLink.activeForeground": "#b2dfff", + "editorLineNumber.foreground": "#444a73", + "editorLineNumber.activeForeground": "#828bb8", + "editorBracketMatch.border": "#82aaffbb", + "editorBracketMatch.background": "#222436", + "editorWhitespace.foreground": "#c8d3f540", + "editor.background": "rgba(var(--color-surface-700))", + "editor.foreground": "#c8d3f5", + "editor.lineHighlightBackground": "#2f334d", + "editor.selectionBackground": "#828bb850", + "editor.selectionHighlightBackground": "#444a73", + "editor.findMatchBackground": "#444a73", + "editor.findMatchBorder": "#86e1fc", + "editor.findMatchHighlightBackground": "#444a73", + "editorOverviewRuler.findMatchForeground": "#86e1fcbb", + "editorOverviewRuler.errorForeground": "#ff757fcc", + "editorOverviewRuler.infoForeground": "#65bcff66", + "editorOverviewRuler.warningForeground": "#ffc777cc", + "editorOverviewRuler.modifiedForeground": "#82aaff66", + "editorOverviewRuler.addedForeground": "#c3e88d66", + "editorOverviewRuler.deletedForeground": "#ff98a466", + "editorOverviewRuler.bracketMatchForeground": "#3e68d7bb", + "editorOverviewRuler.border": "#222436", + "editorHoverWidget.background": "#1b1d2c", + "editorHoverWidget.border": "#000000aa", + "editorIndentGuide.background": "#444a73bb", + "editorIndentGuide.activeBackground": "#828bb8aa", + "editorGroupHeader.tabsBackground": "#1e2030", + "editorGroup.border": "#191a2a", + "editorGutter.modifiedBackground": "#82aaff66", + "editorGutter.addedBackground": "#c3e88d66", + "editorGutter.deletedBackground": "#ff5370aa", + "tab.activeBorder": "#82aaff", + "tab.activeModifiedBorder": "#828bb8", + "tab.unfocusedActiveBorder": "#828bb8", + "tab.activeForeground": "#c8d3f5", + "tab.activeBackground": "#222436", + "tab.inactiveForeground": "#828bb8", + "tab.inactiveBackground": "#1e2030", + "tab.unfocusedActiveForeground": "#c8d3f5", + "tab.border": "#191a2a", + "statusBar.noFolderBackground": "#222436", + "statusBar.border": "#191a2a", + "statusBar.background": "#1e2030", + "statusBar.foreground": "#828bb8", + "statusBar.debuggingBackground": "#82aaff", + "statusBar.debuggingForeground": "#c8d3f5", + "statusBarItem.hoverBackground": "#828bb820", + "activityBar.background": "#1e2030", + "activityBar.border": "#22243660", + "activityBar.foreground": "#b4c2f0", + "activityBarBadge.background": "#3e68d7", + "activityBarBadge.foreground": "#ffffff", + "titleBar.activeBackground": "#1e2030", + "titleBar.activeForeground": "#c8d3f5", + "titleBar.inactiveBackground": "#1e2030", + "titleBar.inactiveForeground": "#828bb8", + "sideBar.background": "#1e2030", + "sideBar.foreground": "#828bb8", + "sideBar.border": "#191a2a", + "titleBar.border": "#191a2a", + "sideBarTitle.foreground": "#c8d3f5", + "sideBarSectionHeader.background": "#1e2030", + "sideBarSectionHeader.border": "#2f334d", + "input.background": "#191a2a", + "input.foreground": "#c8d3f5", + "input.placeholderForeground": "#c8d3f5aa", + "input.border": "#00000066", + "inputValidation.errorBackground": "#c53b53", + "inputValidation.errorForeground": "#ffffff", + "inputValidation.errorBorder": "#ff537050", + "inputValidation.infoBackground": "#446bbb", + "inputValidation.infoForeground": "#ffffff", + "inputValidation.infoBorder": "#82aaff50", + "inputValidation.warningBackground": "#ad7c43", + "inputValidation.warningForeground": "#ffffff", + "inputValidation.warningBorder": "#ffc77750", + "dropdown.foreground": "#c8d3f5", + "dropdown.background": "#2f334d", + "dropdown.border": "#00000066", + "list.hoverForeground": "#c8d3f5", + "list.hoverBackground": "#1e2030", + "list.activeSelectionBackground": "#383e5c", + "list.activeSelectionForeground": "#ffffff", + "list.inactiveSelectionForeground": "#c8d3f5", + "list.inactiveSelectionBackground": "#292e46", + "list.focusBackground": "#131421", + "list.focusForeground": "#c8d3f5", + "list.highlightForeground": "#86e1fc", + "list.warningForeground": "#ffc777cc", + "terminal.foreground": "#bcc4d6", + "terminal.selectionBackground": "#c8d3f544", + "terminal.ansiWhite": "#c8d3f5", + "terminal.ansiBlack": "#000000", + "terminal.ansiBlue": "#82aaff", + "terminal.ansiCyan": "#86e1fc", + "terminal.ansiGreen": "#c3e88d", + "terminal.ansiMagenta": "#fca7ea", + "terminal.ansiRed": "#ff757f", + "terminal.ansiYellow": "#ffc777", + "terminal.ansiBrightWhite": "#c8d3f5", + "terminal.ansiBrightBlack": "#828bb8", + "terminal.ansiBrightBlue": "#82aaff", + "terminal.ansiBrightCyan": "#86e1fc", + "terminal.ansiBrightGreen": "#c3e88d", + "terminal.ansiBrightMagenta": "#fca7ea", + "terminal.ansiBrightRed": "#ff757f", + "terminal.ansiBrightYellow": "#ffc777", + "terminal.border": "#2f334d", + "scrollbarSlider.background": "#828bb830", + "scrollbarSlider.hoverBackground": "#a9b8e830", + "scrollbarSlider.activeBackground": "#82aaff", + "minimap.findMatchHighlight": "#86e1fccc", + "minimap.selectionHighlight": "#86e1fc33", + "minimapGutter.addedBackground": "#c3e88d66", + "minimapGutter.modifiedBackground": "#82aaff66", + "editorSuggestWidget.background": "#191a2a", + "editorSuggestWidget.foreground": "#a9b8e8", + "editorSuggestWidget.highlightForeground": "#86e1fc", + "editorSuggestWidget.selectedBackground": "#2f334d", + "editorSuggestWidget.border": "#00000033", + "editorError.foreground": "#ff5370", + "editorWarning.foreground": "#ffc777cc", + "editorWidget.background": "#1e2030", + "editorWidget.resizeBorder": "#82aaff", + "editorMarkerNavigation.background": "#c8d3f505", + "widget.shadow": "#00000033", + "panel.border": "#00000033", + "panel.background": "#1e2030", + "panel.dropBackground": "#c8d3f5", + "panelTitle.inactiveForeground": "#828bb8", + "panelTitle.activeForeground": "#c8d3f5", + "panelTitle.activeBorder": "#82aaff", + "terminalCursor.foreground": "#82aaff", + "diffEditor.insertedTextBackground": "#c3e88d15", + "diffEditor.removedTextBackground": "#ff537020", + "notifications.background": "#191a2a", + "notifications.foreground": "#c8d3f5", + "notificationLink.foreground": "#82aaff", + "badge.background": "#3e68d7", + "badge.foreground": "#ffffff", + "button.background": "#3e68d7", + "button.hoverBackground": "#65bcffcc", + "extensionButton.prominentBackground": "#3e68d7", + "extensionButton.prominentHoverBackground": "#65bcffcc", + "peekView.border": "#00000030", + "peekViewEditor.background": "#c8d3f505", + "peekViewTitle.background": "#c8d3f505", + "peekViewResult.background": "#c8d3f505", + "peekViewEditorGutter.background": "#c8d3f505", + "peekViewTitleDescription.foreground": "#c8d3f560", + "peekViewResult.matchHighlightBackground": "#828bb850", + "peekViewEditor.matchHighlightBackground": "#828bb850", + "debugToolBar.background": "#1e2030", + "pickerGroup.foreground": "#82aaff", + "gitDecoration.deletedResourceForeground": "#ff5370dd", + "gitDecoration.conflictingResourceForeground": "#ffc777cc", + "gitDecoration.modifiedResourceForeground": "#82aaffee", + "gitDecoration.untrackedResourceForeground": "#77e0c6dd", + "gitDecoration.ignoredResourceForeground": "#777fabaa", + "gitlens.trailingLineForegroundColor": "#828bb8aa", + "editorCodeLens.foreground": "#828bb8", + "peekViewResult.selectionBackground": "#828bb870", + "breadcrumb.background": "#222436", + "breadcrumb.foreground": "#828bb8", + "breadcrumb.focusForeground": "#c8d3f5", + "breadcrumb.activeSelectionForeground": "#82aaff", + "breadcrumbPicker.background": "#1e2030", + "menu.background": "#1e2030", + "menu.foreground": "#c8d3f5", + "menu.selectionBackground": "#00000050", + "menu.selectionForeground": "#82aaff", + "menu.selectionBorder": "#00000030", + "menu.separatorBackground": "#c8d3f5", + "menubar.selectionBackground": "#00000030", + "menubar.selectionForeground": "#82aaff", + "menubar.selectionBorder": "#00000030", + "settings.dropdownForeground": "#c8d3f5", + "settings.dropdownBackground": "#2f334d", + "settings.dropdownBorder": "#191a2a", + "settings.numberInputForeground": "#c8d3f5", + "settings.numberInputBackground": "#191a2a", + "settings.numberInputBorder": "#00000066", + "settings.textInputForeground": "#c8d3f5", + "settings.textInputBackground": "#191a2a", + "settings.textInputBorder": "#00000066", + "settings.headerForeground": "#82aaff", + "settings.modifiedItemIndicator": "#82aaff", + "settings.checkboxBackground": "#131421", + "settings.checkboxForeground": "#c8d3f5", + "settings.checkboxBorder": "#00000066" + }, + "tokenColors": [ + { + "name": "Comment", + "scope": ["comment", "punctuation.definition.comment", "string.quoted.docstring"], + "settings": { + "foreground": "#878eae" + } + }, + { + "name": "Variables and Plain Text", + "scope": ["variable", "support.variable", "string constant.other.placeholder", "text.html"], + "settings": { + "foreground": "#c8d3f5" + } + }, + { + "name": "DOM Variables", + "scope": [ + "support.variable.dom", + "support.constant.math", + "support.type.object.module", + "support.variable.object.process", + "support.constant.json" + ], + "settings": { + "foreground": "#ffc777" + } + }, + { + "name": "Nil", + "scope": ["constant.language.undefined", "constant.language.null"], + "settings": { + "foreground": "#7f85a3" + } + }, + { + "name": "PHP Constants", + "scope": ["constant.other.php"], + "settings": { + "foreground": "#ffc777" + } + }, + { + "name": "Colors", + "scope": ["constant.other.color"], + "settings": { + "foreground": "#ffffff" + } + }, + { + "name": "Invalid", + "scope": ["invalid", "invalid.illegal"], + "settings": { + "foreground": "#ff5370" + } + }, + { + "name": "Invalid deprecated", + "scope": ["invalid.deprecated"], + "settings": { + "foreground": "#c099ff" + } + }, + { + "name": "Keyword, Storage", + "scope": ["keyword", "storage.type", "storage.modifier", "keyword.other.important"], + "settings": { + "foreground": "#c099ff" + } + }, + { + "name": "Keyword, Storage", + "scope": ["keyword.control", "storage"], + "settings": {} + }, + { + "name": "Interpolation", + "scope": ["punctuation.definition.template-expression", "punctuation.section.embedded"], + "settings": { + "foreground": "#86e1fc" + } + }, + { + "name": "Spread", + "scope": ["keyword.operator.spread", "keyword.operator.rest"], + "settings": { + "foreground": "#ff757f", + "fontStyle": "bold" + } + }, + { + "name": "Operator, Misc", + "scope": [ + "keyword.operator", + "keyword.control", + "punctuation", + "punctuation.definition.string", + "punctuation.support.type.property-name", + "text.html.vue-html meta.tag", + "punctuation.definition.keyword", + "punctuation.terminator.rule", + "punctuation.definition.entity", + "constant.other.color", + "meta.tag", + "punctuation.definition.tag", + "punctuation.separator.inheritance.php", + "punctuation.definition.block.tag", + "punctuation.definition.tag.html", + "punctuation.definition.tag.begin.html", + "punctuation.definition.tag.end.html", + "meta.property-list", + "meta.brace.square", + "keyword.other.template", + "keyword.other.substitution" + ], + "settings": { + "foreground": "#86e1fc" + } + }, + { + "name": "Keyword Control", + "scope": ["keyword.control"], + "settings": {} + }, + { + "name": "Tag", + "scope": ["entity.name.tag", "meta.tag", "markup.deleted.git_gutter"], + "settings": { + "foreground": "#ff757f" + } + }, + { + "name": "Function, Special Method", + "scope": ["entity.name.function", "variable.function", "keyword.other.special-method"], + "settings": { + "foreground": "#82aaff" + } + }, + { + "name": "Support Function", + "scope": ["support.function", "meta.function-call entity.name.function"], + "settings": { + "foreground": "#65bcff" + } + }, + { + "name": "C-related Block Level Variables", + "scope": ["source.cpp meta.block variable.other"], + "settings": { + "foreground": "#ff757f" + } + }, + { + "name": "Other Variable, String Link", + "scope": ["support.other.variable", "string.other.link"], + "settings": { + "foreground": "#ff757f" + } + }, + { + "name": "Constant, Function Argument, Tag Attribute, Embedded", + "scope": [ + "variable.other.constant", + "constant.language", + "keyword.other.type.php", + "storage.type.php", + "support.constant", + "constant.character", + "constant.escape", + "keyword.other.unit" + ], + "settings": { + "foreground": "#ff98a4" + } + }, + { + "name": "Number, Boolean", + "scope": [ + "constant.numeric", + "constant.language.boolean", + "constant.language.json", + "constant.language.infinity", + "constant.language.nan" + ], + "settings": { + "foreground": "#ff966c" + } + }, + { + "name": "Function Argument", + "scope": [ + "variable.parameter.function.language.special", + "variable.parameter", + "meta.function.parameter variable" + ], + "settings": { + "foreground": "#fca7ea" + } + }, + { + "name": "String, Symbols, Inherited Class, Markup Heading", + "scope": [ + "string", + "constant.other.symbol", + "constant.other.key", + "entity.other.inherited-class", + "markup.heading", + "markup.inserted.git_gutter", + "meta.group.braces.curly constant.other.object.key.js string.unquoted.label.js", + "meta.attribute-selector" + ], + "settings": { + "fontStyle": "", + "foreground": "#c3e88d" + } + }, + { + "name": "Object", + "scope": ["variable.other.object"], + "settings": { + "foreground": "#ffc777" + } + }, + { + "name": "Object Key", + "scope": [ + "meta.object-literal.key", + "string.alias.graphql", + "string.unquoted.graphql", + "string.unquoted.alias.graphql", + "meta.field.declaration.ts variable.object.property", + "variable.object.property" + ], + "settings": { + "foreground": "#4fd6be" + } + }, + { + "name": "Nested Object Property", + "scope": ["meta.object.member", "variable.other.object.property"], + "settings": { + "foreground": "#a9b8e8" + } + }, + { + "name": "Object Property", + "scope": [ + "variable.other.property", + "support.variable.property", + "support.variable.property.dom" + ], + "settings": { + "foreground": "#a9b8e8" + } + }, + { + "name": "Haskell Constants", + "scope": ["source.haskell constant.other.haskell"], + "settings": { + "foreground": "#ff98a4" + } + }, + { + "name": "Haskell Imports", + "scope": ["source.haskell meta.import.haskell entity.name.namespace"], + "settings": { + "foreground": "#c8d3f5" + } + }, + { + "name": "Types Fixes", + "scope": ["source.haskell storage.type", "source.c storage.type", "source.java storage.type"], + "settings": { + "foreground": "#ffc777" + } + }, + { + "name": "Lambda Arrow", + "scope": ["storage.type.function"], + "settings": { + "foreground": "#c099ff" + } + }, + { + "name": "Class, Support", + "scope": [ + "entity.name", + "support.type", + "support.class", + "support.orther.namespace.use.php", + "meta.use.php", + "support.other.namespace.php", + "markup.changed.git_gutter", + "support.type.sys-types" + ], + "settings": { + "foreground": "#ffc777" + } + }, + { + "name": "Entity types", + "scope": ["support.type"], + "settings": { + "foreground": "#ff966c" + } + }, + { + "name": "CSS Class and Support", + "scope": [ + "source.css support.type.property-name", + "source.sass support.type.property-name", + "source.scss support.type.property-name", + "source.less support.type.property-name", + "source.stylus support.type.property-name", + "source.postcss support.type.property-name", + "support.type.property-name.css", + "support.type.vendored.property-name" + ], + "settings": { + "foreground": "#82aaff" + } + }, + { + "name": "Sub-methods", + "scope": ["entity.name.module.js", "variable.import.parameter.js", "variable.other.class.js"], + "settings": { + "foreground": "#ff757f" + } + }, + { + "name": "Language methods", + "scope": ["variable.language"], + "settings": { + "foreground": "#ff757f" + } + }, + { + "name": "entity.name.method.js", + "scope": ["entity.name.method.js"], + "settings": { + "foreground": "#82aaff" + } + }, + { + "name": "meta.method.js", + "scope": ["meta.class-method.js entity.name.function.js", "variable.function.constructor"], + "settings": { + "foreground": "#82aaff" + } + }, + { + "name": "Attributes", + "scope": ["entity.other.attribute-name"], + "settings": { + "foreground": "#c099ff" + } + }, + { + "name": "HTML Attributes", + "scope": [ + "text.html.basic entity.other.attribute-name.html", + "text.html.basic entity.other.attribute-name" + ], + "settings": { + "foreground": "#ffc777" + } + }, + { + "name": "HTML Doctype", + "scope": [ + "meta.tag.metadata.doctype entity.name.tag", + "meta.tag.metadata.doctype entity.other.attribute-name" + ], + "settings": { + "foreground": "#c099ff" + } + }, + { + "name": "CSS Classes", + "scope": ["entity.other.attribute-name.class"], + "settings": { + "foreground": "#ffc777" + } + }, + { + "name": "CSS ID's", + "scope": ["source.sass keyword.control"], + "settings": { + "foreground": "#82aaff" + } + }, + { + "name": "CSS pseudo selectors", + "scope": [ + "entity.other.attribute-name.pseudo-class", + "entity.other.attribute-name.pseudo-element" + ], + "settings": { + "foreground": "#4fd6be" + } + }, + { + "name": "CSS Property value", + "scope": ["support.constant.property-value"], + "settings": { + "foreground": "#fca7ea" + } + }, + { + "name": "Inserted", + "scope": ["markup.inserted"], + "settings": { + "foreground": "#c3e88d" + } + }, + { + "name": "Deleted", + "scope": ["markup.deleted"], + "settings": { + "foreground": "#ff757f" + } + }, + { + "name": "Changed", + "scope": ["markup.changed"], + "settings": { + "foreground": "#c099ff" + } + }, + { + "name": "Regular Expressions", + "scope": ["string.regexp"], + "settings": { + "foreground": "#b4f9f8" + } + }, + { + "name": "Regular Expressions - Punctuation", + "scope": ["punctuation.definition.group"], + "settings": { + "foreground": "#ff757f" + } + }, + { + "name": "Regular Expressions - Character Class", + "scope": ["constant.other.character-class.regexp", "keyword.control.anchor.regexp"], + "settings": { + "foreground": "#c099ff" + } + }, + { + "name": "Regular Expressions - Character Class Set", + "scope": ["constant.other.character-class.set.regexp"], + "settings": { + "foreground": "#ffc777" + } + }, + { + "name": "Regular Expressions - Quantifier", + "scope": ["keyword.operator.quantifier.regexp"], + "settings": { + "foreground": "#fca7ea" + } + }, + { + "name": "Escape Characters", + "scope": ["constant.character.escape"], + "settings": { + "foreground": "#86e1fc" + } + }, + { + "name": "URL", + "scope": ["*url*", "*link*", "*uri*"], + "settings": { + "fontStyle": "underline" + } + }, + { + "name": "Decorators", + "scope": [ + "tag.decorator.js entity.name.tag.js", + "tag.decorator.js punctuation.definition.tag.js" + ], + "settings": { + "foreground": "#82aaff" + } + }, + { + "name": "CSS Units", + "scope": ["keyword.other.unit"], + "settings": { + "foreground": "#fc7b7b" + } + }, + { + "name": "ES7 Bind Operator", + "scope": ["source.js constant.other.object.key.js string.unquoted.label.js"], + "settings": { + "foreground": "#ff757f" + } + }, + { + "name": "JSON Key - Level 0", + "scope": ["source.json meta.structure.dictionary.json support.type.property-name.json"], + "settings": { + "foreground": "#82aaff" + } + }, + { + "name": "JSON Key - Level 1", + "scope": [ + "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json" + ], + "settings": { + "foreground": "#65bcff" + } + }, + { + "name": "JSON Key - Level 2", + "scope": [ + "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json" + ], + "settings": { + "foreground": "#ff757f" + } + }, + { + "name": "JSON Key - Level 3", + "scope": [ + "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json" + ], + "settings": { + "foreground": "#fca7ea" + } + }, + { + "name": "JSON Key - Level 4", + "scope": [ + "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json" + ], + "settings": { + "foreground": "#ffc777" + } + }, + { + "name": "JSON Key - Level 5", + "scope": [ + "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json" + ], + "settings": { + "foreground": "#4fd6be" + } + }, + { + "name": "JSON Key - Level 6", + "scope": [ + "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json" + ], + "settings": { + "foreground": "#82aaff" + } + }, + { + "name": "Plain Punctuation", + "scope": ["punctuation.definition.list_item.markdown"], + "settings": { + "foreground": "#828bb8" + } + }, + { + "name": "Block Punctuation", + "scope": [ + "meta.block", + "meta.brace", + "punctuation.definition.block", + "punctuation.definition.parameters", + "punctuation.section.function" + ], + "settings": { + "foreground": "#b4c2f0" + } + }, + { + "name": "Markdown - Plain", + "scope": ["meta.jsx.children", "meta.embedded.block"], + "settings": { + "foreground": "#b4c2f0" + } + }, + { + "name": "Markdown - Markup Raw Inline", + "scope": ["text.html.markdown markup.inline.raw.markdown"], + "settings": { + "foreground": "#c099ff" + } + }, + { + "name": "Markdown - Markup Raw Inline Punctuation", + "scope": [ + "text.html.markdown markup.inline.raw.markdown punctuation.definition.raw.markdown" + ], + "settings": { + "foreground": "#86e1fc" + } + }, + { + "name": "Markdown - Heading punctuation", + "scope": [ + "markdown.heading", + "markup.heading | markup.heading entity.name", + "markup.heading.markdown punctuation.definition.heading.markdown" + ], + "settings": { + "foreground": "#86e1fc" + } + }, + { + "name": "Markup - Italic", + "scope": ["markup.italic"], + "settings": { + "fontStyle": "italic", + "foreground": "#ff757f" + } + }, + { + "name": "Markup - Bold", + "scope": ["markup.bold", "markup.bold string"], + "settings": { + "fontStyle": "bold", + "foreground": "#ff757f" + } + }, + { + "name": "Markup - Bold-Italic", + "scope": [ + "markup.bold markup.italic", + "markup.italic markup.bold", + "markup.quote markup.bold", + "markup.bold markup.italic string", + "markup.italic markup.bold string", + "markup.quote markup.bold string" + ], + "settings": { + "fontStyle": "bold", + "foreground": "#ff757f" + } + }, + { + "name": "Markup - Underline", + "scope": ["markup.underline"], + "settings": { + "fontStyle": "underline", + "foreground": "#ff966c" + } + }, + { + "name": "Markdown - Blockquote", + "scope": ["markup.quote punctuation.definition.blockquote.markdown"], + "settings": { + "foreground": "#86e1fc" + } + }, + { + "name": "Markup - Quote", + "scope": ["markup.quote"], + "settings": { + "fontStyle": "italic" + } + }, + { + "name": "Markdown - Link", + "scope": ["string.other.link.title.markdown"], + "settings": { + "foreground": "#82aaff" + } + }, + { + "name": "Markdown - Link Description", + "scope": ["string.other.link.description.title.markdown"], + "settings": { + "foreground": "#c099ff" + } + }, + { + "name": "Markdown - Link Anchor", + "scope": ["constant.other.reference.link.markdown"], + "settings": { + "foreground": "#ffc777" + } + }, + { + "name": "Markup - Raw Block", + "scope": ["markup.raw.block"], + "settings": { + "foreground": "#c099ff" + } + }, + { + "name": "Markdown - Fenced Bode Block Variable", + "scope": ["markup.fenced_code.block.markdown", "markup.inline.raw.string.markdown"], + "settings": { + "foreground": "#86e1fc" + } + }, + { + "name": "Markdown - Fenced Language", + "scope": ["variable.language.fenced.markdown"], + "settings": { + "foreground": "#86e1fc" + } + }, + { + "name": "Markdown - Separator", + "scope": ["meta.separator"], + "settings": { + "fontStyle": "bold", + "foreground": "#86e1fc" + } + }, + { + "name": "Markup - Table", + "scope": ["markup.table"], + "settings": { + "foreground": "#828bb8" + } + }, + { + "scope": "token.info-token", + "settings": { + "foreground": "#65bcff" + } + }, + { + "scope": "token.warn-token", + "settings": { + "foreground": "#ffc777" + } + }, + { + "scope": "token.error-token", + "settings": { + "foreground": "#ff757f" + } + }, + { + "scope": "token.debug-token", + "settings": { + "foreground": "#c099ff" + } + } + ] +} diff --git a/packages/docs/src/lib/types.ts b/packages/docs/src/lib/types.ts new file mode 100644 index 00000000..90b1bd43 --- /dev/null +++ b/packages/docs/src/lib/types.ts @@ -0,0 +1,10 @@ +// Global Docs Types + +// Table Component +export interface TableData { + property: string; + description: string; + type?: string; + default?: string; + required?: boolean; +} diff --git a/packages/docs/src/routes/(inner)/+layout.svelte b/packages/docs/src/routes/(inner)/+layout.svelte new file mode 100644 index 00000000..7121e5a8 --- /dev/null +++ b/packages/docs/src/routes/(inner)/+layout.svelte @@ -0,0 +1,32 @@ + + + +
+ + + +
+ + + +
+ {@render children()} +
+ + +
+ + +
diff --git a/packages/docs/src/routes/(inner)/api/floating-arrow/+page.svelte b/packages/docs/src/routes/(inner)/api/floating-arrow/+page.svelte new file mode 100644 index 00000000..8eb32104 --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/floating-arrow/+page.svelte @@ -0,0 +1,82 @@ + + +
+ +
+

FloatingArrow

+

+ Renders a customizable {''} pointing arrow triangle inside the floating + element that gets automatically positioned. +

+ +
+ +
+

Usage

+ + + + + +
+
Floating
+ +
+ `} + /> +
+ +
+

Props

+ + + +
+

Utility Classes and Styles

+

Provide arbitrary utility classes using the standard attribute.

+ `} /> +
+ +
+

Compare

+ +

+ Compare to Floating UI React. +

+
+ diff --git a/packages/docs/src/routes/(inner)/api/floating-arrow/data.ts b/packages/docs/src/routes/(inner)/api/floating-arrow/data.ts new file mode 100644 index 00000000..a3f4ade1 --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/floating-arrow/data.ts @@ -0,0 +1,67 @@ +// Component: FloatingArrow + +import type { TableData } from '$lib/types.js'; + +// Props +export const tableProps: TableData[] = [ + { + property: `ref*`, + description: `Bound element reference.`, + type: `HTMLElement | null`, + default: `-`, + }, + { + property: `context*`, + description: `The context object returned from useFloating().`, + type: `FloatingContext`, + default: `-`, + }, + { + property: `width`, + description: `The width of the arrow.`, + type: `number`, + default: `14`, + }, + { + property: `height`, + description: `The height of the arrow.`, + type: `number`, + default: `7`, + }, + { + property: `tipRadius`, + description: `The radius (rounding) of the arrow tip.`, + type: `number`, + default: `0 (sharp)`, + }, + { + property: `staticOffset`, + description: `A static offset override of the arrow from the floating element edge. Often desirable if the floating element is smaller than the reference element along the relevant axis and has an edge alignment (start/end).`, + type: `string | number | null`, + default: `undefined (use dynamic path)`, + }, + { + property: `d`, + description: `A custom path for the arrow. Useful if you want fancy rounding. The path should be inside a square SVG and placed at the bottom of it. The path is designed for the 'bottom' placement, which will be rotated for other placements.`, + type: `string`, + default: `"black" (browser default)`, + }, + { + property: `fill`, + description: `The color of the arrow.`, + type: `string`, + default: `xxx`, + }, + { + property: `stroke`, + description: `The stroke (border) color of the arrow. This must match (or be less than) the floating element’s border width.`, + type: `string`, + default: `"none"`, + }, + { + property: `strokeWidth`, + description: `The stroke (border) width of the arrow.`, + type: `number`, + default: `0`, + }, +]; diff --git a/packages/docs/src/routes/(inner)/api/use-click/+page.svelte b/packages/docs/src/routes/(inner)/api/use-click/+page.svelte new file mode 100644 index 00000000..c5ab613f --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-click/+page.svelte @@ -0,0 +1,33 @@ + + +
+ +
+

useClick

+

Opens or closes the floating element when clicking the reference element.

+ +
+ +
+

Usage

+ +
+ +
+

Options

+
+ + +
+

Compare

+ +

+ Compare to Floating UI React. +

+
+ diff --git a/packages/docs/src/routes/(inner)/api/use-click/Example.svelte b/packages/docs/src/routes/(inner)/api/use-click/Example.svelte new file mode 100644 index 00000000..5cf0dfb5 --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-click/Example.svelte @@ -0,0 +1,21 @@ + + + + + + +
+ Floating +
diff --git a/packages/docs/src/routes/(inner)/api/use-click/data.ts b/packages/docs/src/routes/(inner)/api/use-click/data.ts new file mode 100644 index 00000000..330a807e --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-click/data.ts @@ -0,0 +1,38 @@ +import type { TableData } from '$lib/types.js'; + +// Options +export const tableOptions: TableData[] = [ + { + property: 'enabled', + description: 'Whether the Hook is enabled, including all internal Effects and event handlers.', + type: 'boolean', + default: 'true', + }, + { + property: 'event', + description: + 'The type of event to use to determine a "click" with mouse input. Keyboard clicks work as normal.', + type: '"click" | "mousedown"', + default: "'click'", + }, + { + property: 'toggle', + description: 'Whether to toggle the open state with repeated clicks.', + type: 'boolean', + default: 'true', + }, + { + property: 'ignoreMouse', + description: + 'Whether to ignore the logic for mouse input (for example, if `useHover()` is also being used). When `useHover()` and `useClick()` are used together, clicking the reference element after hovering it will keep the floating element open even once the cursor leaves. This may not be desirable in some cases.', + type: 'boolean', + default: 'false', + }, + { + property: 'keyboardHandlers', + description: + 'Whether to add keyboard handlers (Enter and Space key functionality) for non-button elements (to open/close the floating element via keyboard "click").', + type: 'boolean', + default: 'true', + }, +]; diff --git a/packages/docs/src/routes/(inner)/api/use-dismiss/+page.svelte b/packages/docs/src/routes/(inner)/api/use-dismiss/+page.svelte new file mode 100644 index 00000000..2c100f44 --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-dismiss/+page.svelte @@ -0,0 +1,67 @@ + + +
+ +
+

useDismiss

+

+ Closes the floating element when a dismissal is requested — by default, when the user presses + the escape key or outside of the floating element with their pointer. +

+ +
+ +
+

Usage

+ +
+ +
+

Options

+
+ + +
+

Reacting to dismissal

+

+ To react to the dismissal event, you can check for the reason string in + the onOpenChange callback: +

+ { + open = value; + if (reason === 'escape-key' || reason === 'outside-press') { + console.log('dismissed'); + } + }, +}); + `} + /> +
+ + + + +
+

Compare

+ +

+ Compare to Floating UI React. +

+
+ diff --git a/packages/docs/src/routes/(inner)/api/use-dismiss/Example.svelte b/packages/docs/src/routes/(inner)/api/use-dismiss/Example.svelte new file mode 100644 index 00000000..bad8c628 --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-dismiss/Example.svelte @@ -0,0 +1,21 @@ + + + + + + +
+ Floating +
diff --git a/packages/docs/src/routes/(inner)/api/use-dismiss/data.ts b/packages/docs/src/routes/(inner)/api/use-dismiss/data.ts new file mode 100644 index 00000000..3baf2a1b --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-dismiss/data.ts @@ -0,0 +1,61 @@ +// Hook: useDismiss + +import type { TableData } from '$lib/types.js'; + +// Options +export const tableOptions: TableData[] = [ + { + property: `enabled`, + description: `Whether the Hook is enabled, including all internal Effects and event handlers.`, + type: `boolean`, + default: `true`, + }, + { + property: `escapeKey`, + description: `Whether to dismiss the floating element upon pressing the \`esc\` key.`, + type: `boolean`, + default: `true`, + }, + { + property: `referencePress`, + description: `Whether to dismiss the floating element upon pressing the reference element. You likely want to ensure the \`move\` option in the \`useHover()\` Hook has been disabled when this is in use.`, + type: `boolean`, + default: `false`, + }, + { + property: `referencePressEvent`, + description: `The type of event to use to determine a “press”.`, + type: `'pointerdown' | 'mousedown' | 'click'`, + default: `'pointerdown'`, + }, + { + property: `outsidePress`, + description: `Whether to dismiss the floating element upon pressing outside of the floating element.`, + type: `boolean | ((event: MouseEvent) => boolean)`, + default: `true`, + }, + { + property: `outsidePressEvent`, + description: `The type of event to use to determine an outside “press”.`, + type: `'pointerdown' | 'mousedown' | 'click'`, + default: `'pointerdown'`, + }, + { + property: `ancestorScroll`, + description: `Whether to dismiss the floating element upon scrolling an overflow ancestor.`, + type: `boolean`, + default: `false`, + }, + { + property: `bubbles`, + description: `Determines whether event listeners bubble upwards through a tree of floating elements.`, + type: `boolean | { escapeKey?: boolean; outsidePress?: boolean }`, + default: `undefined`, + }, + { + property: `capture`, + description: `Determines whether to use capture phase event listeners.`, + type: `boolean | { escapeKey?: boolean; outsidePress?: boolean }`, + default: `undefined`, + }, +]; diff --git a/packages/docs/src/routes/(inner)/api/use-floating/+page.svelte b/packages/docs/src/routes/(inner)/api/use-floating/+page.svelte new file mode 100644 index 00000000..f2531daf --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-floating/+page.svelte @@ -0,0 +1,67 @@ + + +
+ +
+

useFloating

+

+ The main Hook of the library that acts as a controller for all other Hooks and components. +

+ +
+ +
+

Usage

+

+ The useFloating Svelte hook acts as a controller for all other Floating + UI Svelte features. It handles positioning your floating elements (tooltips, popovers, etc.) relative + to an anchored element. Automatically calculates the best placement and updates it as needed, providing + access to properties for position and style. +

+ + +\n + +
+ Floating +
+ `} + /> +
+ +
+

Note

+

Destructured variables are not supported as this would break reactivity.

+
+ +
+

Options

+
+ + +
+

Returns

+
+ + +
+

Compare

+ +

+ Compare to Floating UI React. +

+
+ diff --git a/packages/docs/src/routes/(inner)/api/use-floating/data.ts b/packages/docs/src/routes/(inner)/api/use-floating/data.ts new file mode 100644 index 00000000..f95c2a49 --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-floating/data.ts @@ -0,0 +1,107 @@ +// Hook: useFloating + +import type { TableData } from '$lib/types.js'; + +// Options +export const tableOptions: TableData[] = [ + { + property: `open`, + description: `Represents the open/close state of the floating element.`, + type: `boolean`, + default: `true`, + }, + { + property: `onOpenChange`, + description: `Event handler that can be invoked whenever the open state changes.`, + type: `(open: boolean, event?: Event, reason?: OpenChangeReason) => void`, + default: ``, + }, + { + property: `placement`, + description: `Where to place the floating element relative to its reference element.`, + type: `Placement`, + default: `'bottom'`, + }, + { + property: `strategy`, + description: `The type of CSS position property to use.`, + type: `Strategy`, + default: `'absolute'`, + }, + { + property: `middleware`, + description: `Supports all Floating UI middleware`, + type: `Array`, + default: `undefined`, + }, + { + property: `transform`, + description: `Whether to use transform instead of top and left styles to position the floating element.`, + type: `boolean`, + default: `true`, + }, + { + property: `elements`, + description: `The reference and floating elements.`, + type: `FloatingElements`, + default: `{}`, + }, + { + property: `whileElementsMounted`, + description: `Callback to handle mounting/unmounting of the elements.`, + type: `((reference: ReferenceElement, floating: FloatingElement, update: () => void) => () => void) | undefined`, + default: `undefined`, + }, + { + property: 'nodeId', + description: 'A unique node ID for the floating element when using a `FloatingTree`.', + type: 'string | undefined', + default: 'undefined', + }, +]; + +// Returns +export const tableReturns: TableData[] = [ + { property: `x`, description: `The x-coord of the floating element.`, type: `number` }, + { property: `y`, description: `The y-coord of the floating element.`, type: `number` }, + { + property: `placement`, + description: `The stateful placement, which can be different from the initial placement passed as options.`, + type: `Placement`, + }, + { + property: `strategy`, + description: `The stateful strategy, which can be different from the initial strategy passed as options.`, + type: `Strategy`, + }, + { + property: `middlewareData`, + description: `Additional data from middleware.`, + type: `MiddlewareData`, + }, + { + property: `isPositioned`, + description: `The boolean that let you know if the floating element has been positioned.`, + type: `boolean`, + }, + { + property: `floatingStyles`, + description: `CSS styles to apply to the floating element to position it.`, + type: `string`, + }, + { + property: `elements`, + description: `The reference and floating elements.`, + type: `FloatingElements`, + }, + { + property: `update`, + description: `The function to update floating position manually.`, + type: `() => void`, + }, + { + property: `context`, + description: `Context object containing internal logic to alter the behavior of the floating element.`, + type: `FloatingContext`, + }, +]; diff --git a/packages/docs/src/routes/(inner)/api/use-focus/+page.svelte b/packages/docs/src/routes/(inner)/api/use-focus/+page.svelte new file mode 100644 index 00000000..f547eb89 --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-focus/+page.svelte @@ -0,0 +1,44 @@ + + +
+ +
+

useFocus

+

+ Opens the floating element while the reference element has focus, like CSS + :focus. +

+ + + +
+ +
+

Usage

+

+ This Hook returns event handler props. To use it, pass it the context object returned from useFloating(), and then feed its result into the useInteractions() array. The returned + prop getters are then spread onto the elements for rendering. +

+ +
+ +
+

Options

+
+ + +
+

Compare

+ +

+ Compare to Floating UI React. +

+
+ diff --git a/packages/docs/src/routes/(inner)/api/use-focus/Example.svelte b/packages/docs/src/routes/(inner)/api/use-focus/Example.svelte new file mode 100644 index 00000000..3c807ca1 --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-focus/Example.svelte @@ -0,0 +1,21 @@ + + + + + + +
+ Floating +
diff --git a/packages/docs/src/routes/(inner)/api/use-focus/data.ts b/packages/docs/src/routes/(inner)/api/use-focus/data.ts new file mode 100644 index 00000000..dba6297a --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-focus/data.ts @@ -0,0 +1,19 @@ +// Hook: useFocus + +import type { TableData } from '$lib/types.js'; + +// Options +export const tableOptions: TableData[] = [ + { + property: `enabled`, + description: `Conditionally enable/disable the Hook.`, + type: `boolean`, + default: `true`, + }, + { + property: `visibleOnly`, + description: `Whether the open state only changes if the focus event is considered visible (:focus-visible CSS selector).`, + type: `boolean`, + default: `true`, + }, +]; diff --git a/packages/docs/src/routes/(inner)/api/use-hover/+page.svelte b/packages/docs/src/routes/(inner)/api/use-hover/+page.svelte new file mode 100644 index 00000000..15626fb7 --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-hover/+page.svelte @@ -0,0 +1,65 @@ + + +
+ +
+

useHover

+

+ Opens the floating element while hovering over the reference element, like CSS + :hover. +

+ +
+ +
+

Usage

+ + + + + +
+ Tooltip +
+ `} + /> +
+ +
+

Options

+
+ + +
+

Compare

+ +

+ Compare to Floating UI React. +

+
+ diff --git a/packages/docs/src/routes/(inner)/api/use-hover/data.ts b/packages/docs/src/routes/(inner)/api/use-hover/data.ts new file mode 100644 index 00000000..18f3808b --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-hover/data.ts @@ -0,0 +1,43 @@ +// Hook: useHover + +import type { TableData } from '$lib/types.js'; + +// Options +export const tableOptions: TableData[] = [ + { + property: `enabled`, + description: `Enables the hook.`, + type: `boolean`, + default: `true`, + }, + { + property: `mouseOnly`, + description: `Only allow pointers of type mouse to trigger the hover (thus excluding pens and touchscreens).`, + type: `boolean`, + default: `false`, + }, + { + property: `delay`, + description: `Time in ms that will delay the change of the open state. Also accepts an object with open and close properties for finer grained control.`, + type: `number`, + default: `0`, + }, + { + property: `restMs`, + description: `Time in ms that the pointer must rest on the reference element before the open state is set to true.`, + type: `number`, + default: `0`, + }, + { + property: `move`, + description: `Whether moving the pointer over the floating element will open it, without a regular hover event required.`, + type: `boolean`, + default: `true`, + }, + { + property: `handleClose`, + description: `Callback to handle the closing of the floating element.`, + type: `HandleCloseFn`, + default: `null`, + }, +]; diff --git a/packages/docs/src/routes/(inner)/api/use-interactions/+page.svelte b/packages/docs/src/routes/(inner)/api/use-interactions/+page.svelte new file mode 100644 index 00000000..87b7ed3c --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-interactions/+page.svelte @@ -0,0 +1,83 @@ + + +
+ +
+

useInteractions

+

A hook to merge or compose interaction event handlers together.

+ +
+ +
+

Usage

+

+ The useInteractions Svelte hook allows you to consume multiple interactions. + It ensures that event listeners from different hooks are properly registered instead of being overruled + by one another. +

+ + +
+ Reference +
+ + +
+ Floating +
+ `} + /> +

+ When you want to apply an event handler to an element that uses a props getter, make sure to + pass it through the getter instead of applying it directly: +

+ +
Reference
+ + +
Reference
+ `} + /> +

+ This will ensure all event handlers will be registered rather being overruled by each-other. +

+
+ +
+

Returns

+
+ + +
+

Compare

+ +

+ Compare to Floating UI React. +

+
+ diff --git a/packages/docs/src/routes/(inner)/api/use-interactions/data.ts b/packages/docs/src/routes/(inner)/api/use-interactions/data.ts new file mode 100644 index 00000000..ceeacf44 --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-interactions/data.ts @@ -0,0 +1,22 @@ +// Hook: useInteractions + +import type { TableData } from '$lib/types.js'; + +// Returns +export const tableReturns: TableData[] = [ + { + property: `getReferenceProps`, + description: `The merged attributes for the reference element.`, + type: `(userProps?: HTMLAttributes) => Record`, + }, + { + property: `getFloatingProps`, + description: `The merged attributes for the floating element.`, + type: `(userProps?: HTMLAttributes) => Record`, + }, + { + property: `getItemProps`, + description: `The merged attributes for when dealing with a list inside the floating element.`, + type: `(userProps?: HTMLAttributes & ExtendedUserProps) => Record`, + }, +]; diff --git a/packages/docs/src/routes/(inner)/api/use-role/+page.svelte b/packages/docs/src/routes/(inner)/api/use-role/+page.svelte new file mode 100644 index 00000000..b29fc2d3 --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-role/+page.svelte @@ -0,0 +1,70 @@ + + +
+ +
+

useRole

+

+ Adds base screen reader props to the reference and floating elements for a given + role. +

+ +

+ This is useful to automatically apply ARIA props to the reference and floating elements to + ensure they’re accessible to assistive technology, including item elements if narrowly + specified. +

+
+ +
+

Usage

+ + +
+ + +
+ Tooltip +
+ `} + /> + + +
+

Options

+
+ + +
+

Compare

+ +

+ Compare to Floating UI React. +

+
+ diff --git a/packages/docs/src/routes/(inner)/api/use-role/data.ts b/packages/docs/src/routes/(inner)/api/use-role/data.ts new file mode 100644 index 00000000..e2e7e84a --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/use-role/data.ts @@ -0,0 +1,19 @@ +// Hook: useRole + +import type { TableData } from '$lib/types.js'; + +// Options +export const tableOptions: TableData[] = [ + { + property: `enabled`, + description: `Enables the interaction.`, + type: `boolean`, + default: `true`, + }, + { + property: `role`, + description: `The role that the floating element should be.`, + type: `AriaRole | ComponentRole`, + default: `'dialog'`, + }, +]; diff --git a/packages/docs/src/routes/(inner)/api/utilities/+page.svelte b/packages/docs/src/routes/(inner)/api/utilities/+page.svelte new file mode 100644 index 00000000..5eb35045 --- /dev/null +++ b/packages/docs/src/routes/(inner)/api/utilities/+page.svelte @@ -0,0 +1,35 @@ + + +
+ +
+

Utilities

+

Below you'll find a number of useful utilities.

+
+ +
+

useId

+

+ Generates a unique identifier string. This function combines a random string and an + incrementing counter to ensure uniqueness. +

+ +
+ +
+

Compare

+ +

+ Compare to Floating UI React. +

+
+
diff --git a/packages/docs/src/routes/(inner)/docs/getting-started/+page.svelte b/packages/docs/src/routes/(inner)/docs/getting-started/+page.svelte new file mode 100644 index 00000000..27b525f6 --- /dev/null +++ b/packages/docs/src/routes/(inner)/docs/getting-started/+page.svelte @@ -0,0 +1,91 @@ + + +
+ +
+

Getting Started

+

+ Floating UI Svelte is a library that helps you create floating elements such as + tooltips, popovers, dropdowns, and more. +

+
+ +
+

Requirements

+

+ Supports projects created using + Svelte v5 + . +

+
+ +
+

Install

+

+ Install Floating UI Svelte using your package manager of choice. +

+ +
+ +
+

Usage

+

Floating UI Features

+ +

+ Floating UI Svelte exposes all Floating UI middleware, types, etc. You do not need to install @floating-ui/dom seperately. +

+ +

Making elements "float"

+

+ At minimum, the following styles must be applied to ensure floating elements do not disrupt + the flow of the document. This can be handled using a single reusable CSS class. +

+ + Some floating element.
`} /> +

Z-Index Stacking

+

+ Please be aware that Floating UI does not take an opinionated stance on z-index stacking. +

+ + +
+

Caveats

+

Server-Side Rendering (SSR)

+

+ When SSR is enabled and the floating element is visible upon page load it will first be + positioned in the top left of your screen. It will remain until the position is calculated. To + prevent this, you may utilize the isPositioned + prop returned from the + useFloating hook: +

+ +
+ diff --git a/packages/docs/src/routes/(inner)/docs/getting-started/ExampleSsr.svelte b/packages/docs/src/routes/(inner)/docs/getting-started/ExampleSsr.svelte new file mode 100644 index 00000000..2d3d297f --- /dev/null +++ b/packages/docs/src/routes/(inner)/docs/getting-started/ExampleSsr.svelte @@ -0,0 +1,13 @@ + + + +
+ + {#if floating.isPositioned} + Floating + {/if} +
diff --git a/packages/docs/src/routes/(inner)/examples/context-menus/+page.svelte b/packages/docs/src/routes/(inner)/examples/context-menus/+page.svelte new file mode 100644 index 00000000..e9209b6a --- /dev/null +++ b/packages/docs/src/routes/(inner)/examples/context-menus/+page.svelte @@ -0,0 +1,7 @@ +
+ +
+

Context Menus

+

Coming Soon!

+
+
diff --git a/packages/docs/src/routes/(inner)/examples/modals/+page.svelte b/packages/docs/src/routes/(inner)/examples/modals/+page.svelte new file mode 100644 index 00000000..8fc07777 --- /dev/null +++ b/packages/docs/src/routes/(inner)/examples/modals/+page.svelte @@ -0,0 +1,7 @@ +
+ +
+

Modals

+

Coming Soon!

+
+
diff --git a/packages/docs/src/routes/(inner)/examples/popovers/+page.svelte b/packages/docs/src/routes/(inner)/examples/popovers/+page.svelte new file mode 100644 index 00000000..b587b667 --- /dev/null +++ b/packages/docs/src/routes/(inner)/examples/popovers/+page.svelte @@ -0,0 +1,186 @@ + + +
+ +
+

Popovers

+

+ This is a functional Popover that uses a combination of hooks and components, each of which is + described in the sections below. +

+
+ +
+

Essentials

+

An accessible popover component has the following qualities:

+
    +
  • + Dynamic anchor positioning: The popover is positioned next to + its reference element, remaining anchored to it while avoiding collisions. +
  • +
  • + Events: When the reference element is clicked, it toggles the + popover open or closed. +
  • +
  • + Dismissal: When the user presses the + esc key or outside the popover while it is open, it closes. +
  • +
  • + Role: The elements are given relevant role and ARIA + attributes to be accessible to screen readers. +
  • +
  • + Focus management: Focus is managed for non-modal or modal + behavior. +
  • +
+
+ +
+

Example

+ + {#snippet preview()}{/snippet} + {#snippet code()}{/snippet} + +
+ +
+

Open State

+ +

+ open determines whether or not the popover is currently open on the screen. + It is used for conditional rendering. +

+
+

Basic Popover

+ +
+

useFloating Hook

+

+ The useFloating hook provides positioning and context + for our popover. We need to pass it some information: +

+ +
    +
  • + open: The open state from our useState() + Hook above. +
  • +
  • + onOpenChange: A callback function that will be called when the + popover is opened or closed. We’ll use this to update our open state. +
  • +
  • + middleware: Import and pass middleware to the array that ensure + the popover remains on the screen, no matter where it ends up being positioned. +
  • +
  • + whileElementsMounted: Ensure the popover remains anchored to the + reference element by updating the position when necessary, only while both the reference and + floating elements are mounted for performance. +
  • +
+
+ +
+

Interaction Hooks

+

+ The useInteractions hooks returns an object + containing keys of props that enable the popover to be opened, closed, or accessible to screen + readers. Using the + context that was returned from the Hook, call the interaction Hooks. +

+ +
    +
  • + useClick(): adds the ability to toggle the popover open or closed + when the reference element is clicked. +
  • +
  • + useDismiss(): adds the ability to dismiss the popover when the + user presses the esc key or presses outside of the popover. +
  • +
  • + useRole(): adds the correct ARIA attributes for a + dialog to the popover and reference elements. +
  • +
+

+ Finally, useInteractions() merges all of their props into prop getters + which can be used for rendering. +

+
+ +
+

Rendering

+

Now we have all the variables and Hooks set up, we can render out our elements.

+ +\n + +{#if open} +
+

+ You can press the esc key or click outside to + *dismiss* this floating element. +

+ +
+{/if} + `} + /> +
    +
  • + {`{...getReferenceProps()}`} / + {`{...getFloatingProps()}`} + spreads the props from the interaction Hooks onto the relevant elements. They contain props like + onClick, aria-expanded, etc. +
  • + +
  • + COMING SOON: {``} is a component that manages + focus of the popover for non-modal or modal behavior. It should directly wrap the floating element + and only be rendered when the popover is also rendered. +
  • +
+
+ + + + +
+

Modals and Non-Modal Behavior

+
Coming Soon.
+
+ +

Reusable Popover Component

+
Coming Soon.
+
diff --git a/packages/docs/src/routes/(inner)/examples/popovers/Example.svelte b/packages/docs/src/routes/(inner)/examples/popovers/Example.svelte new file mode 100644 index 00000000..75243dbf --- /dev/null +++ b/packages/docs/src/routes/(inner)/examples/popovers/Example.svelte @@ -0,0 +1,65 @@ + + +
+ + + + {#if open} +
+

+ You can press the esc key or click outside to + *dismiss* this floating element. +

+ +
+ {/if} +
diff --git a/packages/docs/src/routes/(inner)/examples/tooltips/+page.svelte b/packages/docs/src/routes/(inner)/examples/tooltips/+page.svelte new file mode 100644 index 00000000..26caedb6 --- /dev/null +++ b/packages/docs/src/routes/(inner)/examples/tooltips/+page.svelte @@ -0,0 +1,167 @@ + + +
+ +
+

Tooltips

+

+ A tooltip is a floating element that displays information related to a button or anchor + element when it receives keyboard focus or the mouse hovers over it. +

+
+ +
+

Essentials

+

An accessible tooltip component has the following qualities:

+
    +
  • + Dynamic anchor positioning: The tooltip is positioned next to + its reference element, and remains anchored to it while avoiding collisions. +
  • +
  • + Events: When the mouse hovers over the reference element, or + when the reference element receives keyboard focus, the tooltip opens. When the mouse + leaves, or the reference is blurred, the tooltip closes. +
  • +
  • + Dismissal: When the user presses the + esc key while the tooltip is open, it closes. +
  • +
  • + Role: The elements are given relevant role and ARIA + attributes to be accessible to screen readers. +
  • +
+
+ +
+

Example

+ + {#snippet preview()}{/snippet} + {#snippet code()}{/snippet} + +
+ +
+

Open State

+ +

+ open determines whether or not the tooltip is currently open on the screen. + It is used for conditional rendering. +

+
+ +
+

useFloating Hook

+

+ The useFloating hook provides positioning and context + for our tooltip. We need to pass it some information: +

+ +
    +
  • + open: The open state from our useState() + Hook above. +
  • +
  • + onOpenChange: A callback function that will be called when the + tooltip is opened or closed. We’ll use this to update our open state. +
  • +
  • + middleware: Import and pass middleware to the array that ensure + the tooltip remains on the screen, no matter where it ends up being positioned. +
  • +
  • + whileElementsMounted: Ensure the tooltip remains anchored to the + reference element by updating the position when necessary, only while both the reference and + floating elements are mounted for performance. +
  • +
+
+ +
+

Interaction Hooks

+

+ The useInteractions hooks returns an object + containing keys of props that enable the tooltip to be opened, closed, or accessible to screen + readers. Using the + context that was returned from the Hook, call the interaction Hooks. +

+ +
    +
  • + useRole(): adds the correct ARIA attributes for a + tooltip to the tooltip and reference elements. +
  • +
  • + useHover(): adds the ability to toggle the tooltip open or closed + when the reference element is hovered over. The move option is set + to false so that + mousemove events are ignored. +
  • +
  • + useDismiss(): adds the ability to dismiss the tooltip when the + user presses the esc key. +
  • + +
  • + COMING SOON: useFocus(): adds the ability to toggle the tooltip + open or closed when the reference element is focused. +
  • +
+
+ +
+

Rendering

+

Now we have all the variables and Hooks set up, we can render out our elements.

+ + + + +{#if open} +
+

+ A floating element is one that floats on top of the UI without disrupting the + flow, like this one! +

+ +
+{/if} + `} + /> +

+ {`{...getReferenceProps()}`} and + {`{...getFloatingProps()}`} spreads the props from the interaction + Hooks onto the relevant elements. They contain props like + onMouseEnter, aria-describedby, etc. +

+
+
diff --git a/packages/docs/src/routes/(inner)/examples/tooltips/Example.svelte b/packages/docs/src/routes/(inner)/examples/tooltips/Example.svelte new file mode 100644 index 00000000..4e260074 --- /dev/null +++ b/packages/docs/src/routes/(inner)/examples/tooltips/Example.svelte @@ -0,0 +1,65 @@ + + +
+ + + + {#if open} +
+

+ A floating element is one that floats on top of the UI without disrupting the + flow, like this one! +

+ +
+ {/if} +
diff --git a/packages/docs/src/routes/+error.svelte b/packages/docs/src/routes/+error.svelte new file mode 100644 index 00000000..3c2d070d --- /dev/null +++ b/packages/docs/src/routes/+error.svelte @@ -0,0 +1,24 @@ + + + + {status} | Floating UI Svelte + + +
+
+ +

+ {status} - {message} +

+

We're sorry, something went wrong.

+
+
diff --git a/packages/docs/src/routes/+layout.svelte b/packages/docs/src/routes/+layout.svelte index d145086c..3817fc4b 100644 --- a/packages/docs/src/routes/+layout.svelte +++ b/packages/docs/src/routes/+layout.svelte @@ -1,6 +1,45 @@ -{@render children()} + + {title} | Floating UI Svelte + + + + + + + + + {@render children()} + diff --git a/packages/docs/src/routes/+layout.ts b/packages/docs/src/routes/+layout.ts new file mode 100644 index 00000000..08cd17c1 --- /dev/null +++ b/packages/docs/src/routes/+layout.ts @@ -0,0 +1,28 @@ +import { getHighlighter } from 'shiki'; +import MoonlightDark from '$lib/themes/moonlight-dark.json'; +import { browser } from '$app/environment'; +import type { Pagefind } from 'vite-plugin-pagefind/types'; + +export async function load() { + const highlighter = await getHighlighter({ + langs: ['svelte', 'html', 'css', 'javascript', 'typescript', 'bash'], + // @ts-expect-error - Shiki theme type is annoyingly strict + themes: [MoonlightDark], + }); + + if (browser) { + // @ts-expect-error - Dynamic import + const pagefind: Pagefind = await import('/pagefind/pagefind.js'); + await pagefind.init(); + return { + highlighter, + pagefind, + }; + } + + return { + highlighter, + }; +} + +export const prerender = true; diff --git a/packages/docs/src/routes/+page.svelte b/packages/docs/src/routes/+page.svelte index cc88df0e..4960b9ba 100644 --- a/packages/docs/src/routes/+page.svelte +++ b/packages/docs/src/routes/+page.svelte @@ -1,2 +1,53 @@ -

Welcome to SvelteKit

-

Visit svelte.dev/docs/kit to read the documentation

+ + +
+ +
+ +
+ +

+ Floating UI Svelte is available in early access. Expect bugs, missing features, and + incomplete documentation. +

+
+
+ +
+ +

Floating UI Svelte

+

+ A Svelte library for position floating elements and handling interaction. Inspired by Floating UI. +

+ +
+ + +
diff --git a/packages/docs/vite.config.ts b/packages/docs/vite.config.ts index 6b9eb5d3..185d3e64 100644 --- a/packages/docs/vite.config.ts +++ b/packages/docs/vite.config.ts @@ -1,6 +1,7 @@ import { sveltekit } from "@sveltejs/kit/vite"; import { defineConfig } from "vite"; +import pagefind from 'vite-plugin-pagefind'; export default defineConfig({ - plugins: [sveltekit()], + plugins: [sveltekit(), pagefind()], }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 393346cf..d65e076f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,6 +36,9 @@ importers: autoprefixer: specifier: ^10.4.20 version: 10.4.20(postcss@8.4.49) + pagefind: + specifier: ^1.3.0 + version: 1.3.0 svelte: specifier: ^5.0.0 version: 5.16.0 @@ -51,6 +54,9 @@ importers: vite: specifier: ^5.4.11 version: 5.4.11(@types/node@22.10.2) + vite-plugin-pagefind: + specifier: ^0.3.0 + version: 0.3.0(vite@5.4.11(@types/node@22.10.2)) packages/floating-ui-svelte: dependencies: @@ -415,6 +421,31 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@pagefind/darwin-arm64@1.3.0': + resolution: {integrity: sha512-365BEGl6ChOsauRjyVpBjXybflXAOvoMROw3TucAROHIcdBvXk9/2AmEvGFU0r75+vdQI4LJdJdpH4Y6Yqaj4A==} + cpu: [arm64] + os: [darwin] + + '@pagefind/darwin-x64@1.3.0': + resolution: {integrity: sha512-zlGHA23uuXmS8z3XxEGmbHpWDxXfPZ47QS06tGUq0HDcZjXjXHeLG+cboOy828QIV5FXsm9MjfkP5e4ZNbOkow==} + cpu: [x64] + os: [darwin] + + '@pagefind/linux-arm64@1.3.0': + resolution: {integrity: sha512-8lsxNAiBRUk72JvetSBXs4WRpYrQrVJXjlRRnOL6UCdBN9Nlsz0t7hWstRk36+JqHpGWOKYiuHLzGYqYAqoOnQ==} + cpu: [arm64] + os: [linux] + + '@pagefind/linux-x64@1.3.0': + resolution: {integrity: sha512-hAvqdPJv7A20Ucb6FQGE6jhjqy+vZ6pf+s2tFMNtMBG+fzcdc91uTw7aP/1Vo5plD0dAOHwdxfkyw0ugal4kcQ==} + cpu: [x64] + os: [linux] + + '@pagefind/windows-x64@1.3.0': + resolution: {integrity: sha512-BR1bIRWOMqkf8IoU576YDhij1Wd/Zf2kX/kCI0b2qzCKC8wcc2GQJaaRMCpzvCCrmliO4vtJ6RITp/AnoYUUmQ==} + cpu: [x64] + os: [win32] + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -790,6 +821,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -1275,6 +1309,10 @@ packages: package-manager-detector@0.2.8: resolution: {integrity: sha512-ts9KSdroZisdvKMWVAVCXiKqnqNfXz4+IbrBG8/BWx/TR5le+jfenvoBuIZ6UWM9nz47W7AbD9qYfAwfWMIwzA==} + pagefind@1.3.0: + resolution: {integrity: sha512-8KPLGT5g9s+olKMRTU9LFekLizkVIu9tes90O1/aigJ0T5LmyPqTzGJrETnSw3meSYg58YH7JTzhTTW/3z6VAw==} + hasBin: true + parse5@7.2.1: resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} @@ -1647,11 +1685,19 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + valibot@0.31.0-rc.4: + resolution: {integrity: sha512-2wKEnWVey4+JBVCrSF8nlITg2gMDqAuBoIplMpc5bIpQaeDR9wnrI/fudBooKlIW1EZpIMlWy8Ku2gtF/1uK9g==} + vite-node@2.1.8: resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true + vite-plugin-pagefind@0.3.0: + resolution: {integrity: sha512-zg8YPFNymy/3nOQB3U35S3cONBfeyoNDY0Hb4S1F2TA/3fV9xCH/ReSnQc857P2c1mBQ8X2NyDM+RJCvESBq9g==} + peerDependencies: + vite: ^6.0.0 + vite@5.4.11: resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} engines: {node: ^18.0.0 || >=20.0.0} @@ -2115,6 +2161,21 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.18.0 + '@pagefind/darwin-arm64@1.3.0': + optional: true + + '@pagefind/darwin-x64@1.3.0': + optional: true + + '@pagefind/linux-arm64@1.3.0': + optional: true + + '@pagefind/linux-x64@1.3.0': + optional: true + + '@pagefind/windows-x64@1.3.0': + optional: true + '@pkgjs/parseargs@0.11.0': optional: true @@ -2470,6 +2531,8 @@ snapshots: color-name@1.1.4: {} + colorette@2.0.20: {} + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -2932,6 +2995,14 @@ snapshots: package-manager-detector@0.2.8: {} + pagefind@1.3.0: + optionalDependencies: + '@pagefind/darwin-arm64': 1.3.0 + '@pagefind/darwin-x64': 1.3.0 + '@pagefind/linux-arm64': 1.3.0 + '@pagefind/linux-x64': 1.3.0 + '@pagefind/windows-x64': 1.3.0 + parse5@7.2.1: dependencies: entities: 4.5.0 @@ -3321,6 +3392,8 @@ snapshots: util-deprecate@1.0.2: {} + valibot@0.31.0-rc.4: {} + vite-node@2.1.8(@types/node@22.10.2): dependencies: cac: 6.7.14 @@ -3339,6 +3412,12 @@ snapshots: - supports-color - terser + vite-plugin-pagefind@0.3.0(vite@5.4.11(@types/node@22.10.2)): + dependencies: + colorette: 2.0.20 + valibot: 0.31.0-rc.4 + vite: 5.4.11(@types/node@22.10.2) + vite@5.4.11(@types/node@22.10.2): dependencies: esbuild: 0.21.5