--- url: 'https://flux-ui.dev/guide/introduction/what-is-flux.md' --- # What is Flux Flux is a Vue component library designed to simplify the creation of beautiful and functional interfaces for Vue applications. With a collection of pre-built components, Flux enables developers to seamlessly integrate these elements into their projects, significantly reducing the time and effort required to develop a polished user interface. One of the primary benefits of using Flux is its ability to maintain design consistency across the entire application. By leveraging these pre-designed components, developers can ensure a cohesive and intuitive user experience throughout the application's pages. Additionally, Flux is highly customizable, allowing developers to tailor components to meet specific requirements. For developers seeking to enhance the quality and efficiency of their Vue application development, Flux is an exceptional choice. Whether you are an experienced developer or just beginning your journey, Flux provides the tools to create visually appealing and functional interfaces that end users will admire. In short, Flux is a practical Vue component library that aids in building top-tier interfaces for Vue applications. Its pre-built, adaptable components ensure a consistent and intuitive user interface, while also streamlining the development process to help teams deliver high-quality applications faster. --- --- url: 'https://flux-ui.dev/guide/introduction/installation/manual.md' --- # Installation To start using Flux in your Vue application, you'll need to add it to your project. This section provides step-by-step instructions on how to install Flux, ensuring you can quickly integrate its components into your development workflow. ## Plain installation ::: tip This is the most recommended way to use Flux. Use this form of installation if you don't need to customize the style of Flux or if you simply need to use the components without the source code. ::: ### Step 1 Open your project's root directory in your terminal and run the following command: ::: code-group ```shell [Bun] bun add @flux-ui/components ``` ```shell [PNPM] pnpm install @flux-ui/components ``` ```shell [Yarn] yarn add @flux-ui/components ``` ```shell [NPM] npm install @flux-ui/components ``` ::: ::: tip Date and calendar components Components such as the [Date picker](../../../components/date-picker) and [Calendar](../../../components/calendar) rely on [luxon](https://moment.github.io/luxon/). Most package managers install it automatically as a peer dependency; add it explicitly with `bun add luxon` if yours does not. ::: ### Step 2 Once the installation is completed, you need to add the following to your `main.ts` file. ```ts [main.ts] import '@flux-ui/components/style.css' ``` ### Step 3 For setting up icons, please refer to [Font Awesome](../font-awesome). ### Step 4 Wrap your application in `` once, at the top level, and import the components you want to use: ```vue [App.vue] ``` ::: tip FluxRoot `` is the mounting point for [tooltips](../../../components/tooltip), [overlays](../../../components/overlay), [slide-overs](../../../components/slide-over), [snackbars](../../../components/attention/snackbar) and the programmatic [`showAlert`](../../../components/attention/alert), [`showConfirm`](../../../components/attention/confirm) and [`showPrompt`](../../../components/attention/prompt). Add it once around your app; without it these features silently render nothing. ::: ## Vite-preset installation ::: tip Only use this form of installation if you need more control of Flux and need the Flux source code injected into your own project. ::: ### Step 1 Open your project's root directory in your terminal and run the following command: ::: code-group ```shell [Bun] bun add @flux-ui/components sass-embedded @basmilius/vite-preset ``` ```shell [PNPM] pnpm install @flux-ui/components sass-embedded @basmilius/vite-preset ``` ```shell [Yarn] yarn add @flux-ui/components sass-embedded @basmilius/vite-preset ``` ```shell [NPM] npm install @flux-ui/components sass-embedded @basmilius/vite-preset ``` ::: ### Step 2 Once the installation is completed, you need to configure your Vite config file to use Flux. ::: tip For more information on the vite-preset package, please refer to [@basmilius/vite-preset](https://github.com/basmilius/packages/tree/main/packages/vite-preset) ::: ```ts [vite.config.ts] import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { flux, preset } from '@basmilius/vite-preset' export default defineConfig({ plugins: [ vue(), preset(), flux() ] }); ``` ### Step 3 For setting up icons, please refer to [Font Awesome](../font-awesome). ### Step 4 Wrap your application in `` once, at the top level, and import the components you want to use: ```vue [App.vue] ``` --- --- url: 'https://flux-ui.dev/guide/introduction/installation/vue-router.md' --- # Vue Router Flux is built to work hand-in-hand with [Vue Router](https://router.vuejs.org). All components that accept a `to` prop (such as `FluxLink`, `FluxPressable`, `FluxPrimaryLinkButton`, `FluxSecondaryLinkButton`, `FluxMenuItem` and `FluxMenuCollapsible`) forward it directly to a ``. The same applies to the menu and navigation components inside `@flux-ui/application`. This guide walks you through installing Vue Router and integrating it with Flux. ## Step 1 Open your project's root directory in your terminal and run the following command: ::: code-group ```shell [Bun] bun add vue-router ``` ```shell [PNPM] pnpm install vue-router ``` ```shell [Yarn] yarn add vue-router ``` ```shell [NPM] npm install vue-router ``` ::: ## Step 2 Create a `router.ts` file in your `src` directory and configure your routes: ```ts [router.ts] import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'; const routes: RouteRecordRaw[] = [ { path: '/', name: 'home', component: () => import('./views/Home.vue') }, { path: '/about', name: 'about', component: () => import('./views/About.vue') } ]; export const router = createRouter({ history: createWebHistory(), routes }); ``` ## Step 3 Register the router in your `main.ts` file: ```ts [main.ts] import { createApp } from 'vue'; import { router } from './router'; import App from './App.vue'; import '@flux-ui/components/style.css'; createApp(App) .use(router) // [!code focus] .mount('#app'); ``` ## Step 4 Add a `` to your root component, wrapped in a single ``. When using `@flux-ui/application`, place the `` inside the content slot of the layout: ```vue [App.vue] ``` ::: tip FluxRoot `` does not include a [``](../../../components/root), so add one at the top yourself. It is the mounting point for tooltips, overlays, slide-overs, snackbars and the programmatic alerts, confirms and prompts; without it those features silently render nothing. ::: ## Linking to routes Every Flux component that accepts a `to` prop hands it off to Vue Router's ``, so you can pass either a path string or a route location object. ```vue [Navigation.vue] ``` ## Animating route transitions Flux ships with a [Route transition](../../../components/transitions/route) that animates entering and leaving views. Wrap your `` in a `` to enable it: ```vue [App.vue] ``` ## Named views `@flux-ui/application` uses [named views](https://router.vuejs.org/guide/essentials/named-views.html) to render a context-specific menu next to each route. Add a `menu` named component to any route record that should expose its own menu: ```ts [router.ts] const routes: RouteRecordRaw[] = [ { path: '/projects/:id', components: { default: () => import('./views/ProjectOverview.vue'), menu: () => import('./views/ProjectMenu.vue') // [!code focus] } } ]; ``` The matched menu components are then rendered through ``, so each level of a nested route tree can contribute its own menu. --- --- url: 'https://flux-ui.dev/guide/introduction/installation/nuxt.md' --- # Nuxt Flux works out of the box with [Nuxt](https://nuxt.com). The components are SSR-safe and gate any browser-only logic behind a runtime check, so you can render Flux on the server and hydrate it on the client without extra configuration. This guide walks you through installing Flux in a Nuxt project. ## Plain installation ::: tip This is the most recommended way to use Flux. Use this form of installation if you don't need to customize the style of Flux or if you simply need to use the components without the source code. ::: ### Step 1 Open your project's root directory in your terminal and run the following command: ::: code-group ```shell [Bun] bun add @flux-ui/components ``` ```shell [PNPM] pnpm install @flux-ui/components ``` ```shell [Yarn] yarn add @flux-ui/components ``` ```shell [NPM] npm install @flux-ui/components ``` ::: ### Step 2 Add the Flux stylesheet to your `nuxt.config.ts`: ```ts [nuxt.config.ts] export default defineNuxtConfig({ css: [ '@flux-ui/components/style.css' // [!code focus] ] }); ``` ### Step 3 Register Font Awesome icons through a client-side Nuxt plugin. Create `plugins/flux.client.ts`: ```ts [plugins/flux.client.ts] import { fluxRegisterIcons } from '@flux-ui/components'; import { faRocket, faUser } from '@fortawesome/pro-regular-svg-icons'; export default defineNuxtPlugin(() => { fluxRegisterIcons([ faRocket, faUser ]); }); ``` For more information about icon usage, please refer to [Font Awesome](../font-awesome). ### Step 4 Use the components in your pages and layouts as you would in any Vue application: ```vue [app.vue] ``` ## Vite-preset installation ::: tip Only use this form of installation if you need more control of Flux and need the Flux source code injected into your own project. ::: ### Step 1 Open your project's root directory in your terminal and run the following command: ::: code-group ```shell [Bun] bun add @flux-ui/components sass-embedded @basmilius/vite-preset ``` ```shell [PNPM] pnpm install @flux-ui/components sass-embedded @basmilius/vite-preset ``` ```shell [Yarn] yarn add @flux-ui/components sass-embedded @basmilius/vite-preset ``` ```shell [NPM] npm install @flux-ui/components sass-embedded @basmilius/vite-preset ``` ::: ### Step 2 Configure the Vite plugins through Nuxt's `vite` option: ::: tip For more information on the vite-preset package, please refer to [@basmilius/vite-preset](https://github.com/basmilius/packages/tree/main/packages/vite-preset). ::: ```ts [nuxt.config.ts] import { flux, preset } from '@basmilius/vite-preset'; export default defineNuxtConfig({ css: [ '@flux-ui/components/style.css' ], vite: { plugins: [ preset(), flux() ] } }); ``` ### Step 3 For setting up icons, follow step 3 of the plain installation. ### Step 4 Import the components you want to use as shown in step 4 of the plain installation. ## Nuxt-specific notes ### Auto-imports Nuxt does not auto-import components from external packages by default. Either import them explicitly in each ` ``` --- --- url: 'https://flux-ui.dev/guide/introduction/translations.md' --- # Translations Flux uses a set of built-in strings throughout its components, all of which can be translated. Flux integrates with [vue-i18n](https://vue-i18n.intlify.dev/){target="\_blank"} and uses its translate function, so you can localize these strings alongside the rest of your application. ## Strings ## Pre-translated strings Here are the official translations for the strings used by Flux. If you have additional translations, feel free to contribute by creating a pull request on GitHub. :) ### English ::: code-group ```yaml [en.yaml] flux: back: "Back" cancel: "Cancel" close: "Close" collapseGroup: "Collapse group" collapseRow: "Collapse row" expandGroup: "Expand group" expandRow: "Expand row" comingSoon: "Coming soon" continue: "Continue" createOption: 'Create "{value}"' customPeriod: "Custom period" delete: "Delete" done: "Done" filter: "Filter" filterRemove: "Remove filter" filterReset: "Reset filters" justNow: "Just now" max: "Max" min: "Min" nSelected: "{n} selected" ok: "Ok" optional: "Optional" preview: "Preview" previewClose: "Close preview" displayingOf: "{from}–{to} of {total}" showN: "Show {n}" skip: "Skip" next: "Next" noItems: "There are no items (left)." pagination: "Pagination" paginationNavigateTitle: "Navigate" paginationNavigateMessage: "Please provide the desired page number you wish to navigate to." paginationNavigatePage: "Page" previous: "Previous" search: "Search..." sort: "Sort" sortAscending: "Ascending" sortDescending: "Descending" sortRemove: "Remove sorting" submenu: "Submenu" today: "Today" selectMonth: "Select month" selectYear: "Select year" selectDate: "Select date" previousMonth: "Previous month" nextMonth: "Next month" previousYears: "Previous years" nextYears: "Next years" allDay: "All day" andNMore: "{n} more" grabbedAnnounce: "Item grabbed. Use arrow keys to move, Enter to drop, Escape to cancel." releasedAnnounce: "Item released." goToPage: "Go to page {page}" pinDigit: "Digit {index} of {total}" dropFilesOrClick: "Drop files here or click to upload" colorSaturationBrightness: "Color saturation and brightness" customColor: "Custom color" hue: "Hue" opacity: "Opacity" lowerBound: "Lower bound" upperBound: "Upper bound" galleryPlaceholderButton: "Pick image" galleryPlaceholderMessage: "Drop an image here or click the button to upload..." galleryPlaceholderTitle: "Gallery" timezoneEurope: "Europe" timezoneAmerica: "America" timezoneUs: "United States" timezoneAustralia: "Australia" timezoneCanada: "Canada" timezoneMexico: "Mexico" timezoneAfrica: "Africa" timezoneAntarctica: "Antarctica" timezoneArctic: "Arctic" timezoneAsia: "Asia" timezoneAtlantic: "Atlantic" timezoneBrazil: "Brazil" timezoneChile: "Chile" timezoneEtc: "ETC" timezoneOther: "Other" timezoneIndian: "Indian" timezonePacific: "Pacific" ``` ```json [en.json] { "flux": { "back": "Back", "cancel": "Cancel", "close": "Close", "collapseGroup": "Collapse group", "collapseRow": "Collapse row", "expandGroup": "Expand group", "expandRow": "Expand row", "comingSoon": "Coming soon", "continue": "Continue", "createOption": "Create \"{value}\"", "customPeriod": "Custom period", "delete": "Delete", "done": "Done", "filter": "Filter", "filterRemove": "Remove filter", "filterReset": "Reset filters", "justNow": "Just now", "max": "Max", "min": "Min", "nSelected": "{n} selected", "ok": "Ok", "optional": "Optional", "preview": "Preview", "previewClose": "Close preview", "displayingOf": "{from}–{to} of {total}", "showN": "Show {n}", "skip": "Skip", "next": "Next", "noItems": "There are no items (left).", "pagination": "Pagination", "paginationNavigateTitle": "Navigate", "paginationNavigateMessage": "Please provide the desired page number you wish to navigate to.", "paginationNavigatePage": "Page", "previous": "Previous", "search": "Search...", "sort": "Sort", "sortAscending": "Ascending", "sortDescending": "Descending", "sortRemove": "Remove sorting", "submenu": "Submenu", "today": "Today", "selectMonth": "Select month", "selectYear": "Select year", "selectDate": "Select date", "previousMonth": "Previous month", "nextMonth": "Next month", "previousYears": "Previous years", "nextYears": "Next years", "allDay": "All day", "andNMore": "{n} more", "grabbedAnnounce": "Item grabbed. Use arrow keys to move, Enter to drop, Escape to cancel.", "releasedAnnounce": "Item released.", "goToPage": "Go to page {page}", "pinDigit": "Digit {index} of {total}", "dropFilesOrClick": "Drop files here or click to upload", "colorSaturationBrightness": "Color saturation and brightness", "customColor": "Custom color", "hue": "Hue", "opacity": "Opacity", "lowerBound": "Lower bound", "upperBound": "Upper bound", "galleryPlaceholderButton": "Pick image", "galleryPlaceholderMessage": "Drop an image here or click the button to upload...", "galleryPlaceholderTitle": "Gallery", "timezoneEurope": "Europe", "timezoneAmerica": "America", "timezoneUs": "United States", "timezoneAustralia": "Australia", "timezoneCanada": "Canada", "timezoneMexico": "Mexico", "timezoneAfrica": "Africa", "timezoneAntarctica": "Antarctica", "timezoneArctic": "Arctic", "timezoneAsia": "Asia", "timezoneAtlantic": "Atlantic", "timezoneBrazil": "Brazil", "timezoneChile": "Chile", "timezoneEtc": "ETC", "timezoneOther": "Other", "timezoneIndian": "Indian", "timezonePacific": "Pacific" } } ``` ::: ### Dutch - Nederlands ::: code-group ```yaml [nl.yaml] flux: back: "Terug" cancel: "Annuleren" close: "Sluiten" collapseGroup: "Groep inklappen" collapseRow: "Rij inklappen" expandGroup: "Groep uitklappen" expandRow: "Rij uitklappen" comingSoon: "Binnenkort" continue: "Verder" createOption: 'Maak "{value}" aan' customPeriod: "Aangepaste periode" delete: "Verwijderen" done: "Klaar" filter: "Filter" filterRemove: "Verwijder filter" filterReset: "Verwijder alle filters" justNow: "Zojuist" max: "Maximaal" min: "Minimaal" nSelected: "{n} geselecteerd" ok: "Oké" optional: "Optioneel" preview: "Voorbeeld" previewClose: "Voorbeeld sluiten" displayingOf: "{from}–{to} van {total}" showN: "Toon {n}" skip: "Overslaan" next: "Volgende" noItems: "Geen resultaten gevonden" pagination: "Paginatie" paginationNavigateTitle: "Navigeer" paginationNavigateMessage: "Naar welke pagina wil je toe navigeren?" paginationNavigatePage: "Pagina" previous: "Vorige" search: "Zoeken..." sort: "Sorteer" sortAscending: "Oplopend" sortDescending: "Aflopend" sortRemove: "Verwijder" submenu: "Submenu" today: "Vandaag" selectMonth: "Selecteer maand" selectYear: "Selecteer jaar" selectDate: "Selecteer datum" previousMonth: "Vorige maand" nextMonth: "Volgende maand" previousYears: "Vorige jaren" nextYears: "Volgende jaren" allDay: "Hele dag" andNMore: "nog {n}" grabbedAnnounce: "Item vastgepakt. Gebruik de pijltjestoetsen om te verplaatsen, Enter om los te laten, Escape om te annuleren." releasedAnnounce: "Item losgelaten." goToPage: "Ga naar pagina {page}" pinDigit: "Cijfer {index} van {total}" dropFilesOrClick: "Sleep bestanden hierheen of klik om te uploaden" colorSaturationBrightness: "Kleurverzadiging en helderheid" customColor: "Aangepaste kleur" hue: "Tint" opacity: "Dekking" lowerBound: "Ondergrens" upperBound: "Bovengrens" galleryPlaceholderButton: "Selecteer afbeeldingen" galleryPlaceholderMessage: "Laat hier afbeeldingen vallen om ze te uploaden of klik op de knop om te selecteren." galleryPlaceholderTitle: "Afbeeldingen" timezoneEurope: "Europa" timezoneAmerica: "Amerika" timezoneUs: "Verenigde Staten" timezoneAustralia: "Australië" timezoneCanada: "Canada" timezoneMexico: "Mexico" timezoneAfrica: "Afrika" timezoneAntarctica: "Antarctica" timezoneArctic: "Arctisch" timezoneAsia: "Azië" timezoneAtlantic: "Atlantisch" timezoneBrazil: "Brazilië" timezoneChile: "Chili" timezoneEtc: "ETC" timezoneOther: "Overig" timezoneIndian: "Indisch" timezonePacific: "Pacifisch" ``` ```json [nl.json] { "flux": { "back": "Terug", "cancel": "Annuleren", "close": "Sluiten", "collapseGroup": "Groep inklappen", "collapseRow": "Rij inklappen", "expandGroup": "Groep uitklappen", "expandRow": "Rij uitklappen", "comingSoon": "Binnenkort", "continue": "Verder", "createOption": "Maak \"{value}\" aan", "customPeriod": "Aangepaste periode", "delete": "Verwijderen", "done": "Klaar", "filter": "Filter", "filterRemove": "Verwijder filter", "filterReset": "Verwijder alle filters", "justNow": "Zojuist", "max": "Maximaal", "min": "Minimaal", "nSelected": "{n} geselecteerd", "ok": "Oké", "optional": "Optioneel", "preview": "Voorbeeld", "previewClose": "Voorbeeld sluiten", "displayingOf": "{from}–{to} van {total}", "showN": "Toon {n}", "skip": "Overslaan", "next": "Volgende", "noItems": "Geen resultaten gevonden", "pagination": "Paginatie", "paginationNavigateTitle": "Navigeer", "paginationNavigateMessage": "Naar welke pagina wil je toe navigeren?", "paginationNavigatePage": "Pagina", "previous": "Vorige", "search": "Zoeken...", "sort": "Sorteer", "sortAscending": "Oplopend", "sortDescending": "Aflopend", "sortRemove": "Verwijder", "submenu": "Submenu", "today": "Vandaag", "selectMonth": "Selecteer maand", "selectYear": "Selecteer jaar", "selectDate": "Selecteer datum", "previousMonth": "Vorige maand", "nextMonth": "Volgende maand", "previousYears": "Vorige jaren", "nextYears": "Volgende jaren", "allDay": "Hele dag", "andNMore": "nog {n}", "grabbedAnnounce": "Item vastgepakt. Gebruik de pijltjestoetsen om te verplaatsen, Enter om los te laten, Escape om te annuleren.", "releasedAnnounce": "Item losgelaten.", "goToPage": "Ga naar pagina {page}", "pinDigit": "Cijfer {index} van {total}", "dropFilesOrClick": "Sleep bestanden hierheen of klik om te uploaden", "colorSaturationBrightness": "Kleurverzadiging en helderheid", "customColor": "Aangepaste kleur", "hue": "Tint", "opacity": "Dekking", "lowerBound": "Ondergrens", "upperBound": "Bovengrens", "galleryPlaceholderButton": "Selecteer afbeeldingen", "galleryPlaceholderMessage": "Laat hier afbeeldingen vallen om ze te uploaden of klik op de knop om te selecteren.", "galleryPlaceholderTitle": "Afbeeldingen", "timezoneEurope": "Europa", "timezoneAmerica": "Amerika", "timezoneUs": "Verenigde Staten", "timezoneAustralia": "Australië", "timezoneCanada": "Canada", "timezoneMexico": "Mexico", "timezoneAfrica": "Afrika", "timezoneAntarctica": "Antarctica", "timezoneArctic": "Arctisch", "timezoneAsia": "Azië", "timezoneAtlantic": "Atlantisch", "timezoneBrazil": "Brazilië", "timezoneChile": "Chili", "timezoneEtc": "ETC", "timezoneOther": "Overig", "timezoneIndian": "Indisch", "timezonePacific": "Pacifisch" } } ``` ::: ### French - Français ::: code-group ```yaml [fr.yaml] flux: back: "Retour" cancel: "Annuler" close: "Fermer" collapseGroup: "Réduire le groupe" collapseRow: "Réduire la ligne" expandGroup: "Développer le groupe" expandRow: "Développer la ligne" comingSoon: "Bientôt disponible" continue: "Continuer" createOption: 'Créer "{value}"' customPeriod: "Période personnalisée" delete: "Supprimer" done: "Terminé" filter: "Filtrer" filterRemove: "Supprimer le filtre" filterReset: "Réinitialiser les filtres" justNow: "À l'instant" max: "Max" min: "Min" nSelected: "{n} sélectionné(s)" ok: "OK" optional: "Optionnel" preview: "Aperçu" previewClose: "Fermer l'aperçu" displayingOf: "{from}–{to} sur {total}" showN: "Afficher {n}" skip: "Passer" next: "Suivant" noItems: "Aucun élément disponible." pagination: "Pagination" paginationNavigateTitle: "Naviguer" paginationNavigateMessage: "Veuillez indiquer le numéro de page souhaité." paginationNavigatePage: "Page" previous: "Précédent" search: "Recherche..." sort: "Trier" sortAscending: "Ascendant" sortDescending: "Descendant" sortRemove: "Supprimer le tri" submenu: "Sous-menu" today: "Aujourd'hui" selectMonth: "Sélectionner le mois" selectYear: "Sélectionner l'année" selectDate: "Sélectionner la date" previousMonth: "Mois précédent" nextMonth: "Mois suivant" previousYears: "Années précédentes" nextYears: "Années suivantes" allDay: "Toute la journée" andNMore: "{n} de plus" grabbedAnnounce: "Élément saisi. Utilisez les touches fléchées pour déplacer, Entrée pour déposer, Échap pour annuler." releasedAnnounce: "Élément relâché." goToPage: "Aller à la page {page}" pinDigit: "Chiffre {index} sur {total}" dropFilesOrClick: "Déposez des fichiers ici ou cliquez pour téléverser" colorSaturationBrightness: "Saturation et luminosité de la couleur" customColor: "Couleur personnalisée" hue: "Teinte" opacity: "Opacité" lowerBound: "Borne inférieure" upperBound: "Borne supérieure" galleryPlaceholderButton: "Choisir une image" galleryPlaceholderMessage: "Déposez une image ici ou cliquez sur le bouton pour télécharger..." galleryPlaceholderTitle: "Galerie" timezoneEurope: "Europe" timezoneAmerica: "Amérique" timezoneUs: "États-Unis" timezoneAustralia: "Australie" timezoneCanada: "Canada" timezoneMexico: "Mexique" timezoneAfrica: "Afrique" timezoneAntarctica: "Antarctique" timezoneArctic: "Arctique" timezoneAsia: "Asie" timezoneAtlantic: "Atlantique" timezoneBrazil: "Brésil" timezoneChile: "Chili" timezoneEtc: "ETC" timezoneOther: "Autre" timezoneIndian: "Indien" timezonePacific: "Pacifique" ``` ```json [fr.json] { "flux": { "back": "Retour", "cancel": "Annuler", "close": "Fermer", "collapseGroup": "Réduire le groupe", "collapseRow": "Réduire la ligne", "expandGroup": "Développer le groupe", "expandRow": "Développer la ligne", "comingSoon": "Bientôt disponible", "continue": "Continuer", "createOption": "Créer \"{value}\"", "customPeriod": "Période personnalisée", "delete": "Supprimer", "done": "Terminé", "filter": "Filtrer", "filterRemove": "Supprimer le filtre", "filterReset": "Réinitialiser les filtres", "justNow": "À l'instant", "max": "Max", "min": "Min", "nSelected": "{n} sélectionné(s)", "ok": "OK", "optional": "Optionnel", "preview": "Aperçu", "previewClose": "Fermer l'aperçu", "displayingOf": "{from}–{to} sur {total}", "showN": "Afficher {n}", "skip": "Passer", "next": "Suivant", "noItems": "Aucun élément disponible.", "pagination": "Pagination", "paginationNavigateTitle": "Naviguer", "paginationNavigateMessage": "Veuillez indiquer le numéro de page souhaité.", "paginationNavigatePage": "Page", "previous": "Précédent", "search": "Recherche...", "sort": "Trier", "sortAscending": "Ascendant", "sortDescending": "Descendant", "sortRemove": "Supprimer le tri", "submenu": "Sous-menu", "today": "Aujourd'hui", "selectMonth": "Sélectionner le mois", "selectYear": "Sélectionner l'année", "selectDate": "Sélectionner la date", "previousMonth": "Mois précédent", "nextMonth": "Mois suivant", "previousYears": "Années précédentes", "nextYears": "Années suivantes", "allDay": "Toute la journée", "andNMore": "{n} de plus", "grabbedAnnounce": "Élément saisi. Utilisez les touches fléchées pour déplacer, Entrée pour déposer, Échap pour annuler.", "releasedAnnounce": "Élément relâché.", "goToPage": "Aller à la page {page}", "pinDigit": "Chiffre {index} sur {total}", "dropFilesOrClick": "Déposez des fichiers ici ou cliquez pour téléverser", "colorSaturationBrightness": "Saturation et luminosité de la couleur", "customColor": "Couleur personnalisée", "hue": "Teinte", "opacity": "Opacité", "lowerBound": "Borne inférieure", "upperBound": "Borne supérieure", "galleryPlaceholderButton": "Choisir une image", "galleryPlaceholderMessage": "Déposez une image ici ou cliquez sur le bouton pour télécharger...", "galleryPlaceholderTitle": "Galerie", "timezoneEurope": "Europe", "timezoneAmerica": "Amérique", "timezoneUs": "États-Unis", "timezoneAustralia": "Australie", "timezoneCanada": "Canada", "timezoneMexico": "Mexique", "timezoneAfrica": "Afrique", "timezoneAntarctica": "Antarctique", "timezoneArctic": "Arctique", "timezoneAsia": "Asie", "timezoneAtlantic": "Atlantique", "timezoneBrazil": "Brésil", "timezoneChile": "Chili", "timezoneEtc": "ETC", "timezoneOther": "Autre", "timezoneIndian": "Indien", "timezonePacific": "Pacifique" } } ``` ::: --- --- url: 'https://flux-ui.dev/guide/introduction/colors.md' --- # Colors Flux ships a color palette of six colors: **gray**, **primary**, **danger**, **info**, **success**, and **warning**. Each color is available in 12 shades, from 25 to 950, so you can make fine-grained design choices. ## Gray ## Primary ## Danger ## Info ## Success ## Warning --- --- url: 'https://flux-ui.dev/guide/introduction/design-tokens.md' --- # Design tokens Flux exposes its visual language as CSS custom properties. Use them to theme your application, build new components that fit in seamlessly, or override individual values for a single element. All tokens are defined on `:root` and adjust automatically when [Dark mode](./dark-mode) is active. For the color palette tokens (`--gray-*`, `--primary-*`, `--danger-*`, `--info-*`, `--success-*`, `--warning-*`) see [Colors](./colors). ## Surface Semantic tokens for backgrounds, borders and disabled states. These are the tokens you should reach for first when styling new UI. They automatically follow the active theme. ## Foreground Tokens for text and iconography. ## Overlay Used by `FluxOverlay`, `FluxSlideOver`, `FluxFlyout` and other dialog-like components. Dark mode uses solid black with alpha to keep dimming effects readable. ## Shadow A scale of seven shadow levels. Each level uses a slightly different opacity in dark mode so elevations remain visible against the darker surface. ## Radius ## Typography ### Text scale Every size is paired with a line-height, and the two are always set together. The pairing is what keeps line boxes on the 3px grid: a font-size on its own would derive its line box from a ratio and land on fractional pixels. Headings sit outside this scale and carry their own pair: `h1` is 27/42, `h2` is 21/33. The remaining levels line up with the scale, so `h3` is `xlarge`, `h4` is `large`, `h5` is `default` and `h6` is `small`. ::: tip Changing the base size `--font-size-default` also sets the root font-size, so it is the basis for every `rem` in your own code. Override it on `:root` to rescale the interface, and override `--line-height-default` along with it to keep the rhythm on the grid. ::: ## Motion The motion tokens drive every Flux transition. Use them when you build custom animations so timings stay consistent with the rest of the system. ## Overriding tokens All tokens are regular CSS custom properties, so you can override them at any level: globally, on a single component, or even inline. ```scss :root { --radius: 8px; /* Square off the entire UI. */ --primary-600: #0070f3; /* Replace the primary accent. */ } .my-card { --surface: var(--primary-50); --surface-stroke: var(--primary-200); } ``` Because semantic tokens reference palette tokens (e.g. `--surface: var(--gray-25)`), changing a single palette token cascades through every component that uses it. --- --- url: 'https://flux-ui.dev/guide/introduction/typography.md' --- # Typography Flux ships a consistent typographic system covering font families, sizes, weights, and spacing. This page documents how typography works in Flux and how to apply it to text throughout your application. Outside of any container, Flux applies only light element defaults: heading sizes and weights, link styling and a monospace font for code. Rich prose, with vertical rhythm, decorated blockquotes, list markers and styled tables, lives inside the [Prose](/components/prose) component. Every example below is wrapped in `FluxProse`. ::: tip Flux uses the [Inter Variable](https://rsms.me/inter/) font family by default, you will need to include the font in your application for it to work. ::: ## The text scale Text comes in six steps, and each step pairs a font-size with a line-height. Always set the two together: a font-size on its own derives its line box from a ratio, which lands on fractional pixels at every size except the default and drifts off the 3px grid. ```css .my-label { font-size: var(--font-size-small); line-height: var(--line-height-small); } ``` Pick a step by role rather than by measuring the design: * **2xsmall** (12/18) for fine print, such as meta rows and counters. * **xsmall** (13/18) for compact labels that sit inline in body text, like a badge. * **small** (14/21) for interface text: tables, menus, tooltips. * **default** (15/24) for body text. This is inherited, so you rarely set it. * **large** (16/24) for a prominent single line, such as a pane caption. * **xlarge** (18/27) for titles that sit below heading level. Deviate from a pair only when an element has to line up with a line box it does not own. A checkbox label is the canonical case: the box is 21px, so its label takes `default` at a 21px line-height instead of its own 24px, or the two stop aligning. Anything with a fixed height should set its own step rather than inherit one. A button is 42px tall whatever you put around it, so its label stays 15px even inside a 14px table cell. Text that should adapt to its surroundings, such as a badge sitting inline in a sentence, is the exception that inherits. See [Design tokens](/guide/introduction/design-tokens#text-scale) for the full table. ## Examples ::: example Headings example=../../code/guide/introduction/typography/headings.vue ::: ::: example Paragraph example=../../code/guide/introduction/typography/paragraph.vue ::: ::: example Lists example=../../code/guide/introduction/typography/lists.vue ::: ::: example Image example=../../code/guide/introduction/typography/image.vue ::: ::: example Blockquote example=../../code/guide/introduction/typography/blockquote.vue ::: ## Using Inter Variable font If you desire to use the **Inter Variable** font, you need to override the `--font-sans` css variable. To achieve this, you'll need to add the following to your application. ```css [app.css] :root { --font-sans: inter-variable, sans-serif; } ``` --- --- url: 'https://flux-ui.dev/guide/introduction/dark-mode.md' --- # Dark mode Flux includes full support for both light and dark mode, with a color system that adapts to each. Toggle dark mode by setting the `dark` attribute on the document element, as shown below. ## Functional API ::: code-group ```ts [theme.ts] import { useRemembered } from '@flux-ui/internals' const darkMode = useRemembered("dark-mode", false); function toggleMode(): void { darkMode.value = !darkMode.value; if (darkMode.value) { document.documentElement.setAttribute("dark", "dark"); } else { document.documentElement.removeAttribute("dark"); } } ``` ```vue [App.vue] ``` ::: --- --- url: 'https://flux-ui.dev/guide/introduction/font-awesome.md' --- # Font Awesome Flux uses [Font Awesome](https://fontawesome.com) as its icon library, giving you access to a large collection of icons for your UI. Icons must be registered before use. ## Register icons Icons must be registered before use so they are available throughout your application. Import the icons you need from [Font Awesome](https://fontawesome.com) and register them with the `configureIcons` function. ::: code-group ```ts [icons.ts] export { faCircleCheck, faCircleExclamation } from '@fortawesome/pro-regular-svg-icons'; ``` ```ts [register.ts] import { configureIcons } from '@flux-ui/components'; import * as icons from './icons.ts'; configureIcons({icons}); ``` ```vue [Page.vue] ``` ::: > The standalone `fluxRegisterIcons(icons)` function still works but is deprecated in favor of `configureIcons({icons})`. ## Using the icon font Instead of registering SVG icons, you can render icons with a Font Awesome webfont. Load the font yourself, bind its `font-family` to the style class Flux emits, then switch Flux to font mode with `configureIcons`. Icons keep being used the same way through the `name` prop. In font mode `` renders the icon name as the element's text and relies on the font's ligatures to turn it into the glyph: ```html user ``` ::: code-group ```ts [main.ts] import { configureIcons } from '@flux-ui/components'; configureIcons({ renderMode: 'font', defaultStyle: 'regular' }); ``` ```css [fonts.css] @font-face { font-family: font-awesome; src: url(...); } /* Bind the style class Flux emits to the loaded font. */ .fa-regular { font-family: font-awesome; font-weight: 400; } ``` ```vue [Page.vue] ``` ::: Because Font Awesome glyphs draw with `currentColor`, the `color` and `size` props behave exactly as they do in SVG mode. The internal Flux icons were designed against the `regular` family, so `defaultStyle: 'regular'` matches the default SVG look most closely. ### Choosing the style Flux emits one style class per icon (`fa-solid`, `fa-regular`, `fa-light`, `fa-thin`, `fa-duotone`, `fa-brands`) that you bind to a `font-family`. `FluxIconName` only carries the name, so the style is resolved in this order: 1. The `icon-style` prop on the icon. 2. A per-name entry in `styleOverrides`. 3. The global `defaultStyle`. 4. `solid` as a fallback. ```ts configureIcons({ renderMode: 'font', defaultStyle: 'light', styleOverrides: { github: 'brands' } }); ``` ```vue ``` ### Duotone Font Awesome draws a duotone icon as two stacked layers, so in `duotone` mode Flux renders the primary shape over a dimmed secondary one, both from a single `color`. Bind `.fa-duotone` to the duotone font like any other style; tune the secondary tone with the `--fa-secondary-opacity` custom property (default `.2`, matching the SVG rendering). ### Notes * Font mode does not register any SVG data, so chart icons in `@flux-ui/statistics` still require SVG registration through `configureIcons({icons})`. * The font must provide ligatures for the icon names; otherwise the bare name stays visible as text. ## Required icons Below is a list of all the icons that Flux uses throughout the library. ```ts [icons.ts] export { faAngleDown, faAngleLeft, faAngleRight, faAnglesUpDown, faArrowDown19, faArrowDownAZ, faArrowDownShortWide, faArrowUp91, faArrowUpAZ, faArrowUpArrowDown, faArrowUpWideShort, faCalendar, faCheck, faChevronDown, faChevronRight, faChevronUp, faCircleCheck, faCircleExclamation, faCircleInfo, faCircleXmark, faCloud, faEllipsis, faEllipsisH, faEye, faEyeSlash, faFilter, faMagnifyingGlass, faMinus, faPlus, faRotateLeft, faSlashForward, faSlidersSimple, faStar, faTrash, faUser, faXmark } from '@fortawesome/pro-regular-svg-icons'; ``` --- --- url: 'https://flux-ui.dev/guide/composables/useBreakpoints.md' --- # useBreakpoints This composable tracks the current viewport breakpoint and provides reactive boolean refs for each breakpoint size. ## Usage ```ts import { useBreakpoints } from '@flux-ui/components'; const { currentBreakpoint, xs, sm, md, lg, xl } = useBreakpoints(); // Use in a computed or watcher if (md.value) { console.log('Viewport is at least medium'); } ``` ## Example Switch a stack from horizontal to vertical depending on the active breakpoint. Resize the preview to see it in action. ::: example Responsive layout || A card layout that switches direction at the `md` breakpoint. example=../../code/guide/composables/useBreakpoints/responsive-layout.vue ::: ## Breakpoints ### xs (0px) Targets the smallest viewports. Active when the viewport width is 0px or more. ### sm (640px) Targets small viewports such as large phones in landscape mode. Active when the viewport width is 640px or more. ### md (768px) Targets medium viewports such as tablets in portrait mode. Active when the viewport width is 768px or more. ### lg (1024px) Targets large viewports such as tablets in landscape mode and small desktops. Active when the viewport width is 1024px or more. ### xl (1280px) Targets extra-large viewports such as full-size desktop screens. Active when the viewport width is 1280px or more. ## Type declarations ```ts type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; declare function useBreakpoints(): { readonly currentBreakpoint: Ref; readonly xs: Ref; readonly sm: Ref; readonly md: Ref; readonly lg: Ref; readonly xl: Ref; }; ``` --- --- url: 'https://flux-ui.dev/guide/composables/useDisabled.md' --- # useDisabled This composable merges a component's local disabled state with any inherited disabled state from a parent [Disabled](../../components/disabled) component. Returns `true` if either the component itself or any parent in the tree is disabled. ## Usage ```ts import { useDisabled } from '@flux-ui/components'; import { toRef } from 'vue'; const { disabled: componentDisabled } = defineProps<{ disabled?: boolean; }>(); const disabled = useDisabled(toRef(() => componentDisabled)); ``` ## Type declarations ```ts import type { ComputedRef, Ref } from 'vue'; declare function useDisabled( componentDisabled: Ref ): ComputedRef; ``` ## Example Toggle a parent [Disabled](../../components/disabled) component to disable an entire group of inputs and actions at once. Each Flux component reads the inherited disabled state through `useDisabled` internally, so you don't need to forward the prop manually. ::: example Inherited disabled || A toggle that disables a group of inputs and buttons via a wrapping `FluxDisabled`. example=../../code/guide/composables/useDisabled/inherited.vue ::: ## Used by * [Button](../../components/button/) * [Form](../../components/form/) * [Input](../../components/form/input/) * [Select](../../components/form/select/) --- --- url: 'https://flux-ui.dev/guide/composables/useDisabledInjection.md' --- # useDisabledInjection This composable retrieves the disabled state from a parent [Disabled](../../components/disabled) component via Vue's dependency injection. Returns `false` when no parent provides a disabled state. ## Usage ```ts import { useDisabledInjection } from '@flux-ui/components'; const isTreeDisabled = useDisabledInjection(); ``` ## Type declarations ```ts import type { Ref } from 'vue'; declare function useDisabledInjection(): Ref; ``` ## Used by * [useDisabled](./useDisabled) --- --- url: 'https://flux-ui.dev/guide/composables/useExpandableGroupInjection.md' --- # useExpandableGroupInjection This composable provides access to the [Expandable group](../../components/expandable/group) context. It allows child expandable items to register with the group and respond to group-level actions like closing all items. ## Usage ```ts import { useExpandableGroupInjection } from '@flux-ui/components'; const { closeAll, register, unregister } = useExpandableGroupInjection(); ``` ## Type declarations ```ts declare function useExpandableGroupInjection(): { closeAll(): void; register(uid: number, instance: object): void; unregister(uid: number): void; }; ``` ## Used by * [Expandable](../../components/expandable/) --- --- url: 'https://flux-ui.dev/guide/composables/useFilterInjection.md' --- # useFilterInjection This composable provides access to the [Filter](../../components/filter/) context. It is used by filter sub-components to interact with the parent filter's state and actions. ## Usage ```ts import { useFilterInjection } from '@flux-ui/components'; const { state, back, reset, getValue, hasValue, setValue } = useFilterInjection(); ``` ## Type declarations ```ts import type { Ref } from 'vue'; declare function useFilterInjection(): { readonly state: Ref; back(): void; reset(): void; getValue(): unknown; hasValue(): boolean; setValue(value: unknown): void; }; ``` ## Used by * [Filter](../../components/filter/) * [Date](../../components/filter/date) * [Option](../../components/filter/option) * [Options](../../components/filter/options) * [Range](../../components/filter/range) --- --- url: 'https://flux-ui.dev/guide/composables/useFlyoutInjection.md' --- # useFlyoutInjection This composable provides access to the [Flyout](../../components/flyout) state. It allows child components to react to the flyout's open, opening and closing states. ## Usage ```ts import { useFlyoutInjection } from '@flux-ui/components'; const { isClosing, isOpen, isOpening } = useFlyoutInjection(); ``` ## Type declarations ```ts import type { Ref } from 'vue'; declare function useFlyoutInjection(): { readonly isClosing: Ref; readonly isOpen: Ref; readonly isOpening: Ref; }; ``` ## Used by * [Flyout](../../components/flyout) * [Menu](../../components/menu/) --- --- url: 'https://flux-ui.dev/guide/composables/useFormFieldInjection.md' --- # useFormFieldInjection This composable provides access to the [Form field](../../components/form/field/) context. It supplies a unique ID that can be used for `for`/`id` attribute pairing between labels and inputs. ## Usage ```ts import { useFormFieldInjection } from '@flux-ui/components'; const { id } = useFormFieldInjection(); ``` ## Type declarations ```ts declare function useFormFieldInjection(): { readonly id: string; }; ``` ## Used by * [Form](../../components/form/) * [Input](../../components/form/input/) * [Select](../../components/form/select/) * [Text area](../../components/form/text-area) --- --- url: 'https://flux-ui.dev/guide/composables/useTableInjection.md' --- # useTableInjection This composable provides access to the [Table](../../components/table/) layout context. It exposes the pinned column state and lets custom column headers register themselves so the table can compute its `grid-template-columns`. ## Usage ```ts import { useTableInjection } from '@flux-ui/components'; const { pinnedEdges, pinnedOffsets, registerColumn } = useTableInjection(); ``` ## Type declarations ```ts declare function useTableInjection(): { readonly pinnedEdges: Ref<{ readonly end: number; readonly start: number; }>; readonly pinnedOffsets: Ref>; registerColumn(element: Readonly>, column: Readonly>): () => void; }; ``` * `pinnedEdges`: the column index of the last start-pinned column and the first end-pinned column (`-1` when there is none). Used to render the scroll shadow on the outermost pinned column. * `pinnedOffsets`: the sticky offset in pixels for each pinned column, keyed by column index. * `registerColumn`: registers a column definition (sizing and pinning) for the table's `grid-template-columns`. Returns an unregister function. ## Used by * [Table](../../components/table/) * [Row](../../components/table/row) * [Cell](../../components/table/cell) * [Header](../../components/table/header) --- --- url: 'https://flux-ui.dev/guide/composables/useTooltipInjection.md' --- # useTooltipInjection This composable provides access to the [Tooltip](../../components/tooltip) provider context. It exposes a `calculate` method that triggers tooltip position recalculation. ## Usage ```ts import { useTooltipInjection } from '@flux-ui/components'; const { calculate } = useTooltipInjection(); // Trigger position recalculation calculate(); ``` ## Type declarations ```ts declare function useTooltipInjection(): { calculate(): void; }; ``` ## Used by * [Tooltip](../../components/tooltip) --- --- url: 'https://flux-ui.dev/guide/api/useFluxStore.md' --- # useFluxStore Provides access to the centralized Flux store that manages dialogs, snackbars and tooltips. This composable is primarily used internally by Flux components, but can be useful for advanced use cases. ## Usage ```ts import { useFluxStore } from '@flux-ui/components'; const store = useFluxStore(); // Check if any dialogs are open if (store.inertMain.value) { console.log('A dialog is currently blocking the main content.'); } ``` ## Type declarations ```ts import type { ComputedRef } from 'vue'; declare function useFluxStore(): FluxStore; interface FluxStore { readonly alerts: FluxAlertObject[]; readonly confirms: FluxConfirmObject[]; readonly prompts: FluxPromptObject[]; readonly snackbars: FluxSnackbarObject[]; readonly tooltips: FluxTooltipObject[]; readonly dialogs: number[]; readonly dialogCount: number; readonly inertMain: ComputedRef; readonly tooltip: ComputedRef; addAlert(spec: Omit): number; addConfirm(spec: Omit): number; addPrompt(spec: Omit): number; addSnackbar(spec: Omit): number; addTooltip(spec: Omit): number; removeAlert(id: number): void; removeConfirm(id: number): void; removePrompt(id: number): void; removeSnackbar(id: number): void; removeTooltip(id: number): void; updateSnackbar(id: number, spec: Partial): void; updateTooltip(id: number, spec: Partial): void; registerDialog(): FluxDialogRegistration; showAlert(spec: Omit): Promise; showConfirm(spec: Omit): Promise; showPrompt(spec: Omit): Promise; showSnackbar(spec: Omit & { duration?: number }): Promise; showSnackbarSync(spec: Omit & { duration?: number }): void; } interface FluxDialogRegistration { readonly id: number; getPosition(): number; isCurrent(): boolean; unregister(): void; } ``` ::: tip For showing dialogs and snackbars, prefer using the dedicated functions [showAlert](../../components/attention/alert), [showConfirm](../../components/attention/confirm), [showPrompt](../../components/attention/prompt) and [showSnackbar](../../components/attention/snackbar) instead of interacting with the store directly. ::: --- --- url: 'https://flux-ui.dev/guide/api/helpers.md' --- # Helper functions Utility helpers and type guards for working with Flux components. ## defineFilter Macro for building a [Filter](../../components/filter) definition factory. Call it on the top level of ` ``` ::: ## Used components * [Icon](../../icon) --- --- url: 'https://flux-ui.dev/components/form/input/group.md' --- # Input group The input group combines an input field with an additional element, such as a button to create a single, cohesive control. This layout is useful for actions or context directly related to the input. ::: render render=../../../code/components/form/input/group/preview.vue ::: ## Examples ::: example Basic || A basic and simple input group. example=../../../code/components/form/input/group/basic.vue ::: ::: example Labelled || An accessible group label via `aria-label`; the group only takes `role="group"` when labelled. example=../../../code/components/form/input/group/labelled.vue ::: --- --- url: 'https://flux-ui.dev/components/form/number-input.md' --- # Number input A number input is a form-integrated numeric field with stepper buttons. Users can type a value directly, use the up and down buttons, or the arrow keys to step by the configured `step`. The value is clamped to `min` and `max` when stepping and on blur, and on blur it is additionally snapped to the nearest `step`. It is bound through `v-model` as a `number` (or `null` when empty). ::: render render=../../code/components/form/number-input/preview.vue ::: ::: tip For a standalone amount picker outside of a form (such as a quantity in a shopping cart), consider the [Quantity selector](./quantity-selector) instead. ::: ## Examples ::: example Basic || A number input inside a form field. example=../../code/components/form/number-input/basic.vue ::: ::: example Range and step || A number input bound to a range with a custom step. example=../../code/components/form/number-input/range.vue ::: ::: example Step snapping || Typed values snap to the nearest valid step (from `min`) and clamp on blur. example=../../code/components/form/number-input/snapping.vue ::: ## Used components * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/form/pin-input.md' --- # PIN input The PIN input renders a fixed number of single-character boxes for entering a PIN-like value, such as a TOTP code from an authenticator app. ::: render render=../../code/components/form/pin-input/preview.vue ::: ::: tip Pasting a code fills the fields automatically. Non-digit characters are stripped and longer values are truncated to `max-length`, so a partial or padded paste still lands the cursor on the last filled field. ::: ## Examples ::: example Basic || A basic pin input. example=../../code/components/form/pin-input/basic.vue ::: ::: example Toggle || A pin input where you can toggle the private state. example=../../code/components/form/pin-input/toggle.vue ::: ::: example Custom || A pin input with a different amount of numbers. example=../../code/components/form/pin-input/longer.vue ::: ::: example Accessible label || An accessible label for screen readers; pasted codes are truncated to the length and partial pastes are supported. example=../../code/components/form/pin-input/accessible.vue ::: --- --- url: 'https://flux-ui.dev/components/form/quantity-selector.md' --- # Quantity selector A quantity selector can be used when users need to select an amount of something. For example, Within a shop, a user is able to select how many of a certain product they want to buy. ::: render render=../../code/components/form/quantity-selector/preview.vue ::: ## Examples ::: example Basic || A basic quantity selector. example=../../code/components/form/quantity-selector/basic.vue ::: ::: example Step || A quantity selector with steps. example=../../code/components/form/quantity-selector/step.vue ::: ::: example Fractional step || A quantity selector with a decimal step; values snap to the step. example=../../code/components/form/quantity-selector/fractional.vue ::: ::: example Disabled || A disabled quantity selector. example=../../code/components/form/quantity-selector/disabled.vue ::: ## Used components * [Button](../button) * [Secondary](../button/secondary) * [Group](../button/group) --- --- url: 'https://flux-ui.dev/components/form/radio.md' --- # Radio A radio represents a single option within a [Radio group](./group). It carries a `value`; selecting it updates the group's `v-model` to that value. A radio can render a plain label or fully custom content through its default slot. ::: render render=../../../code/components/form/radio/preview.vue ::: ::: warning This component is best used within a [Radio group](./group). ::: ## Examples ::: example Custom content || A radio with custom label content. example=../../../code/components/form/radio/content.vue ::: ::: example Sub-label || A radio with a secondary line of text below the label. example=../../../code/components/form/radio/sub-label.vue ::: ::: example Disabled option || A radio group where a single option is disabled. example=../../../code/components/form/radio/disabled-option.vue ::: ::: example Label only || A minimal radio group using just the `label` prop. example=../../../code/components/form/radio/label-only.vue ::: ## Used components * [Radio group](./group) --- --- url: 'https://flux-ui.dev/components/form/radio/group.md' --- # Radio group A radio group lets users pick a single option from a small, fully visible set of choices. Each choice is a [Radio](./), and the selected one is bound through `v-model` and reflects the `value` of the active radio. ::: render render=../../../code/components/form/radio/group/preview.vue ::: ::: tip Reach for a radio group when every option should stay visible at a glance. When the list is long or space is tight, prefer a [Select](../select/) instead. When wrapped in a `required` [Form field](../field/), the group (`role="radiogroup"`) automatically receives `aria-required`, and setting `error` exposes `aria-invalid`. ::: ## Examples ::: example Basic || A radio group inside a form field. example=../../../code/components/form/radio/group/basic.vue ::: ::: example Inline || A radio group laid out horizontally. example=../../../code/components/form/radio/group/inline.vue ::: ::: example Disabled item || A radio group with a single disabled option. example=../../../code/components/form/radio/group/disabled.vue ::: ::: example Tile || Card-style options through [Radio tile](./tile), with an icon and description. example=../../../code/components/form/radio/tile/stacked.vue ::: ::: example Mixed || Combine tiles with a regular radio for a less prominent option. example=../../../code/components/form/radio/tile/mixed.vue ::: ::: example Connected || Join the tiles into a single block with is-connected. example=../../../code/components/form/radio/tile/connected.vue ::: ## Used components * [Radio](./) * [Radio tile](./tile) --- --- url: 'https://flux-ui.dev/components/form/radio/tile.md' --- # Radio tile A radio tile is a card-style [Radio](./) for prominent, fully visible choices. Each option carries an icon, a label and a short description. Place the tiles inside a [Radio group](./group) just like regular radios; the group handles selection and state. ::: render render=../../../code/components/form/radio/tile/preview.vue ::: ::: tip Tiles fill the group's width when stacked. Add `is-inline` to the [Radio group](./group) to lay them out in equal columns, best for two or three options. You can mix tiles and regular [Radios](./) in the same group when one option is less prominent. ::: ## Examples ::: example Stacked || Card-style radios stacked at full width. example=../../../code/components/form/radio/tile/stacked.vue ::: ::: example Inline || Tiles laid out in equal columns with is-inline. example=../../../code/components/form/radio/tile/inline.vue ::: ::: example Without description || Compact tiles with just an icon and label, no sub-label. example=../../../code/components/form/radio/tile/without-description.vue ::: ::: example Shipping method || A real-world group with a description and price per option. example=../../../code/components/form/radio/tile/shipping.vue ::: ## Used components * [Icon](../../icon) * [Radio group](./group) --- --- url: 'https://flux-ui.dev/components/form/rating.md' --- # Rating The rating lets a user pick a score by selecting stars. It supports half-step selection, a read-only mode for displaying an existing rating, and full keyboard control: arrow keys adjust the value, number keys jump to a score, Home/End select the extremes, and Delete/Backspace clear it when `clearable`. The model value is a number, or `null` when no rating is set. ::: render render=../../code/components/form/rating/preview.vue ::: ## Examples ::: example Basic || A basic rating. example=../../code/components/form/rating/basic.vue ::: ::: example Half steps || A rating that allows half steps. example=../../code/components/form/rating/half-steps.vue ::: ::: example Read-only || A read-only rating for displaying a value. example=../../code/components/form/rating/readonly.vue ::: ::: example Clearable || A clearable rating; keyboard users can press Delete or Backspace to reset it. example=../../code/components/form/rating/clearable.vue ::: ::: example Custom count || A rating out of ten stars using `count`. example=../../code/components/form/rating/count.vue ::: ::: example Custom icon || A rating using a different icon. example=../../code/components/form/rating/icon.vue ::: ::: example Custom size || Larger stars using the `size` prop. example=../../code/components/form/rating/size.vue ::: ::: example Disabled || A disabled rating showing a fixed value. example=../../code/components/form/rating/disabled.vue ::: ## Used components * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/form/row.md' --- # Row The row places fields in a horizontal stack. It's ideal for grouping related inputs side-by-side, such as first and last name fields. This layout keeps the form compact and visually aligned while maintaining a clear relationship between the fields. ::: render render=../../code/components/form/row/preview.vue ::: ## Examples ::: example Basic || A basic form row. example=../../code/components/form/row/basic.vue ::: --- --- url: 'https://flux-ui.dev/components/form/section.md' --- # Form section The form section groups related fields under a shared title. It helps divide longer forms into logical blocks, making them easier to scan and complete. ::: render render=../../code/components/form/section/preview.vue ::: ::: info Accessibility The section is exposed as a labelled group (`role="group"` + `aria-labelledby`) so assistive technology announces the title as the name of the contained fields. Use `heading-level` to keep the rendered heading (`

`–`

`) consistent with the surrounding document outline. ::: ::: tip This component is best used within a [Form](../form). ::: ## Examples ::: example Heading level || Render the section title as a real heading (h1–h6) instead of the default h3. example=../../code/components/form/section/heading-level.vue ::: ## Snippet ::: code-group ```vue \[FluxFormSection.vue] ``` ::: --- --- url: 'https://flux-ui.dev/components/form/select.md' --- # Select The select lets users choose one or more options from a list. Enable `is-searchable` to filter long lists and `is-multiple` to allow several values at once. Options can be grouped. ::: render render=../../../code/components/form/select/preview.vue ::: ::: info Accessibility The control is exposed as a `role="combobox"` and tracks the highlighted option through `aria-activedescendant` and `aria-controls` while the popup is open. When `name` is set, the selected values are mirrored into a hidden input so the select participates in native form submission. ::: ## Examples ::: example Basic || A basic form select. example=../../../code/components/form/select/basic.vue ::: ::: example Searchable || A form select in where you can search for the items. example=../../../code/components/form/select/searchable.vue ::: ::: example Multiple || A form select in where you can select multiple options. example=../../../code/components/form/select/multiple.vue ::: ::: example Read-only || A read-only select that shows its value but cannot be opened or changed. example=../../../code/components/form/select/readonly.vue ::: ## Used components * [Form](../../form) * [Input](../input) * [Menu](../../menu) * [Item](../../menu/item) * [Group](../../menu/group) * [SubHeader](../../menu/sub-header) * [Icon](../../icon) * [Spinner](../../spinner) * [Tag](../../tag) --- --- url: 'https://flux-ui.dev/components/form/select/async.md' --- # Select async The async select fetches its options on demand instead of receiving them up front. Provide `fetch-relevant`, `fetch-search` and `fetch-options` to load the initial set, respond to the search query, and resolve selected values by their id. Enable `is-multiple` to allow several values at once. ::: render render=../../../code/components/form/select/async/preview.vue ::: ::: tip When the popup opens with an active search query, `fetch-search` is called with that query; otherwise `fetch-relevant` is used. This keeps a previously typed search reflected in the initial result set. ::: ## Examples ::: example Basic || A basic asynchronous form select. example=../../../code/components/form/select/async/basic.vue ::: ::: example Multiple || An asynchronous form select in where you can select multiple options. example=../../../code/components/form/select/async/multiple.vue ::: ## Used components * [Form](../../form) * [Input](../input) * [Menu](../../menu) * [Item](../../menu/item) * [Group](../../menu/group) * [SubHeader](../../menu/sub-header) * [Icon](../../icon) * [Spinner](../../spinner) * [Tag](../../tag) --- --- url: 'https://flux-ui.dev/components/form/slider.md' --- # Slider The slider lets users pick a single value from a range by dragging a thumb. Set `min`, `max` and `step` to define the range, and provide a `formatter` to control how the value is displayed. ::: render render=../../../code/components/form/slider/preview.vue ::: ::: tip Clicking anywhere on the track jumps the thumb to that position, and dragging keeps tracking the pointer even when it leaves the slider. The thumb can also be moved with the arrow keys for keyboard users. ::: ## Examples ::: example Basic || A basic slider from 0 to 100. example=../../../code/components/form/slider/basic.vue ::: ::: example Vertical || A vertical slider. It defaults to 210px tall and can be resized with CSS. example=../../../code/components/form/slider/vertical.vue ::: ::: example Ticks || A slider where the ticks are visible. example=../../../code/components/form/slider/ticks.vue ::: ::: example Custom formatter || A slider with a custom formatter. example=../../../code/components/form/slider/formatter.vue ::: --- --- url: 'https://flux-ui.dev/components/form/slider/ranged.md' --- # Range slider The range slider lets users select a range of values between a lower and an upper bound. It works like the [Slider](../slider/), but with two thumbs, one for each end of the range. ::: render render=../../../code/components/form/slider/ranged/preview.vue ::: ::: tip Clicking anywhere on the track moves the thumb closest to the pointer, so the range can be adjusted without grabbing a handle first. Use `min-distance` to keep a minimum gap between the two thumbs. ::: ## Examples ::: example Basic || A basic range slider from 0 to 100. example=../../../code/components/form/slider/ranged/basic.vue ::: ::: example Vertical || A vertical range slider. It defaults to 210px tall and can be resized with CSS. example=../../../code/components/form/slider/ranged/vertical.vue ::: ::: example Minimum distance || A range slider that keeps at least 20 units between both thumbs. example=../../../code/components/form/slider/ranged/min-distance.vue ::: ::: example Ticks || A range slider where the ticks are visible. example=../../../code/components/form/slider/ranged/ticks.vue ::: ::: example Custom formatter || A range slider with a custom formatter. example=../../../code/components/form/slider/ranged/formatter.vue ::: --- --- url: 'https://flux-ui.dev/components/form/step.md' --- # Form step The form step breaks a longer form into numbered stages. Each step is automatically numbered and pairs a required title with an optional subtitle, followed by its own content at full width. ::: render render=../../code/components/form/step/preview.vue ::: ::: info Accessibility Every step is exposed as a labelled group (`role="group"` + `aria-labelledby`) so assistive technology announces the title as the name of its content. The number badge is decorative (`aria-hidden`). ::: ::: tip This component is best used within a [Form](../form), which resets the numbering. Steps are numbered automatically with a CSS counter. ::: ## Examples ::: example End slot || Add trailing content, like a status badge, to the step header through the `end` slot. example=../../code/components/form/step/end-slot.vue ::: ## Snippet ::: code-group ```vue \[FluxFormStep.vue] ``` ::: --- --- url: 'https://flux-ui.dev/components/form/tags-input.md' --- # Tags input The tags input lets users build a list of tags by typing and committing each value, for example to assign keywords or labels. Values are committed on Enter or a comma (configurable), pasted text is split into multiple tags, and Backspace on an empty input removes the last tag. When `suggestions` are provided, a filtered dropdown is shown while typing. ::: info Picking a suggestion stores its `value` (as a string) when one is set, falling back to the `label` otherwise. This keeps the bound `v-model` made up of stable identifiers rather than display text. The input is exposed as a `role="combobox"` and links the highlighted suggestion through `aria-activedescendant`. ::: ::: render render=../../code/components/form/tags-input/preview.vue ::: ## Examples ::: example Basic || A basic tags input. example=../../code/components/form/tags-input/basic.vue ::: ::: example Suggestions || A tags input with suggestions. example=../../code/components/form/tags-input/suggestions.vue ::: ::: example Tag color || Render the tags in a chosen color with `tag-color`. example=../../code/components/form/tags-input/tag-color.vue ::: ::: example Validation || Only accept valid entries by passing a `validate` function. example=../../code/components/form/tags-input/validation.vue ::: ::: example Custom delimiters || Commit tags on a space or comma in addition to Enter. example=../../code/components/form/tags-input/delimiters.vue ::: ::: example Disabled || A disabled tags input with existing tags. example=../../code/components/form/tags-input/disabled.vue ::: ## Used components * [Tag](../tag) --- --- url: 'https://flux-ui.dev/components/form/text-area.md' --- # Text area A form text area is a text field that may have multiple lines of text. It is used for longer text and can be used within a contact form to ask for a question. ::: render render=../../code/components/form/text-area/preview.vue ::: ## Examples ::: example Basic || A basic text area. example=../../code/components/form/text-area/basic.vue ::: ::: example Multiple rows || A text area with multiple rows example=../../code/components/form/text-area/rows.vue ::: ::: example Max length || A text area capped with `max-length`. example=../../code/components/form/text-area/max-length.vue ::: ::: example Disabled || A disabled text area. example=../../code/components/form/text-area/disabled.vue ::: ::: example Invalid || A text area with an error message. example=../../code/components/form/text-area/invalid.vue ::: ::: example Read-only || A read-only text area showing prefilled content. example=../../code/components/form/text-area/readonly.vue ::: --- --- url: 'https://flux-ui.dev/components/form/time.md' --- # Time ::: warning This component is coming soon! ::: --- --- url: 'https://flux-ui.dev/components/form/time-zone-picker.md' --- # Time zone picker The time zone picker lets users choose a time zone from a comprehensive list, so date and time information stays accurate for their location. ::: render render=../../code/components/form/time-zone-picker/preview.vue ::: ## Examples ::: example Basic || A basic time zone picker. example=../../code/components/form/time-zone-picker/basic.vue ::: ::: example Preselected || A time zone picker with a value already selected. example=../../code/components/form/time-zone-picker/preselected.vue ::: ::: example Disabled || A disabled time zone picker. example=../../code/components/form/time-zone-picker/disabled.vue ::: ::: example Invalid || A time zone picker with an error message. example=../../code/components/form/time-zone-picker/invalid.vue ::: ## Used components * [Form](../form) * [Select](./select) --- --- url: 'https://flux-ui.dev/components/form/toggle.md' --- # Toggle The toggle switches between two states, on and off. Use it in settings and option panels to enable or disable a feature. ::: render render=../../code/components/form/toggle/preview.vue ::: ::: info Accessibility The toggle is exposed as a native `role="switch"` checkbox. State and validation attributes (`aria-checked`, `aria-disabled`, `aria-readonly`, `aria-invalid`) sit on that control, and when wrapped in a required [Form field](./field/) it also receives `aria-required`. ::: ## Examples ::: example Basic || A basic toggle. example=../../code/components/form/toggle/basic.vue ::: ::: example Icons || A toggle with icons for both the on and off state. example=../../code/components/form/toggle/icon.vue ::: ::: example Form || A toggle used in a form. example=../../code/components/form/toggle/form.vue ::: ::: example Disabled || A disabled toggle in both the off and on state. example=../../code/components/form/toggle/disabled.vue ::: ::: example Invalid || A toggle with an error message. example=../../code/components/form/toggle/invalid.vue ::: ::: example Read-only || A read-only toggle that cannot be changed. example=../../code/components/form/toggle/readonly.vue ::: ## Used components * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/form/tree-view-select.md' --- # Tree view select This is a form select element that displays options in a hierarchical tree structure. It supports expanding and collapsing branches, single and multiple selection, an optional search input for filtering, and cascading selection where picking a parent covers its whole subtree. Each selectable option carries a checkbox (multiple) or radio (single) showing whether it is selected. The tree is rendered with connecting lines to visualize the hierarchy. Every option ends its guide line with a marker of the same size: options with children render it as the expand toggle holding the chevron, leaf options as a plain circle. Markers can be colored per option or per depth level, using either a `FluxColor` name or any CSS/HEX color string. ::: render render=../../code/components/form/tree-view-select/preview.vue ::: ::: info Accessibility The trigger is exposed as a `role="combobox"` (`aria-haspopup="tree"`) and the option list as a `role="listbox"`. The highlighted node is tracked through `aria-activedescendant`, selectable nodes carry `role="option"` with `aria-selected`, and non-selectable group headers are marked `role="presentation"`. The option row itself stays the control: its checkbox or radio is a read-only indicator marked `aria-hidden`, so assistive tech announces the selection once, through `aria-selected`. When wrapped in a required [Form field](./field/) the trigger also receives `aria-required`. ::: ## Option object Each entry in the `options` array (and nested `children` arrays) is a `FluxFormTreeViewSelectOption`: ## Keyboard navigation ## Examples ::: example Basic || A tree view select with per-level colors. example=../../code/components/form/tree-view-select/basic.vue ::: ::: example Multiple || A tree view select that allows selecting multiple items across the tree. example=../../code/components/form/tree-view-select/multiple.vue ::: ::: example Searchable || A tree view select with a search input. Matching nodes keep their place in the hierarchy: their ancestors stay visible and non-matching branches are pruned. example=../../code/components/form/tree-view-select/searchable.vue ::: ::: example Non-selectable parents || Parent nodes can have `selectable: false` so they act as group headers. Only leaf nodes can be selected. example=../../code/components/form/tree-view-select/non-selectable-parents.vue ::: ::: example Expanded depth || With `expanded-depth`, the popup opens with more than just its roots visible. Handy when the top level only groups the options that can actually be picked. example=../../code/components/form/tree-view-select/expanded-depth.vue ::: ::: example Cascading || With `is-cascading`, selecting a parent covers its whole subtree. Its descendants are shown as checked and locked, while the model value keeps only the explicitly selected ids. example=../../code/components/form/tree-view-select/cascading.vue ::: ::: example Disabled options || Options with `disabled: true` cannot be selected, but their branch can still be expanded. example=../../code/components/form/tree-view-select/disabled-options.vue ::: ::: example Per-option colors || Coloring each option individually with `color`, instead of per depth level. example=../../code/components/form/tree-view-select/per-option-colors.vue ::: ::: example Custom colors || Using HEX colors instead of FluxColor names for each level. example=../../code/components/form/tree-view-select/custom-colors.vue ::: ## Used components * [Form](../form) * [Checkbox](./checkbox) * [Input](./input) * [Radio](./radio) * [Icon](../icon) * [Tag](../tag) --- --- url: 'https://flux-ui.dev/components/navigation.md' --- # Navigation The navigation components handle wayfinding and view-switching, so people can move around, change what they see and step through multi-stage flows. --- --- url: 'https://flux-ui.dev/components/breadcrumb.md' --- # Breadcrumb A breadcrumb shows users where they are within a hierarchy and lets them navigate back to any ancestor. Each step is a [Breadcrumb item](./item) or a [Breadcrumb flyout](./flyout); a non-linked item represents the current page and is rendered as plain, non-interactive text with `aria-current="page"`. Separators are inserted automatically between steps. Steps are not limited to a label and icon. An item can hold an [avatar](../avatar), a [badge](../badge) or a [tag](../tag) through its `leading` and `trailing` slots, and a [Breadcrumb flyout](./flyout) turns a step into a dropdown so users can switch to a sibling without leaving the trail. ::: render render=../../code/components/breadcrumb/preview.vue ::: ## Examples ::: example Basic || A breadcrumb trail with links. example=../../code/components/breadcrumb/basic.vue ::: ::: example With icons || An icon per step makes the trail easier to scan. example=../../code/components/breadcrumb/icons.vue ::: ::: example Custom separator || The separator defaults to a chevron. Set `separator` to any icon, such as `slash-forward`, to change it. example=../../code/components/breadcrumb/separator.vue ::: ::: example Collapse the middle || Set `collapse="middle"` to keep the first and last step visible and fold the rest into an overflow menu when the trail runs out of space. Collapsed [Breadcrumb flyout](./flyout) steps become nested submenus. example=../../code/components/breadcrumb/collapse-middle.vue ::: ::: example Collapse from the start || Set `collapse="start"` to keep only the trailing steps visible and fold everything before them into an overflow menu. example=../../code/components/breadcrumb/collapse-start.vue ::: ::: example Rich trail || Combine icons, an [avatar](../avatar), a [badge](../badge) and a [flyout](./flyout) switcher in a single trail. example=../../code/components/breadcrumb/rich.vue ::: ::: tip Collapsing measures the available width, so the breadcrumb needs a bounded container to fold. Place it in a layout that constrains its width (a header bar, a card) rather than an intrinsically sized wrapper. ::: ## Used components * [Breadcrumb item](./item) * [Breadcrumb flyout](./flyout) --- --- url: 'https://flux-ui.dev/components/breadcrumb/item.md' --- # Breadcrumb item A breadcrumb item is a single step in a [Breadcrumb](../breadcrumb/) trail. Provide a `to` to render it as a router link, an `href` to render it as an external anchor, or neither to mark it as the current page, in which case it becomes plain text with `aria-current="page"`. Beyond a `label` and `icon`, an item can render richer content through its `leading` and `trailing` slots — an [avatar](../avatar) for a person, a [badge](../badge) for a status, a [tag](../tag) for a label — or fully custom markup through the default slot. When the item is collapsed into an overflow menu, its `label`, `icon` and `leading` slot are shown as a menu entry. ::: render render=../../code/components/breadcrumb/item/preview.vue ::: ::: warning This component is best used within a [Breadcrumb](../breadcrumb/). ::: ## Examples ::: example Current page || Using `is-current` to mark a linked last item as the current page. example=../../code/components/breadcrumb/item/current.vue ::: ::: example With icons || Add an `icon` to each item to make the trail easier to scan. example=../../code/components/breadcrumb/item/icons.vue ::: ::: example With an avatar || Use the `leading` slot to render an [avatar](../avatar) for a person or organisation. example=../../code/components/breadcrumb/item/avatar.vue ::: ::: example With a badge or tag || Use the `trailing` slot to annotate a step with a [badge](../badge) or [tag](../tag). example=../../code/components/breadcrumb/item/badge.vue ::: ::: example Custom label || Use the default slot to render custom markup instead of the `label` prop. example=../../code/components/breadcrumb/item/slot.vue ::: ## Used components * [Icon](../icon) * [Avatar](../avatar) * [Badge](../badge) * [Tag](../tag) --- --- url: 'https://flux-ui.dev/components/breadcrumb/flyout.md' --- # Breadcrumb flyout A breadcrumb flyout is a step that opens a dropdown instead of navigating, letting users switch to a sibling in the middle of a [Breadcrumb](../breadcrumb/) trail — a different client, project or account — without leaving the current view. It renders a chevron to signal the dropdown and, when collapsed into an overflow menu, becomes a nested submenu. Provide the menu entries in the default slot as [Menu item](../menu/item) components; the wrapping [Menu](../menu/) is added for you. ::: render render=../../code/components/breadcrumb/flyout/preview.vue ::: ::: warning This component is best used within a [Breadcrumb](../breadcrumb/). ::: ## Examples ::: example Path switcher || Group the sibling options, and add actions such as creating a new one below a separator. example=../../code/components/breadcrumb/flyout/basic.vue ::: ::: example With an avatar || Use the `leading` slot to switch between people, showing an [avatar](../avatar) on the trigger. example=../../code/components/breadcrumb/flyout/avatar.vue ::: ## Used components * [Icon](../icon) * [Menu](../menu/) * [Menu item](../menu/item) * [Avatar](../avatar) --- --- url: 'https://flux-ui.dev/components/command-palette.md' --- # Command Palette A searchable command palette that provides quick access to navigation, actions, and entity search through a unified interface. It can optionally be opened with a global `⌘K` (Mac) or `Ctrl+K` (Windows/Linux) keyboard shortcut by setting the `has-keyboard-shortcut` prop. Items are organized through sources, where each source represents a group of related items. Sources can optionally appear as horizontal tabs for scoped filtering. Items within a source can have sub-actions, which are shown after selecting the item. The palette follows the ARIA combobox pattern: the search input owns focus and points at the active result through `aria-activedescendant`, while the results render as a `listbox` of `option`s. The placeholder, empty-state text and accessible labels are localized through the Flux translation keys, so they follow the active locale automatically. ::: render render=../code/components/command-palette/preview.vue ::: ## Sources Sources are the core building blocks of the command palette. Each source has a `key`, `label`, and a list of `items`. Set `tab: true` to show the source as a tab in the tab bar. Use an empty `label` to hide the group header for a source. ```ts type FluxCommandSource = { readonly key: string; readonly label: string; readonly icon?: FluxIconName; readonly tab?: boolean; readonly items: FluxCommandSourceItem[]; readonly fetchSearch?: (query: string) => Promise; }; ``` ### Async sources A source can provide a `fetchSearch` function to load items asynchronously when the user types a search query. Static `items` are shown when the search is empty, and `fetchSearch` results replace them when a query is entered. A centered spinner is displayed while the fetch is in progress. ## Items Each item has a label, optional icon, and an `onActivate` callback. Items can also have a `command` string (e.g. `⌘D`) displayed as a keyboard shortcut badge, and `subActions` for secondary actions. ```ts type FluxCommandSourceItem = { readonly id: string | number; readonly label: string; readonly subLabel?: string; readonly icon?: FluxIconName; readonly command?: string; readonly subActions?: FluxCommandSubAction[]; readonly onActivate: () => void; }; ``` ## Sub-actions When an item has `subActions`, selecting it will show a sub-action menu instead of immediately activating the item. This is useful for entities that have multiple possible actions, such as "View", "Edit", or "Delete". ```ts type FluxCommandSubAction = { readonly label: string; readonly icon?: FluxIconName; readonly onActivate: () => void; }; ``` ## Examples ::: example Basic || A basic command palette with navigation and actions. Press `⌘K` or click the button to open. example=../code/components/command-palette/basic.vue ::: ::: example Multiple sources || A command palette with multiple sources, tabs, and sub-actions. example=../code/components/command-palette/with-sources.vue ::: ::: example Async || A command palette with an async source that fetches customers from a simulated API. Static items are shown initially, and search results are loaded dynamically. example=../code/components/command-palette/async.vue ::: ::: example Complex || A full-featured command palette with navigation, entity search, standalone actions with sub-menus (Theme, Language, Export), recent items, and keyboard shortcut badges. example=../code/components/command-palette/complex.vue ::: --- --- url: 'https://flux-ui.dev/components/context-menu.md' --- # Context menu The Context menu component opens a menu at the cursor when the user right-clicks its content. It is positioned at the pointer, traps focus while open, supports arrow-key navigation through the menu, and closes on Escape, scroll, or an outside click. Nest a [Menu flyout](./menu/flyout) inside the menu to add submenus. A prediction cone keeps a submenu open while the pointer moves diagonally towards it, and back out to its opener, even when the cursor briefly crosses another item. Set `debug-cone` to visualize that cone. ::: render render=../code/components/context-menu/preview.vue ::: ## Examples ::: example Basic || A basic context menu. example=../code/components/context-menu/basic.vue ::: ::: example With icons || A context menu with icons. example=../code/components/context-menu/with-icons.vue ::: ::: example With submenus || Nest a Menu flyout to add a submenu that opens to the side. example=../code/components/context-menu/with-submenu.vue ::: ::: example Deep submenus || Menu flyouts nest arbitrarily deep. The prediction cone guides the pointer into a submenu and back out to its opener across every level. example=../code/components/context-menu/deep-submenus.vue ::: ::: example Nested formatting || A spreadsheet-style menu mixing several openers with two and three levels of nesting. example=../code/components/context-menu/nested-formatting.vue ::: ::: example Real-world || A Finder-style menu with several submenu openers stacked under each other. example=../code/components/context-menu/finder.vue ::: ::: example With color picker || Embed a full component with a Menu pane. The picker stays interactive while the menu is open. example=../code/components/context-menu/with-color-picker.vue ::: ## Used components * [Menu](./menu/) * [Menu flyout](./menu/flyout) * [Menu pane](./menu/pane) --- --- url: 'https://flux-ui.dev/components/expandable.md' --- # Expandable This component provides a toggleable container for additional content. It consists of a header with a label and a body that holds the expandable content. When the header button is clicked, the body opens or closes to reveal or hide the content. ::: render render=../../code/components/expandable/preview.vue ::: ::: tip Multiple expandables can be grouped together using [Expandable Groups](./group). ::: ::: tip The default header renders an accessible disclosure button with `aria-controls` and `aria-expanded` wired to the body region. When you provide a custom `header` slot, use the `headerId` and `contentId` slot props (also available on the `body` slot) to recreate this relationship on your own trigger element. ::: ## Examples ::: example Basic || The most basic form of an expandable. example=../../code/components/expandable/basic.vue ::: ::: example Pane || Expandables work great with panes. example=../../code/components/expandable/pane.vue ::: ::: example Custom || The header of an expandable can be overwritten with a slot called header. That slot is provided with an isOpen boolean and three functions to control the expandable. example=../../code/components/expandable/custom.vue ::: ## Used components * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/expandable/group.md' --- # Expandable group This component groups multiple [Expandables](../expandable) together, allowing for collective control of their open and close states. It provides mechanisms to register, unregister, and close all expandable items within the group. The first item in an uncontrolled group opens by default. ::: render render=../../code/components/expandable/group/preview.vue ::: ## Examples ::: example Default || An expandable group makes sure that only one expandable is open at ant moment. It closes other expandables when one is opened. example=../../code/components/expandable/group/default.vue ::: ::: example Pane || Grouped expandables are especially nice within a Pane. example=../../code/components/expandable/group/pane.vue ::: --- --- url: 'https://flux-ui.dev/components/menu.md' --- # Menu The menu is the base structure for building menus. It stacks its child elements vertically, which suits side navigations and flyout menus, and provides basic accessibility features. Insert custom content freely; the menu handles keyboard navigation for you. ::: render render=../../code/components/menu/container/preview.vue ::: ## Examples ::: example Basic || A basic menu that consists of a few items. example=../../code/components/menu/container/basic.vue ::: ::: example Pane || Panes have first-class support for menus inside them. Place a menu directly inside a Pane to create a contained menu. example=../../code/components/menu/container/pane.vue ::: --- --- url: 'https://flux-ui.dev/components/menu/collapsible.md' --- # Menu collapsible A menu item that expands to reveal a nested group of sub-items. When Vue Router is available, the collapsible automatically opens if any direct sub-item's `to` or `href` matches the current route. If a `to` or `href` is set on the collapsible itself, clicking the header navigates and opens the group in a single interaction. Without those props, clicking the header simply toggles the open state. ::: render render=../../code/components/menu/collapsible/preview.vue ::: ## Examples ::: example Basic || A collapsible group without its own route. Click the header to toggle. example=../../code/components/menu/collapsible/basic.vue ::: ::: example Navigate || A collapsible with a link on the header. Clicking navigates and opens. example=../../code/components/menu/collapsible/navigate.vue ::: ::: example Controlled || Control the open state from outside with v-model:isOpened. example=../../code/components/menu/collapsible/controlled.vue ::: ## Used components * [Menu item](./item) * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/menu/flyout.md' --- # Menu flyout A menu item that opens a submenu in a flyout next to it, rather than expanding inline like a [Collapsible](./collapsible). Use it inside any [Menu](./), such as a [Context menu](../context-menu), a dropdown, or a plain menu in a pane. Submenus may be nested arbitrarily deep. The flyout opens on hover and on `ArrowRight`, `Enter` or click, and keeps itself within the browser window: when there is no room on the chosen side it flips to the opposite side and is clamped to the viewport. A **prediction cone** keeps the submenu open while the pointer moves diagonally towards it, even when the cursor briefly passes over a sibling item, so reaching a submenu no longer requires a perfectly straight path. A matching return cone does the same on the way back, so heading from the submenu to its opener does not drop the submenu or activate the items in between. The cone can be visualized for debugging with the `debug-cone` prop on the surrounding [Context menu](../context-menu) or [Menu](./). ::: render render=../../code/components/menu/flyout/preview.vue ::: ## Examples ::: example Basic || A menu item that opens a submenu on hover or with the keyboard. example=../../code/components/menu/flyout/basic.vue ::: ::: example Nested || A submenu inside a submenu. There is no depth limit. example=../../code/components/menu/flyout/nested.vue ::: ::: example Stacked || Several submenu openers under each other, like a Format menu in an editor. example=../../code/components/menu/flyout/stacked.vue ::: ## Used components * [Menu](./) * [Menu item](./item) * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/menu/group.md' --- # Menu group This component provides a container for grouping menu items, adjusting its orientation based on the `isHorizontal` prop. When set to horizontal, it applies a specific style; otherwise, it defaults to a vertical layout. ::: render render=../../code/components/menu/group/preview.vue ::: ## Examples ::: example Vertical || Vertical groups are for combining menu items that share context. example=../../code/components/menu/group/vertical.vue ::: ::: example Horizontal || Horizontal groups suit menu items that together form a single state, such as text alignment. example=../../code/components/menu/group/horizontal.vue ::: ::: example Separated || Groups can also be separated using a separator. example=../../code/components/menu/group/separated.vue ::: ::: example Both || Menu's can also have both horizontal and vertical groups in them. example=../../code/components/menu/group/both.vue ::: --- --- url: 'https://flux-ui.dev/components/menu/item.md' --- # Menu item This component is designed to be a flexible menu item that fits into a navigation or action menu. It leverages the properties of buttons and can display icons, images, and commands to suit various needs. You can customize it with different states like active, selected, or highlighted, and it's capable of handling click events. Its versatility makes it easy to integrate into any menu structure, enhancing the user experience with well-defined actions and options. ::: render render=../../code/components/menu/item/preview.vue ::: ## Examples ::: example Basic || A simple menu item with an icon. example=../../code/components/menu/item/basic.vue ::: ::: example Selectable || Menu items can be selectable, mostly used within groups. example=../../code/components/menu/item/selectable.vue ::: ::: example Persistent || Mark items with is-persistent to keep the surrounding menu open on click, useful for toggles and multi-select actions. Items without it (like Done) still close the menu. example=../../code/components/menu/item/persistent.vue ::: ::: example Keybind || Each menu item can have a keybind (command). example=../../code/components/menu/item/keybind.vue ::: ::: example Navigate || A menu item can also just contain an icon at the end. example=../../code/components/menu/item/navigate.vue ::: ::: example Spinner || Loading states can also be applied to menu items to indicate that something is loading. example=../../code/components/menu/item/spinner.vue ::: ## Used components * [Icon](../icon) * [Spinner](../spinner) --- --- url: 'https://flux-ui.dev/components/menu/options.md' --- # Menu options This component provides a container for grouping menu items that behave like options, allowing only one to be selected at a time. Its layout can be adjusted based on the `isHorizontal` prop. When set to horizontal, it applies a specific style; otherwise, it defaults to a vertical layout. Selection is tracked by identity rather than position: each item is matched on its vnode `:key` when it has one, falling back to its index for keyless static lists. Give items an explicit `:key` so the selection survives conditional or reordered items. ::: render render=../../code/components/menu/options/preview.vue ::: ## Examples ::: example Alignment || Horizontal option menus can be used to allow users to select an alignment. example=../../code/components/menu/options/alignment.vue ::: ::: example Option || Vertical option menus can be used to allow the user to switch between different view modes. example=../../code/components/menu/options/option.vue ::: ::: example Inside a flyout || Option menus stay open while selecting, even inside a flyout. Pass :is-persistent="false" if you want the menu to close on selection instead. example=../../code/components/menu/options/persistent.vue ::: ## Used components * [Button](../button) * [Menu group](./group) --- --- url: 'https://flux-ui.dev/components/menu/pane.md' --- # Menu pane A container that lets you drop a full interactive component (a [Color picker](../color/picker), a slider or a small form) into a [Menu](./), a [Menu flyout](./flyout) submenu or a [Context menu](../context-menu). A plain [Menu](./) runs a roving focus zone: arrow keys move between its items and only one item sits in the tab order at a time. Wrapping custom content in a Menu pane opts that subtree out of the focus zone, so the embedded component keeps its own keyboard behavior. Arrow keys drive its sliders and steppers and `Tab` reaches every control. Arrow navigation across the surrounding menu items simply skips over the pane; reach it with `Tab`. Clicking inside a pane never closes the menu, so the embedded component stays usable while the menu is open. ::: render render=../../code/components/menu/pane/preview.vue ::: ## Examples ::: example Color picker || Embed a full color picker in a menu flyout submenu. Drag the saturation field, use the sliders and type into the inputs without the menu interfering. example=../../code/components/menu/pane/color-picker.vue ::: ::: example Slider || A single control such as a slider. Focus it with `Tab`, then the arrow keys adjust the value instead of moving between menu items. example=../../code/components/menu/pane/slider.vue ::: ::: example Range slider || A two-thumb range. Each thumb is its own focus stop and the arrow keys move it without disturbing the menu. example=../../code/components/menu/pane/range.vue ::: ::: example Text area || A multi-line input. Typing, Enter and the arrow keys for the caret all stay inside the field. example=../../code/components/menu/pane/note.vue ::: ::: example Filter || A search field that filters the items below it. Typing (including the arrow keys for the caret) stays inside the input. example=../../code/components/menu/pane/filter.vue ::: ::: example Settings || Several controls in one pane. `Tab` reaches every toggle, and toggling one never closes the menu. example=../../code/components/menu/pane/settings.vue ::: --- --- url: 'https://flux-ui.dev/components/menu/sub-header.md' --- # Menu sub header This component is used for creating subheaders within menus. It can display an optional icon before and after the label, making it easy to visually separate different sections of a menu. The label text is prominently displayed, and the subheader plays a role in organizing menu items into more digestible and structured sections. This component helps enhance the readability and usability of complex menus by providing clear visual breaks. ::: render render=../../code/components/menu/sub-header/preview.vue ::: ## Examples ::: example Grouped example=../../code/components/menu/sub-header/grouped.vue ::: ## Used components * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/menu/title.md' --- # Menu title This component is used to display a title within a menu. The title is highlighted, enhancing the visual structure of the menu by clearly indicating different sections or overall context. This simple yet effective component ensures that users can easily identify the purpose or category of the menu items that follow. ::: render render=../../code/components/menu/title/preview.vue ::: ## Examples ::: example Section example=../../code/components/menu/title/section.vue ::: --- --- url: 'https://flux-ui.dev/components/pagination.md' --- # Pagination A component that displays the pages for paginated content. The component automatically decides which pages to show or not. ::: render render=../../code/components/pagination/preview.vue ::: ::: info Ellipsis behavior Hidden pages are collapsed into a non-interactive ellipsis (`…`), which is hidden from assistive technologies via `aria-hidden`. A gap is only collapsed when at least two pages are hidden; a single hidden page is rendered directly, since an ellipsis would take up the same space as the page it replaces. In compact mode the current page button is labelled for screen readers so its purpose stays clear. ::: ## Examples ::: example Basic || A basic pagination. example=../../code/components/pagination/basic.vue ::: ::: example Compact || A compact pagination. example=../../code/components/pagination/compact.vue ::: ## Used components * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/pagination/bar.md' --- # Pagination bar The pagination bar displays information about the current page of data and allows the user to change how many items are shown per page. ::: render render=../../code/components/pagination/bar/preview.vue ::: ::: tip Empty data sets When `total` is `0` the range readout shows `0` as its lower bound instead of `1`, so an empty result reads as `0–0 of 0` rather than implying a first item that does not exist. ::: ## Examples ::: example Basic || A basic pagination bar. example=../../code/components/pagination/bar/basic.vue ::: ## Used components * [Pagination](../pagination) * [Layout](../layout) * [Spacer](../layout/spacer) * [Form](../form) * [Select](../form/select) --- --- url: 'https://flux-ui.dev/components/segmented-control.md' --- # Segmented control The segmented control lets users choose one option from a small set of segments. Each segment is a [Segmented control item](./item) with a label and/or icon, and the selected segment is highlighted. Use it in navigation, forms, or settings where a compact choice fits. The selected segment is bound through `v-model` and reflects the `value` of the active [Segmented control item](./item). ::: render render=../../code/components/segmented-control/preview.vue ::: ::: tip To switch between content areas based on the selected segment, use [Tabs](../tabs/). ::: ## Examples ::: example Basic || A basic segmented control. example=../../code/components/segmented-control/basic.vue ::: ::: example Icons || A segmented control with icons only. example=../../code/components/segmented-control/icon.vue ::: ::: example With tabs || A segmented control driving the tab bar of [Tabs](../tabs/) to switch content. example=../../code/components/segmented-control/tabs.vue ::: ::: example Sizes || A segmented control in all available sizes. example=../../code/components/segmented-control/sizes.vue ::: ::: example Fill || A segmented control that fills its parent. example=../../code/components/segmented-control/fill.vue ::: ::: example Disabled item || A segmented control with a single disabled segment. example=../../code/components/segmented-control/disabled-item.vue ::: ::: example Disabled || A segmented control disabled in its entirety. example=../../code/components/segmented-control/disabled.vue ::: ## Used components * [Segmented control item](./item) * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/segmented-control/item.md' --- # Segmented control item The segmented control item represents an individual segment within the segmented control. Each item carries a `value`; selecting it updates the segmented control's `v-model` to that value. An item can render an icon, a label, or fully custom content. ::: render render=../../code/components/segmented-control/item/preview.vue ::: ::: warning This component is best used within a [Segmented control](../segmented-control). ::: ## Examples ::: example Basic || A basic segmented control item. example=../../code/components/segmented-control/item/basic.vue ::: ::: example Disabled || A segmented control with a disabled item. example=../../code/components/segmented-control/item/disabled.vue ::: ::: example Icon only || Omit the `label` to render compact, icon-only segments. example=../../code/components/segmented-control/item/icon-only.vue ::: ::: example Labels only || Omit the `icon` to render text-only segments. example=../../code/components/segmented-control/item/labels-only.vue ::: ::: example Custom content || Use the default slot to render custom content such as an icon with a badge. example=../../code/components/segmented-control/item/custom.vue ::: ## Used components * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/stepper.md' --- # Stepper The stepper guides users through a process in clearly numbered steps, showing where they are and what remains. ::: render render=../../code/components/stepper/preview.vue ::: ## Examples ::: example Basic || A basic stepper. example=../../code/components/stepper/basic.vue ::: ::: example Custom steps || Override the `steps` slot to render labelled buttons instead of the default dot indicator. example=../../code/components/stepper/custom-steps.vue ::: ## Used components * [Stepper](../stepper) * [Steps](../stepper/steps) * [Dynamic view](../dynamic-view) --- --- url: 'https://flux-ui.dev/components/stepper/steps.md' --- # Stepper steps The stepper steps component displays the list of steps available in the stepper, showing users where they are in the overall process. It acts as a navigation layer, allowing users to understand their current position and progress while also offering a clear overview of what comes next. ::: render render=../../code/components/stepper/steps/preview.vue ::: ## Examples ::: example Basic || A basic stepper steps. example=../../code/components/stepper/steps/basic.vue ::: ::: example Progress states || The `current` prop drives the active step; completed steps show a check. example=../../code/components/stepper/steps/progress.vue ::: ::: example Two steps || A minimal stepper with only two steps. example=../../code/components/stepper/steps/two-steps.vue ::: ## Used components * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/stepper/step.md' --- # Stepper step The stepper step represents an individual step within the stepper. It contains the content, actions, and guidance needed for that part of the process. Each FluxStepperStep helps users focus on one task at a time, making multi-step workflows feel clear and manageable. ## Snippet ::: code-group ```vue \[StepperStep.vue] ``` ::: ## Usage Each step is placed inside a [Stepper steps](./steps) component. The step's content is only rendered when the corresponding step is active. ```vue

Content for the first step.

Content for the second step.

``` ## Used components * [Stepper](./index) * [Stepper steps](./steps) --- --- url: 'https://flux-ui.dev/components/tab-bar.md' --- # Tab bar The tab bar displays a row of navigation tabs, allowing users to switch between different sections or views within the interface. It groups multiple tab items together in a single bar and provides a consistent, easy-to-scan structure for navigating related content areas. The bar is exposed as a `role="tablist"` and is fully keyboard navigable: ArrowLeft/ArrowUp and ArrowRight/ArrowDown move between tabs (wrapping around the ends), while Home and End jump to the first and last tab. Disabled tabs are skipped, and the overflow scroll arrows are hidden from assistive technologies. A single roving tab stop keeps the bar reachable with Tab: the selected tab is tabbable, or the first enabled tab when none is selected. ::: render render=../../code/components/tab-bar/preview.vue ::: ## Examples ::: example Basic || A basic tab bar. example=../../code/components/tab-bar/basic.vue ::: ::: example Icon and label || A tab bar with both icons and labels. example=../../code/components/tab-bar/icon-label.vue ::: ::: example Pane || A tab bar inside a pane. example=../../code/components/tab-bar/pane.vue ::: ::: example Pills || A tab bar rendered as pills. example=../../code/components/tab-bar/pills.vue ::: ::: example Pills with icon and label || A pills tab bar with both icons and labels. example=../../code/components/tab-bar/pills-icon-label.vue ::: ::: example Pills in pane || A pills tab bar inside a pane. example=../../code/components/tab-bar/pills-pane.vue ::: ## Used components * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/tab-bar/item.md' --- # Tab bar item The tab bar item represents an individual tab within the tab bar. Each item corresponds to a specific content view or section. When selected, it updates the displayed content accordingly, helping users understand where they are and switch between sections effortlessly. ::: render render=../../code/components/tab-bar/item/preview.vue ::: ::: warning This component is best used within a [Tab bar](../tab-bar). ::: ## Examples ::: example Basic || A basic tab bar item. example=../../code/components/tab-bar/item/basic.vue ::: ::: example Pills || A tab bar item rendered as a pill. example=../../code/components/tab-bar/item/pills.vue ::: ::: example Active tab || Mark the selected tab with `is-active`. example=../../code/components/tab-bar/item/active.vue ::: ::: example Disabled tab || A tab bar with a disabled item that cannot be selected. example=../../code/components/tab-bar/item/disabled.vue ::: ::: example Label only || Tab bar items can render just a `label` without an icon. example=../../code/components/tab-bar/item/label-only.vue ::: ::: example Count badge || Show an unread or item count after the label using the `end` slot. example=../../code/components/tab-bar/item/count.vue ::: ::: example Avatar and status || Render an avatar with a status indicator before the label using the `start` slot. example=../../code/components/tab-bar/item/avatar.vue ::: ::: example Validation state || Flag a tab that contains errors. The slot may be filled conditionally. example=../../code/components/tab-bar/item/validation.vue ::: ::: example Start and end slots || Both slots combined in a single tab. example=../../code/components/tab-bar/item/slots.vue ::: ## Used components * [Icon](../icon) --- --- url: 'https://flux-ui.dev/components/tabs.md' --- # Tabs The tabs component organizes content into separate views, showing one at a time. Each tab switches to its matching content area, keeping related content grouped without crowding the interface. ::: render render=../../code/components/tabs/preview.vue ::: ## Examples ::: example Basic || A basic tabs pane. example=../../code/components/tabs/basic.vue ::: ::: example Icons || A tabs pane with only icons. example=../../code/components/tabs/icons.vue ::: ::: example Icon and label || A tabs pane with both icons and labels. example=../../code/components/tabs/icon-label.vue ::: ::: example Pills || A tabs pane with the tab bar rendered as pills. example=../../code/components/tabs/pills.vue ::: ::: example Pills with icons || A pills tabs pane with only icons. example=../../code/components/tabs/pills-icons.vue ::: ::: example Pills with icon and label || A pills tabs pane with both icons and labels. example=../../code/components/tabs/pills-icon-label.vue ::: ## Used components * [Tab bar](../tab-bar) * [Item](../tab-bar/item) --- --- url: 'https://flux-ui.dev/components/tabs/tab.md' --- # Tab A tab represents a single selectable option within a tabs interface. Each tab is labelled to indicate the content it corresponds to, and selecting it updates the view to display the associated content area. ::: render render=../../code/components/tabs/tab/preview.vue ::: ::: warning This component is best used within [Tabs](../tabs). The icon and label props are not rendered without it. ::: ## Examples ::: example Basic || A basic tab. example=../../code/components/tabs/tab/basic.vue ::: --- --- url: 'https://flux-ui.dev/components/data-display.md' --- # Data display The data display components present structured data in a clear, scannable way, from tables and filters to timelines, calendars and tree views. --- --- url: 'https://flux-ui.dev/components/calendar.md' --- # Calendar This component shows a calendar with four different views (month, week, two-days, day). Items can be added to the calendar by filling the default slot with `FluxCalendarItem` instances. ::: render render=../../code/components/calendar/preview.vue ::: ## Snippet ::: code-group ```vue \[Calendar.vue] ``` ::: ## Auto-responsive views When you don't pass a `view` prop, the calendar picks the most appropriate view based on the viewport. On large screens it shows `month`, on medium screens it falls back to `week`, then `two-days` and finally `day` on small viewports. ::: render render=../../code/components/calendar/auto-responsive.vue ::: ::: code-group ```vue \[AutoResponsive.vue] ``` ::: ## Week view A 7-column time-grid with a sticky day-header, an all-day section and a vertically scrollable hour-grid. Use `duration` on items to set their length in minutes. ::: render render=../../code/components/calendar/week-view.vue ::: ::: code-group ```vue \[WeekView.vue] ``` ::: ## Day view The single-day variant of the time-grid. Combine `duration` with `all-day` for a richer day-planning view. ::: render render=../../code/components/calendar/day-view.vue ::: ::: code-group ```vue \[DayView.vue] ``` ::: ## Draggable items Set `draggable` on the calendar to let users move items between day-cells (and time-slots in time-grid views). The calendar is fully controlled. Listen for the `reschedule` event and update your own state. While dragging, hovering the previous/next month buttons advances the view so items can be moved across months. ::: render render=../../code/components/calendar/draggable.vue ::: ::: code-group ```vue \[Draggable.vue] ``` ::: ## Resize In time-grid views, items expose top and bottom drag-handles when the calendar is `draggable`. Listen for the `resize` event to update your `duration` (and optionally `date` for top-handle resizes). ::: render render=../../code/components/calendar/resize.vue ::: ::: code-group ```vue \[Resize.vue] ``` ::: ## Keyboard navigation When `draggable` is enabled, items become focusable. Press Tab to focus an item, then Space or Enter to grab. Use the arrow keys to move it (per day in month, per snap-step or per day in time-grid). Enter drops; Escape cancels. ::: render render=../../code/components/calendar/keyboard.vue ::: ::: code-group ```vue \[Keyboard.vue] ``` ::: ## Plain items An item without custom styling, just text in the slot. Useful for lightweight calendars where the day's events are simply listed. ::: render render=../../code/components/calendar/plain.vue ::: ::: code-group ```vue \[Plain.vue] ``` ::: ## Item with tooltip Wrap your item content in a [Tooltip](../tooltip) component to surface extra detail on hover. ::: render render=../../code/components/calendar/tooltip.vue ::: ::: code-group ```vue \[Tooltip.vue] ``` ::: ## Used components * [Action bar](../action-bar) * [Button](../button) * [Secondary](../button/secondary) * [Group](../button/group) * [Calendar](../calendar) * [Item](../calendar/item) * [Date picker](../date-picker) * [Flyout](../flyout) * [Spinner](../spinner) --- --- url: 'https://flux-ui.dev/components/calendar/item.md' --- # Calendar item This component is used within the [Calendar](../calendar) component to render a single calendar entry. The `default` slot is yours to fill. Render any content (icons, labels, badges, copy) you like. When the parent calendar has `draggable` enabled, items with an `id` can be dragged between day-cells (in month view) or between day-cells and time-slots (in time-grid views). To add a tooltip, wrap your slot content in a [Tooltip](../tooltip) component. ## Snippets ::: code-group ```vue [CalendarItem.vue] ``` ```vue [CalendarItemWithDuration.vue] ``` ```vue [CalendarItemAllDay.vue] ``` ```vue [CalendarItemWithTooltip.vue] ``` ::: --- --- url: 'https://flux-ui.dev/components/comment.md' --- # Comment This component represents a user comment with support for customizable details such as the author's name, avatar, and optional time information. It includes a structured layout with an avatar, header, and message body, allowing additional content to be provided via a slot. Styles can adjust its appearance, such as flipping or differentiating received comments. ::: render render=../code/components/comment/preview.vue ::: ## Examples ::: example Incoming || An incoming comment that is used within a message thread. example=../code/components/comment/incoming.vue ::: ::: example Outgoing || An outgoing comment that is used within a message thread. example=../code/components/comment/outgoing.vue ::: ::: example Typing || An indication that someone is typing a message. example=../code/components/comment/typing.vue ::: ## Used components * [Avatar](./avatar) --- --- url: 'https://flux-ui.dev/components/data-table.md' --- # Data table The data table organizes large sets of data into rows and columns, layering sorting, filtering, pagination, selection, grouping and expandable rows on top of a plain [Table](./table). It is built for server-driven data, so you feed it one page of rows at a time. ::: render render=../code/components/data-table/preview.vue ::: ::: info Server-side pagination The data table does **not** paginate `items` internally. The `items` prop should contain only the rows for the currently active page, fetched from your server or API. The `page` and `per-page` props are used to drive the pagination bar and are exposed through slot bindings so you can display them, but the component never slices or filters the `items` array itself. ::: ::: tip Fast group toggling By default a collapsed group unmounts its rows, so re-expanding a group of rich rows (per-row flyouts, links, indicators) re-mounts all of them. Set `collapse-mode="hide"` to keep the rows mounted and hide them instead, making every toggle instant. Hidden rows are excluded from keyboard navigation and assistive technology, so there is no visible or behavioural change beyond the speed. ::: ## Examples ::: example File manager || A data table that is used for file management. example=../code/components/data-table/file-manager.vue ::: ::: example Paginated || A data table that is split into pages. example=../code/components/data-table/paginated.vue ::: ::: example Custom pagination || A data table whose `pagination` slot renders a compact pager instead of the default bar. example=../code/components/data-table/pagination-slot.vue ::: ::: example Clickable rows || A data table that emits `row-click` per row, while ignoring clicks on the action button inside a cell. Focused rows can be walked with the arrow keys and activated with `Enter`/`Space`. example=../code/components/data-table/clickable.vue ::: ::: example Row colors || A data table that tints rows based on their status. example=../code/components/data-table/row-colors.vue ::: ::: example Selectable rows || A data table where multiple rows can be selected via checkboxes. example=../code/components/data-table/selection.vue ::: ::: example Single selection || A data table where at most one row can be selected. example=../code/components/data-table/selection-single.vue ::: ::: example Selection toolbar || A bar with bulk actions that takes the place of the filter bar while rows are selected. example=../code/components/data-table/selection-toolbar.vue ::: ::: example Sortable columns || A data table whose columns drive a single, coordinated client-side sort. example=../code/components/data-table/sortable.vue ::: ::: example Filtering and search || A data table with a filter bar, client-side filtering, pagination and selection. example=../code/components/data-table/filterable.vue ::: ::: example Rich cells and row actions || A data table with avatars, badges, progress bars and a per-row actions menu. example=../code/components/data-table/rich.vue ::: ::: example Expandable rows || A data table where each row can be expanded to reveal detail content. example=../code/components/data-table/expandable.vue ::: ::: example Single expansion || A data table where opening a row collapses the previously opened one. example=../code/components/data-table/expand-single.vue ::: ::: example Conditional expansion || A data table where only rows with detail content show an expand toggle. example=../code/components/data-table/expand-conditional.vue ::: ::: example Grouped rows || A data table whose rows are grouped under collapsible headers. example=../code/components/data-table/grouped.vue ::: ::: example Static groups || A data table whose rows are grouped under plain, non-collapsible headers. example=../code/components/data-table/grouped-static.vue ::: ::: example Wide table || A wide data table with multiple pinned columns on the left and right edges. example=../code/components/data-table/wide.vue ::: ::: example Pinned with selection || A data table where pinning the first column keeps the selection column pinned alongside it. example=../code/components/data-table/pinned.vue ::: ::: example Column sizing || Headers mixing a fixed width, a min/max range and a shrinking column. example=../code/components/data-table/column-sizing.vue ::: ::: example Numeric columns || Right-aligned numeric columns with sortable numeric and date headers. example=../code/components/data-table/numeric.vue ::: ::: example Summary footer || A footer row that sums the page across spanning cells. example=../code/components/data-table/footer.vue ::: ::: example Fixed-width columns || A weekly timesheet with fixed-width day columns and a total. example=../code/components/data-table/timesheet.vue ::: ::: example Stacked cells || Cells that stack a primary and secondary line of content. example=../code/components/data-table/stacked.vue ::: ::: example Wrapping content || A wrapping subject column whose meta columns stay on a single line. example=../code/components/data-table/wrapping.vue ::: ::: example Consistent height || A partial page that keeps a fixed height with filler rows. example=../code/components/data-table/fill.vue ::: ::: example Sticky header || A long list whose header and bar stick while scrolling. example=../code/components/data-table/sticky.vue ::: ::: example Sticky groups || Grouped rows whose header sticks while scrolling through the groups. example=../code/components/data-table/sticky-groups.vue ::: ::: example Skeleton loading || A data table whose `loading` slot replaces the spinner with skeleton rows. example=../code/components/data-table/skeleton.vue ::: ::: example Empty || A data table that shows a custom message when there is no data. example=../code/components/data-table/empty.vue ::: ## Used components * [Table](./table) * [Actions](./table/actions) * [Cell](./table/cell) * [Group](./table/group) * [Header](./table/header) * [Row](./table/row) --- --- url: 'https://flux-ui.dev/components/description-list.md' --- # Description list The Description list component displays a set of label/value pairs, such as the fields of a record in a detail panel. It renders as a semantic `
` with an optional heading, an optional leading icon per row, and the value aligned to the trailing edge. Values can be plain text, or richer content such as a badge, a copy action, or a link. ::: render render=../../code/components/description-list/preview.vue ::: ::: tip For a single icon and message, use [Info](../info) instead. The description list is meant for multiple label/value pairs. ::: ## Examples ::: example Account || A profile panel with labels, icons, and a status badge. example=../../code/components/description-list/account.vue ::: ::: example Order summary || An order panel with a copy action, a badge, and a stacked address. example=../../code/components/description-list/order.vue ::: ::: example Aligned labels || Values aligned to the leading edge next to a label column, using `label-width`. example=../../code/components/description-list/aligned.vue ::: ::: example Columns || Items laid out as columns separated by dividers, using `direction="horizontal"`. example=../../code/components/description-list/horizontal.vue ::: ## Used components * [Description item](./item) --- --- url: 'https://flux-ui.dev/components/description-list/item.md' --- # Description item The Description item component represents a single label/value pair within a [Description list](./). The label is rendered as a `
` with an optional leading icon, and the value, provided through the default slot, as a `
` aligned to the trailing edge. ::: render render=../../code/components/description-list/item/preview.vue ::: ## Examples ::: example Basic || A description item with an icon and a rich value. example=../../code/components/description-list/item/basic.vue ::: ::: example Multiple pairs || A typical list of several term and value pairs. example=../../code/components/description-list/item/multiple.vue ::: ::: example Stacked || Use `is-stacked` to place the value below the label instead of beside it. example=../../code/components/description-list/item/stacked.vue ::: ::: example Custom label || Use the `label` slot to render custom markup for the term. example=../../code/components/description-list/item/custom-label.vue ::: ## Used components * [Description list](./) --- --- url: 'https://flux-ui.dev/components/filter.md' --- # Filter The filter builds nested filter menus with state management, navigation, and optional reset support. It organizes its content from the slots you provide and animates height changes as users move between views. ::: render render=../../code/components/filter/preview.vue ::: ::: tip Don't make your view too complex. Limit yourself to one filter per view. ::: ::: tip Looking for a toolbar-style filter with a search input? See [Filter bar](./bar). ::: ## Available filters * [Date](./date) * [Date range](./date-range) * [Option](./option) * [Options](./options) * [Range](./range) * [Async option](./async-option) * [Async options](./async-options) ## Common props Every filter component (built-in and custom) accepts the following props in addition to its own: ::: tip Clear vs. reset Clearing a filter removes its key from the state entirely and calls on-clear. Resetting a filter that has a default-value writes that value back and calls on-change; resetting a filter without a default-value behaves like clear and removes the key while calling on-clear. ::: ## Custom filter types Build your own filter component by calling `defineFilter()` on the top level of ` ``` ::: ## Examples ::: example Basic || A basic example of the filter. example=../../code/components/filter/full.vue ::: ::: example Flyout || A filter that pops up when you press on a button. example=../../code/components/filter/flyout.vue ::: ## Used components * [Menu](../menu) * [Group](../menu/group) * [Item](../menu/item) * [Window](../window) --- --- url: 'https://flux-ui.dev/components/filter/bar.md' --- # Filter bar The filter bar combines a search input with dynamic filter buttons into a single toolbar. Active filters are shown as individual buttons with a badge indicating the selected value. When the bar runs out of space, overflow filters collapse into a flyout menu. This component is an alternative to [Filter](./index) and is well suited for use above data tables. ::: render render=../../code/components/filter/bar/preview.vue ::: ::: tip Don't make your view too complex. Limit yourself to one filter bar per view. ::: ## Examples ::: example Basic || A basic filter bar with a search input and filters. example=../../code/components/filter/bar.vue ::: ::: example Start and end slots || Adding custom content before the search input and after the filter button. example=../../code/components/filter/bar/slots.vue ::: ## Used components * [Filter](./index) * [Flyout](../flyout) * [Form](../form) * [Input](../form/input/) * [Button](../button) * [Secondary](../button/secondary) * [Menu](../menu) * [Overflow bar](../overflow-bar) * [Separator](../separator) --- --- url: 'https://flux-ui.dev/components/filter/date.md' --- # Filter date The date filter lets users pick a single date, honoring the configured minimum and maximum. It writes the selection to the filter state automatically. ::: render render=../../code/components/filter/date/preview.vue ::: ::: warning This component can only be used within a [Filter](./index). ::: ## Snippet ::: code-group ```vue \[FilterDate.vue] ``` ::: ## Used components * [Date picker](../date-picker) --- --- url: 'https://flux-ui.dev/components/filter/date-range.md' --- # Filter date range The date range filter lets users pick a start and end date, honoring the configured minimum and maximum. It writes the selection to the filter state automatically. ::: render render=../../code/components/filter/date-range/preview.vue ::: ::: warning This component can only be used within a [Filter](./index). ::: ## Snippet ::: code-group ```vue \[FilterDateRange.vue] ``` ::: ## Used components * [Date picker](../date-picker) --- --- url: 'https://flux-ui.dev/components/filter/option.md' --- # Filter option The option filter lets users pick a single option from a predefined set. It writes the selection to the filter state automatically. ::: render render=../../code/components/filter/option/preview.vue ::: ::: warning This component can only be used within a [Filter](./index). ::: ## Snippet ::: code-group ```vue \[FilterOption.vue] ``` ::: ## Used components * [Form](../form) * [Input](../form/input) * [Menu](../menu) * [Group](../menu/group) * [Item](../menu/item) * [Sub header](../menu/sub-header) --- --- url: 'https://flux-ui.dev/components/filter/options.md' --- # Filter options The options filter lets users pick multiple options from a predefined set. It writes the selection to the filter state automatically. ::: render render=../../code/components/filter/options/preview.vue ::: ::: warning This component can only be used within a [Filter](./index). ::: ## Snippet ::: code-group ```vue \[FilterOptions.vue] ``` ::: ## Used components * [Form](../form) * [Input](../form/input) * [Menu](../menu) * [Group](../menu/group) * [Item](../menu/item) * [Sub header](../menu/sub-header) --- --- url: 'https://flux-ui.dev/components/filter/range.md' --- # Filter range The range filter constrains a data set to a numeric range with a pair of sliders, one for the lower bound and one for the upper. It writes the selected range to the filter state automatically. ::: render render=../../code/components/filter/range/preview.vue ::: ::: warning This component can only be used within a [Filter](./index). ::: ## Snippet ::: code-group ```vue \[FilterRange.vue] ``` ::: ## Used components * [Form](../form) * [Column](../form/column) * [Field](../form/field) * [Slider](../form/slider) --- --- url: 'https://flux-ui.dev/components/filter/async-option.md' --- # Filter option (async) The async option filter lets users pick a single option from a set that is fetched on demand. It writes the selection to the filter state automatically. ::: render render=../../code/components/filter/async-option/preview.vue ::: ::: warning This component can only be used within a [Filter](./index). ::: ## Snippet ::: code-group ```vue \[FilterAsyncOption.vue] ``` ::: ## Used components * [Form](../form) * [Input](../form/input) * [Menu](../menu) * [Group](../menu/group) * [Item](../menu/item) * [Sub header](../menu/sub-header) --- --- url: 'https://flux-ui.dev/components/filter/async-options.md' --- # Filter options (async) The async options filter lets users pick multiple options from a set that is fetched on demand. It writes the selection to the filter state automatically. ::: render render=../../code/components/filter/async-options/preview.vue ::: ::: warning This component can only be used within a [Filter](./index). ::: ## Snippet ::: code-group ```vue \[FilterAsyncOptions.vue] ``` ::: ## Used components * [Form](../form) * [Input](../form/input) * [Menu](../menu) * [Group](../menu/group) * [Item](../menu/item) * [Sub header](../menu/sub-header) --- --- url: 'https://flux-ui.dev/components/kanban.md' --- # Kanban A kanban board for organizing items across draggable columns. Items can be moved between columns and reordered within a column using drag and drop, or with the keyboard. The component is fully controlled. The parent is responsible for updating the data after a `move` event. ::: render render=../../code/components/kanban/preview.vue ::: ::: tip Keyboard support Tab to an item, press Space or Enter to grab it, use the arrow keys to move, Enter/Space to drop and Escape to cancel. When `reorderable-columns` is enabled, Tab to a column header and use ←/→ to move the column left or right. ::: ## Move event The `move` event contains everything needed to update the data: ## Examples ::: example Basic || A task board with draggable items. example=../../code/components/kanban/basic.vue ::: ::: example Custom item || Using the default slot to render rich item content. example=../../code/components/kanban/custom-item.vue ::: ::: example Disabled || A read-only board. Drag-and-drop is disabled. example=../../code/components/kanban/disabled.vue ::: ::: example Validation || Use `can-move` to reject specific drops. example=../../code/components/kanban/validation.vue ::: ::: example Reorderable columns || Drag a column header (or focus it and press the left/right arrow keys) to change column order. example=../../code/components/kanban/reorder-columns.vue ::: ## Used components * [Column](./column) * [Item](./item) * [Pane](../pane) --- --- url: 'https://flux-ui.dev/components/kanban/column.md' --- # Kanban column A single column inside a [`FluxKanban`](./) board. Each column has a unique `column-id` that is referenced by its child items and included in the `move` event when an item is dropped on it. The header shows the `label`, an optional `icon` and a `count` badge, and can be extended with the `actions` slot for things like a quick-add button. Use the `empty` slot for an empty-state message and the `footer` slot for inline actions like adding a new item. ::: render render=../../code/components/kanban/column/preview.vue ::: ## Examples ::: example Basic || A column with a label and a couple of items. example=../../code/components/kanban/column/basic.vue ::: ::: example Actions || Adding an action button to the column header via the `actions` slot. example=../../code/components/kanban/column/actions.vue ::: ::: example Header || Adding an `icon` and a `count` badge to the column header. example=../../code/components/kanban/column/header.vue ::: ::: example Empty state || Showing a message in the `empty` slot when no items are present. example=../../code/components/kanban/column/empty.vue ::: ::: example Footer || An inline "Add item" button rendered through the `footer` slot. example=../../code/components/kanban/column/footer.vue ::: ## Used components * [Item](./item) * [Kanban](./) --- --- url: 'https://flux-ui.dev/components/kanban/item.md' --- # Kanban item A draggable item inside a [`FluxKanbanColumn`](./column). The `item-id` uniquely identifies the item and the `column-id` must match the parent column. The kanban board uses both to compute drop targets and to populate the `move` event. The component itself is intentionally unstyled. It only adds the interaction layer (drag handle, focus ring, drop indicator). The visual surface (padding, background, border, shadows) is up to you. Render any markup inside the default slot; the examples below all wrap their content in a `
` with a ` ``` ::: --- --- url: 'https://flux-ui.dev/components/transitions/route.md' --- # Route ::: render render=../../code/components/transitions/route/preview.vue ::: ## Snippet ::: code-group ```vue \[FluxRouteTransition.vue] ``` ::: --- --- url: 'https://flux-ui.dev/components/transitions/slide-over.md' --- # Slide over ::: render render=../../code/components/transitions/slide-over/preview.vue ::: ## Snippet ::: code-group ```vue \[FluxSlideOverTransition.vue] ``` ::: --- --- url: 'https://flux-ui.dev/components/transitions/tooltip.md' --- # Tooltip ::: render render=../../code/components/transitions/tooltip/preview.vue ::: ## Snippet ::: code-group ```vue \[FluxTooltipTransition.vue] ``` ::: --- --- url: 'https://flux-ui.dev/components/transitions/vertical-window.md' --- # Vertical window ::: render render=../../code/components/transitions/vertical-window/preview.vue ::: ## Snippet ::: code-group ```vue \[FluxVerticalWindowTransition.vue] ``` ::: --- --- url: 'https://flux-ui.dev/components/transitions/window.md' --- # Window ::: render render=../../code/components/transitions/window/preview.vue ::: ## Snippet ::: code-group ```vue \[FluxWindowTransition.vue] ``` ::: --- --- url: 'https://flux-ui.dev/flow.md' --- # Flux Flow Flux Flow is a collection of declarative building blocks for displaying node based flows: automations, pipelines, decision trees and agent workflows. You compose a flow from plain Vue markup, positioning cards on a pannable canvas and wiring them together with connectors, without reaching for a heavyweight graph library. The toolkit is display oriented. A full editor (dragging nodes, drawing connections) is intentionally out of scope, but the primitives are shaped so an editor can be layered on top later. ::: render render=../code/flow/components/flow/preview.vue ::: ## Highlights * **Declarative.** Write nodes and connectors as Vue markup; connectors reference nodes by id, so cards stay free of wiring props. * **Opinionated cards.** A base `FluxFlowCard` plus `Trigger`, `Condition` and `Action` variants give you a Flux styled node surface in a single line, always headed by its type icon. * **Small nodes too.** A `FluxFlowPill` heads a flow with a single named trigger, a `FluxFlowTerminal` opens and closes it, a `FluxFlowStep` marks the steps running down its trunk, a `FluxFlowJunction` knots lines together and a `FluxFlowNote` annotates the canvas. * **Named branches.** A `FluxFlowPort` marks a point inside a card, so the branches of a condition leave it at the outcome they belong to, and a `FluxFlowGate` says out loud whether they meet on `and`, `or` or `xor`. * **Layout that is not yours to do by hand.** A `FluxFlowChain` places a run of steps and wires it up, a `FluxFlowGraph` does the same for a flow that forks and merges, `useFlowLayout` turns a branching graph into coordinates, and a `FluxFlowGroup` or a `FluxFlowLane` frames the part of the canvas that belongs together. * **Runnable.** Connectors accept a `progress-color` and `progress-value`, so you can visualize a flow while it runs. * **Read only viewport.** Drag to pan, `ctrl`/`cmd` + scroll to zoom, and the canvas fits its content on mount. * **Controls that stay put.** A `FluxFlowPanel` pins anything to a corner of the viewport, `FluxFlowControls` puts the zoom and fullscreen buttons there, and a `FluxFlowMinimap` maps the whole flow with the viewport drawn on it. Head straight for [Examples](./examples) to see complete flows, or start with [Flow](./components/flow) for the canvas itself. --- --- url: 'https://flux-ui.dev/flow/introduction/installation.md' --- # Installation To start using Flux Flow in your Vue application, you'll need to add it to your project alongside `@flux-ui/components`, which provides the shared primitives (icons, tags, badges) that the flow cards build on. ## Step 1 Open your project's root directory in your terminal and run the following command: ::: code-group ```shell [bun] bun add @flux-ui/flow @flux-ui/components ``` ```shell [pnpm] pnpm install @flux-ui/flow @flux-ui/components ``` ```shell [yarn] yarn add @flux-ui/flow @flux-ui/components ``` ```shell [npm] npm install @flux-ui/flow @flux-ui/components ``` ::: ## Step 2 Once the installation is complete, add the following lines to your `main.ts` file: ```ts [main.ts] import '@flux-ui/flow/style.css' import '@flux-ui/components/style.css' ``` ## Step 3 Make sure the icons used by your flow cards are registered with Font Awesome, then import the components you want to use: ```vue [Flow.vue] ``` ::: tip By default `FluxFlow` sizes its own height to its content, so it drops inline without a wrapper. Add `interactive` for a fixed-size, pannable canvas instead (give that a sized parent). ::: --- --- url: 'https://flux-ui.dev/flow/components/flow.md' --- # Flow `FluxFlow` is the root of a flow: a shared coordinate space that connectors use to route between nodes. By default it lays its content out naturally, sizes its own height, and scrolls horizontally when the content is wider than its container, so it drops inline without a fixed-height wrapper. Add `interactive` to opt into a pannable and zoomable viewport that fills its container instead: drag or scroll with two fingers to pan, and pinch or hold `ctrl`/`cmd` while scrolling to zoom towards the cursor. ::: render render=../../code/flow/components/flow/preview.vue ::: ::: tip Everything inside a flow, both `FluxFlowNode` and `FluxFlowConnection`, is written declaratively. Connectors reference nodes by id, so cards stay free of wiring props. ::: ## Examples ::: example Branching || A condition that fans out to two labeled branches. Branching is just more connectors, each referencing a node by id. example=../../code/flow/components/flow/branching.vue ::: ::: example Axis || Two branches sitting further apart than the row below them is deep. Without `axis` each connector would take the shorter way out, leaving the card sideways and crossing back over it; naming the axis keeps every line running with the flow. example=../../code/flow/components/flow/axis.vue ::: ::: example Background || Opt into a `dots` or `grid` backdrop with the `background` prop; it is transparent by default. example=../../code/flow/components/flow/background.vue ::: ::: example Interactive || With `interactive` the flow fills its container as a pannable, zoomable canvas, starting at 100% from the top of the flow. Drag or scroll with two fingers to pan, and pinch or hold `ctrl`/`cmd` while scrolling to zoom. example=../../code/flow/components/flow/interactive.vue ::: ::: example Start point || Point `start` at a node id to open the interactive viewport centered on that card instead of the top of the flow. example=../../code/flow/components/flow/start.vue ::: ::: tip On an interactive canvas, controls inside a card (a toggle, a button, a link, a text field) keep working: a press that starts on one never begins a pan. Add `data-nopan` to any other element that should grab the pointer for itself instead of panning the canvas. ::: ::: tip An interactive canvas is reachable with the keyboard: tab to it, then pan with the arrow keys (hold `shift` to cover three times the ground), zoom with `+` and `-`, and press `0` to fit the whole flow in view. A field or a button inside a card keeps every key it is given. ::: ::: tip An interactive canvas pans up to 300px past the viewport and then stops, so it always has room to move, even when the flow is smaller than its container. A two-finger scroll that runs into that edge hands the page its scroll back, so a flow embedded halfway down a page never traps it. ::: For flows built out in full, from routing rules to a running deploy pipeline, see [Examples](../examples). ## Used components * [Node](./node) * [Connection](./connection) * [Card](./card) * [Controls](./controls) * [Minimap](./minimap) --- --- url: 'https://flux-ui.dev/flow/components/node.md' --- # Node `FluxFlowNode` positions a piece of content on the flow canvas. Give it a unique `id` and an `x` / `y` position in flow coordinates; the node measures its rendered size and registers it with the flow, so connectors can anchor to its edges. A node renders whatever you place in its default slot. In practice that is a [Card](./card), but any markup works. A card and a pill each mark their icon with a `data-flow-anchor` attribute, which is what a connector with `from-align="start"` or `to-align="start"` lands on. Put the attribute on an element of your own to give custom node content the same anchor; without one, a `start` connector falls back to 30px from the corner. ::: render render=../../code/flow/components/node/preview.vue ::: ::: tip Connectors reference a node by its `id`, never through props on the node or the card, so the wiring of a flow stays in one place: the connectors. ::: ## Used components * [Flow](./flow) * [Card](./card) --- --- url: 'https://flux-ui.dev/flow/components/chain.md' --- # Chain `FluxFlowChain` positions a run of nodes and wires them together. Give it a starting point and it hands every [Node](./node) inside it a position, so a straight sequence of steps no longer needs a coordinate per card. A link keeps its own `id`, so connectors from outside the chain reference it exactly as they always have. ::: render render=../../code/flow/components/chain/preview.vue ::: ::: tip Absolute `x` and `y` on a node stay the source of truth for positions. A chain only fills them in for the nodes it holds; give a node its own `x` and `y` and it keeps them, stepping out of the layout while staying in the markup. ::: ## Examples ::: example Mixed sizes || A terminal, a pill and a card are all different widths. With `align="center"` their middles land on one line, so the connectors run dead straight through the whole run. example=../../code/flow/components/chain/mixed.vue ::: ::: example Horizontal || Set `direction="horizontal"` to run the chain from left to right. Links line up on their middles across the run, the same way they do vertically. example=../../code/flow/components/chain/horizontal.vue ::: ::: example Your own connector || A `FluxFlowConnection` written between two links replaces the automatic one, so a labelled or colored connector never doubles up with a plain one. A side branch stays outside the chain and references the link by id. example=../../code/flow/components/chain/branch.vue ::: ::: example Labelled connectors || A connector that carries a label or an icon gets a wider segment, so the badge sits clear of both cards with a stretch of line on either side. Tune it with `label-gap` when your labels run long. example=../../code/flow/components/chain/labelled.vue ::: ::: tip A chain only claims the pairs it can see: a connector between two links has to sit inside the chain, in the same direction, to replace the automatic one. Set `:auto-connect="false"` to draw every connector yourself. ::: ## Used components * [Flow](./flow) * [Node](./node) * [Connection](./connection) * [Card](./card) ## See also * [useFlowLayout](../composables/useFlowLayout) for a graph that branches instead of running in a line. --- --- url: 'https://flux-ui.dev/flow/components/graph.md' --- # Graph `FluxFlowGraph` places a branching flow for you. It reads the connectors written inside it as the graph they describe, lays the nodes out in layers, and hands each one its position, so a [Node](./node) inside a graph carries no `x` and no `y`. It is the branching counterpart of a [Chain](./chain): a chain places a straight run, a graph places anything that forks and merges. The layout runs on the sizes the cards measured for themselves, so a 300px card and a pill in the same layer still line up. Two shapes are on offer. By default the graph stacks in layers, which suits a pipeline: everything at the same depth sits on the same row. Name a `trunk` instead and those ids run straight down a column while everything hanging off them walks out to the right, which suits a numbered rule list, where each rule should stay with its own fan-out rather than share a row with the next rule. ::: render render=../../code/flow/components/graph/preview.vue ::: ::: tip Name the axis on the surrounding [Flow](./flow) that matches the graph's `direction`, so every connector runs with the flow instead of taking the shorter way out. ::: ::: tip A graph reads its connectors before it lays anything out, so it also knows whether any of them carries a badge and leaves the layers further apart when one does, exactly as a [Chain](./chain) does for its run. Set `layer-gap` yourself to take that over. ::: ::: tip A trunk places the nodes; the connectors are still yours. Give the ones that run sideways into a card a `to-align="start"` so they land on its icon rather than halfway down it, and give a branch a `from-side="bottom"` so it drops out of the card above rather than leaving its right edge and doubling back. ::: ::: tip A node lands one layer past its furthest source, and every layer is centred against the widest one. An edge that would close a cycle is cut rather than followed, so a graph that is not a tree still lays out; give such a connector its own `from-side` and `to-side` to send it around the diagram. ::: ## Examples ::: example Horizontal || Set `direction` to `horizontal` to stack the layers left to right, and match it with `axis` on the flow. example=../../code/flow/components/graph/horizontal.vue ::: ::: example Fanning out and merging || Three checks run off one trigger and come back together on the step that needs all of them. The layer is laid out on what each node actually measures, so pills of three different widths sit evenly spaced and the layers above and below stay centred on them. example=../../code/flow/components/graph/branches.vue ::: ::: example Running back || A connector that would close a cycle is cut out of the layout rather than followed, so the three steps still stack in order. Give it a `from-side` and a `to-side` on the off axis and it loops around the diagram instead of cutting back across it. example=../../code/flow/components/graph/cycle.vue ::: ::: example Keeping a node in place || A node that carries its own `x` and `y` is left where it is and takes no part in the layout, which is how an annotation stands beside a flow without pushing a layer aside. example=../../code/flow/components/graph/pinned.vue ::: ::: example A running pipeline || The [running pipeline](../examples) from the examples, with every coordinate taken out. Each stage still swaps its icon and tint off one clock, spins while it runs and carries a `FluxBadge` naming its state, and the connectors still fill towards the stage they feed; the graph is what decides where the pill and the three cards land. The stages are written with a `v-for`, and the graph reads straight through it. example=../../code/flow/components/graph/pipeline.vue ::: ::: example Routing rules || The [routing rules](../examples) from the examples, with every coordinate taken out. Naming the trigger and the two steps as the `trunk` runs them straight down a column and walks each rule out to the right, so a rule stays with its own fan-out. Every rule is as tall as what it does, and the next step clears the branch above it. example=../../code/flow/components/graph/routing.vue ::: ## Used components * [Flow](./flow) * [Node](./node) * [Connection](./connection) * [Card](./card) --- --- url: 'https://flux-ui.dev/flow/components/connection.md' --- # Connection `FluxFlowConnection` draws a line between two nodes. It references them by `from` and `to`, resolves their positions from the flow, and routes a path between the nearest edges. Because connectors are declared separately from the nodes, all of a flow's wiring lives in one place. By default the connector picks the most natural pair of sides based on where the nodes sit: stacked nodes connect bottom to top, side by side nodes connect right to left. Override `from-side` / `to-side` when you need an explicit route, for example the two branches out of a condition. Both branches then leave the same edge in the same spot; `from-align` / `to-align` move either end to the start or the end of its side to pull them apart, aligned on the icon of the node they touch. For a branch that belongs to something written inside the node, a [Port](./port) is the sharper tool: `from-port` / `to-port` land the connector on the row that names the outcome. A connector may also point at the node it left. Give `from` and `to` the same id and it loops out of one side and back into that same side, which is how a retry says it runs the step again. Name both `from-side` and `to-side` and the loop routes around the node from the one to the other instead. ::: render render=../../code/flow/components/connection/preview.vue ::: ## Examples ::: example Types || Four connector shapes: `smoothstep` (the default, orthogonal with rounded corners), `step` (the same route with sharp corners), `bezier` and `straight`. example=../../code/flow/components/connection/types.vue ::: ::: example Progress || A connector with a `progress-value` fills from the source towards the target, which is useful for visualizing a running flow. The fill animates as the value changes and respects reduced motion. example=../../code/flow/components/connection/progress.vue ::: ::: example Colors || Give a connector a `color`, a FluxColor or any CSS color, to categorize it. example=../../code/flow/components/connection/colors.vue ::: ::: example Explicit sides || Override `from-side` and `to-side` to route a connector out of a specific edge, for example the two branches of a condition. example=../../code/flow/components/connection/sides.vue ::: ::: example Loop || Point `from` and `to` at the same node and the connector loops out of one side and back into it. It uses the side a connector running against the flow would take, so a retry and a step back read alike; `from-side` moves it elsewhere. example=../../code/flow/components/connection/loop.vue ::: ::: example Loop between two sides || Name both `from-side` and `to-side` and the loop travels from the one to the other: two adjacent sides turn a corner, two opposite ones wrap the node along the axis they do not use. example=../../code/flow/components/connection/loop-sides.vue ::: ::: example Alignment || A side is not one point: `from-align` and `to-align` move a connector to the `start` or `end` of the side it uses, which pulls two branches out of the same edge apart. `start` lands on the node's own icon, wherever that sits, so a card and a pill each anchor on their own; `end` mirrors that margin to the far corner. A node too narrow for the margin keeps its connector centered. example=../../code/flow/components/connection/alignment.vue ::: ::: example Label placement || A badge rides the middle of the connector. On a connector that bends that middle can land on a bend, or on the leg two branches share, so `label-placement` moves it to the leg leaving the source or the leg entering the target instead. example=../../code/flow/components/connection/label-placement.vue ::: ::: example Icons || An `icon` next to a `label` rides along in the badge. An `icon` on its own drops the badge and stands on the line itself, which keeps a connector that only needs a symbol light. Both break the line the same way, and both follow the connector's `color`. example=../../code/flow/components/connection/icons.vue ::: ::: example Line styles || Connectors are solid by default; set `dashed` or `dotted` for other styles. A connector leaves its source with a port dot and reaches its target with an arrow head; `marker-start` and `marker-end` swap either for the other shape, or drop it entirely. example=../../code/flow/components/connection/dashed.vue ::: ::: example Animated || Add `animated` to a dashed or dotted connector to travel its pattern towards the target, which reads as work in flight. It respects reduced motion. example=../../code/flow/components/connection/animated.vue ::: ::: example Markers || Both ends carry their own marker. Give a two-way connector a head on each end, or strip them both for a bare line. example=../../code/flow/components/connection/markers.vue ::: ::: example Marker shapes || Six shapes to end a connector with. `chevron` and `arrow` point at the target; `dot`, `diamond` and `square` read as ports; `bar` caps the line off. example=../../code/flow/components/connection/marker-shapes.vue ::: ## Waypoints A connector routes itself, which is what you want until it runs straight over the card between its two ends. Give it `waypoints` and it runs through the points you name instead. They are plain flow coordinates, the same space as the `x` / `y` of a node, so a route is written where you can read it off the canvas. Every shape honours them: `straight` becomes a polyline, `smoothstep` rounds each corner the way it rounds its own, `step` turns those same corners sharply, and `bezier` becomes a single smooth curve through the points. The label rides the middle of the whole route, and both endpoints still leave and reach their node along the side they use. ::: example Three shapes, one detour || The same two waypoints in all three shapes. The endpoints are unaffected: waypoints only shape the run between them, and the label rides the middle of that run. example=../../code/flow/components/connection/waypoints.vue ::: ::: tip The canvas sizes itself to the nodes it holds, not to the connectors. Keep waypoints inside that area, or give the [Flow](./flow) enough `padding` to cover the detour. ::: ## Used components * [Flow](./flow) * [Node](./node) * [Port](./port) --- --- url: 'https://flux-ui.dev/flow/components/port.md' --- # Port `FluxFlowPort` marks a named point inside a [Node](./node). Put one next to the row it belongs to and reference it from a connector with `from-port` or `to-port`: the connector lands on the node's edge at the height of that row, instead of on the node's icon. That turns a condition card into a real branching point. Every outcome gets its own row and its own port, so the two branches leave the card where their outcome is written rather than both leaving from the same corner. A port renders nothing and takes no space of its own: it is a zero sized marker riding the middle of the row it sits in, so adding one never moves the content around it. Only the connector shows where it is. ::: render render=../../code/flow/components/port/preview.vue ::: ::: tip The port fixes where along the side the connector lands, `side` fixes which edge. A connector that names a port therefore ignores `from-align` / `to-align`, and a `from-port` that no port answers to falls back to the node's own anchor. ::: ## Examples ::: example Named branches || Every outcome of a condition gets a row and a port, so each branch leaves the card at its own answer. example=../../code/flow/components/port/branches.vue ::: ::: example Sides || Leave `side` out and the port takes the edge it sits closest to, which is the right one for a port at the end of a row. Name a `side` for the rest, for example a port in a footer that should leave through the bottom of the card. example=../../code/flow/components/port/sides.vue ::: ## Used components * [Flow](./flow) * [Node](./node) * [Connection](./connection) --- --- url: 'https://flux-ui.dev/flow/components/card.md' --- # Card `FluxFlowCard` is the node surface: a header carrying the type icon and title, a body and an optional footer. It is a plain element, so it renders inside a [Node](./node) or on its own. A card always shows an icon, so every node on the canvas reads as a type at a glance. Each variant brings its own icon, tint and type name; `icon`, `color` and `label` override them. ::: render render=../../code/flow/components/card/preview.vue ::: ## Variants `FluxFlowTriggerCard`, `FluxFlowConditionCard` and `FluxFlowActionCard` are thin wrappers around `FluxFlowCard` that preset the three common automation node types. Each default is overridable with the `label`, `icon` and `color` props. * **`FluxFlowTriggerCard`** — type "Trigger", icon `bolt`, color `info`. * **`FluxFlowConditionCard`** — type "Condition", icon `code-branch`, color `warning`. * **`FluxFlowActionCard`** — type "Action", icon `play`, color `primary`. ::: example Variants || The three node variants. Override `label`, `icon` and `color` to fit your own node types. example=../../code/flow/components/card/variants.vue ::: ::: example Colors || The badge accepts any FluxColor, so you can style a card for any kind of node. example=../../code/flow/components/card/colors.vue ::: ## Rich content The card body is a plain vertical stack, so you are not limited to text. Drop in any component from Flux or Flux Statistics: a [`FluxDescriptionList`](../../components/description-list/) for compact key/value data, a `FluxStatisticsLegend` for a color coded breakdown, a chart, badges, anything you need. ::: example Rich content || A card mixing plain text, a FluxDescriptionList and a FluxStatisticsLegend. example=../../code/flow/components/card/content.vue ::: ::: example Header || The `header` slot fills the trailing end of the header, beside the title. Keep it to one small thing that qualifies the node; anything larger belongs in the body or the footer. example=../../code/flow/components/card/header.vue ::: ## Interactive content Nothing about the body is read only. Because it is plain markup, interactive controls, buttons and animated values work exactly as they would anywhere else, so a card can double as a small control surface for its node. ::: example Toggle || A FluxToggle drives the node's state; the badge and accent border follow it. example=../../code/flow/components/card/toggle.vue ::: ::: example Approval || A FluxAvatar identifies the reviewer and a FluxSecondaryButton in the footer resolves the step. example=../../code/flow/components/card/approval.vue ::: ::: example Live progress || A FluxStatisticsMeter reflects a running job by animating its value while the card stays active. example=../../code/flow/components/card/progress.vue ::: ::: example Loading || Set `isLoading` to swap the type icon for a spinner in the same tinted tile, so a running step reads as busy without moving anything on the canvas. example=../../code/flow/components/card/loading.vue ::: ## Used components * [Flow](./flow) * [Node](./node) --- --- url: 'https://flux-ui.dev/flow/components/pill.md' --- # Pill `FluxFlowPill` is a compact node: a tinted icon and a label on a raised pill. Where a [Card](./card) describes a step in full, a pill names one, which makes it a natural head for a flow, the trigger that everything below hangs off. ::: render render=../../code/flow/components/pill/preview.vue ::: ## Examples ::: example In a flow || A pill starts the flow and connects to the rest of the canvas like any other node. example=../../code/flow/components/pill/flow.vue ::: ::: example Loading || Set `isLoading` to swap the leading icon for a spinner in the same tinted tile. A chain of pills walks itself: the running stage spins, finished ones flip to a check. example=../../code/flow/components/pill/loading.vue ::: ## Used components * [Flow](./flow) * [Node](./node) --- --- url: 'https://flux-ui.dev/flow/components/step.md' --- # Step `FluxFlowStep` is a small marker that names a step. Place it in its own [Node](./node) and wire it up like any other node, so the trunk of a flow runs straight through it while each step branches off to the side. A single character keeps the marker square. Give it a word and it widens to fit, which suits a flow whose steps are named rather than numbered. ::: render render=../../code/flow/components/step/preview.vue ::: ## Examples ::: example Numbered steps || The trunk runs from marker to marker; every marker points at the step it numbers. example=../../code/flow/components/step/flow.vue ::: ::: example Values || Digits, letters and words all sit in the same marker. example=../../code/flow/components/step/values.vue ::: ## Used components * [Flow](./flow) * [Node](./node) --- --- url: 'https://flux-ui.dev/flow/components/terminal.md' --- # Terminal `FluxFlowTerminal` is the start and the end of a flow: the capsule a classic flowchart opens and closes with. Place it in its own [Node](./node) and connect it like any other node. Where a [Pill](./pill) names a step on a raised surface, a terminal is one solid tinted capsule, so an endpoint never reads as another step in the chain. ::: render render=../../code/flow/components/terminal/preview.vue ::: ::: tip An endpoint has nothing before or after it, so drop the marker on that side of its connector: `marker-start="none"` on the line leaving a start, `marker-end="none"` on the line reaching an end. ::: ## Examples ::: example In a flow || A start terminal heads the flow and an end terminal closes it, with the steps in between. example=../../code/flow/components/terminal/flow.vue ::: ::: example Colors || A terminal accepts any FluxColor, which is enough to tell a clean finish from a failed one. example=../../code/flow/components/terminal/colors.vue ::: ## Used components * [Flow](./flow) * [Node](./node) --- --- url: 'https://flux-ui.dev/flow/components/junction.md' --- # Junction `FluxFlowJunction` is the knot in a flow: the point where several lines meet, or where one line splits into many. Place it in its own [Node](./node) and wire it up like any other node, so three connectors reaching it and one leaving it read as a single merge instead of three lines crossing. It is a connection point, not a step, so it carries no label. A [Step](./step) numbers a stage of the flow; a junction only says the wiring comes together here. ::: render render=../../code/flow/components/junction/preview.vue ::: ## Examples ::: example Merging sources || Three sources land on one junction, and a single connector carries them into the step that consumes them. Dropping the marker on the connectors that meet keeps the junction itself the only shape at that point. example=../../code/flow/components/junction/flow.vue ::: ## Used components * [Flow](./flow) * [Node](./node) --- --- url: 'https://flux-ui.dev/flow/components/gate.md' --- # Gate `FluxFlowGate` is the diamond of a flow: the point where several lines have to agree, or where exactly one of many branches is taken. It says out loud what a [Junction](./junction) leaves implicit, which is why it carries its rule (`and`, `or` or `xor`) in the shape itself. Place it in its own [Node](./node) and wire it up like any other node. Its four points sit on the sides a connector attaches to, so lines land on the diamond rather than next to it. ::: render render=../../code/flow/components/gate/preview.vue ::: ::: tip Reach for a [Junction](./junction) when lines simply come together, and for a gate when the way they come together is part of the flow. ::: ## Examples ::: example One branch only || An `xor` gate splits a payment into the two routes it can take. The branches leave through the top and bottom points of the diamond, so neither line has to share a corner with the other. Dropping the marker on the line that arrives keeps the diamond the only shape at that point. example=../../code/flow/components/gate/flow.vue ::: ::: example Any one of them || An `or` gate lets three conditions feed the same action. Two of them land on the top and bottom points and the third runs straight into the left one, so the gate takes three lines without any of them crossing. example=../../code/flow/components/gate/any-of.vue ::: ::: example Gates in sequence || Both conditions have to hold before an order ships, and only then does the shipping method split in two. A gate can hand off to another gate directly, with no card in between. example=../../code/flow/components/gate/chained.vue ::: ::: example Without a tint || Left without a `color`, the diamond is drawn in the same gray as a plain connector. Use it when the gate is only wiring and the steps around it carry the emphasis. example=../../code/flow/components/gate/plain.vue ::: ## Used components * [Flow](./flow) * [Node](./node) * [Card](./card) * [Connection](./connection) * [Pill](./pill) --- --- url: 'https://flux-ui.dev/flow/components/group.md' --- # Group `FluxFlowGroup` draws a labelled frame behind a set of nodes: a retry block, a stage of a pipeline, the part of a flow that runs on one machine. It names the nodes it encloses by id and measures the frame from them, so it follows along when they move. A group is a backdrop, not a node. It renders behind every card on the canvas, never takes a pointer, and nothing anchors a connector to it. ::: render render=../../code/flow/components/group/preview.vue ::: ::: tip An id that matches no node is skipped without a word, so a group survives a card that is only rendered under a condition. ::: ## Examples ::: example Two stages || A frame per stage, each in its own tint. The frames grow with the cards inside them, so a chain that gains a step keeps its group. example=../../code/flow/components/group/flow.vue ::: ## Used components * [Flow](./flow) * [Node](./node) * [Chain](./chain) * [Card](./card) --- --- url: 'https://flux-ui.dev/flow/components/lane.md' --- # Lane `FluxFlowLane` is the swimlane of a flow: a band with a titled gutter that says who owns the part of the canvas standing on it. Client and server, the two teams a handover runs between, the machine a stage runs on. A lane is a backdrop and nothing more. It never positions its content: the nodes keep their own absolute `x` and `y`, and the lane is the strip they happen to stand on. ::: render render=../../code/flow/components/lane/preview.vue ::: ::: tip The pair of props you give picks the axis: `y` and `height` make a row, `x` and `width` make a column. The other axis is not yours to set, since a lane always spans the whole flow. ::: ## Examples ::: example Columns || `x` and `width` turn the band on its side, so a handover between two teams reads left to right with the title above each column. The steps inside a column are placed by a [Chain](./chain), which lines up pills of different widths that a lane would not. example=../../code/flow/components/lane/columns.vue ::: ## Used components * [Flow](./flow) * [Node](./node) * [Card](./card) --- --- url: 'https://flux-ui.dev/flow/components/note.md' --- # Note `FluxFlowNote` is an annotation on the canvas: the remark that explains why a step is there, or what the person reading the flow has to know about it. A note is a full node rather than a decoration, so it gets an `id` through its [Node](./node) like everything else and you hang it off the step it belongs to with a connector. A dashed line without markers reads as a remark rather than as a step in the flow. ::: render render=../../code/flow/components/note/preview.vue ::: ## Examples ::: example Annotating a flow || Two notes hang off the steps they explain. Dashed connectors without markers keep them out of the flow itself. example=../../code/flow/components/note/flow.vue ::: ## Used components * [Flow](./flow) * [Node](./node) * [Connection](./connection) --- --- url: 'https://flux-ui.dev/flow/components/panel.md' --- # Panel `FluxFlowPanel` pins its content to a corner of the viewport instead of to the canvas. Everything else written inside a [Flow](./flow) lives in the world and travels with it; a panel sits above that world and stays where it is while the flow pans and zooms underneath. Write it anywhere inside the flow. Where it sits in your markup makes no difference: the corner is the `position` prop. ::: render render=../../code/flow/components/panel/preview.vue ::: ::: tip A panel takes its own presses back, so a button or a field inside one never starts a pan. It is also transparent to the pointer everywhere it does not cover, so the canvas below keeps the rest of the surface. ::: ::: tip [Controls](./controls) and [Minimap](./minimap) are panels with something ready-made in them. Reach for `FluxFlowPanel` directly when you need a corner of the viewport for something else. ::: ## Used components * [Flow](./flow) --- --- url: 'https://flux-ui.dev/flow/components/controls.md' --- # Controls `FluxFlowControls` is the button bar of an interactive canvas: zoom out, the current zoom level, zoom in, and take the flow fullscreen. Write it anywhere inside a [Flow](./flow) and it pins itself to a corner of the viewport, so it stays put while the flow pans and zooms behind it. It renders nothing on a flow without `interactive`, since there is nothing there to zoom. The zoom level sits between the two zoom buttons and is a button of its own: it opens a flyout holding 200%, 150%, 100%, 75%, 50% and fit view. A level zooms about the middle of the viewport, so what is being looked at stays where it is, and a level the flow cannot reach is left out of the list: a canvas capped with `max-zoom` never offers one. Fullscreen hands the whole screen to the flow, panels and all, and leaves the zoom and the position alone: the flow only gains room. The button sits apart from the zoom buttons, and it is left out entirely on a browser that does not allow fullscreen. ::: render render=../../code/flow/components/controls/preview.vue ::: ::: tip The buttons carry an icon and no text of their own, so every name the bar holds is a prop rather than a fixed string: set `fit-label`, `fullscreen-label`, `exit-fullscreen-label`, `zoom-in-label`, `zoom-label` and `zoom-out-label` to the language of your application. The zoom levels are percentages, which need no translating. ::: ## Examples ::: example Corner || Point `position` at the corner the bar belongs in. It is the same prop a [Panel](./panel) takes, so controls and a panel of your own line up on the same grid. example=../../code/flow/components/controls/position.vue ::: ## Used components * [Flow](./flow) * [Panel](./panel) --- --- url: 'https://flux-ui.dev/flow/components/minimap.md' --- # Minimap `FluxFlowMinimap` is the whole flow at a glance: a block per node and a frame around the part of it currently on screen. Click or drag on the map to move the viewport there, which is how you cross a flow that reaches well past its container without panning your way over. It renders nothing on a flow without `interactive`, since a flow that shows all of itself has nothing to map. ::: render render=../../code/flow/components/minimap/preview.vue ::: ::: tip The map fits the nodes, not the whole world, so panning past the flow does not shrink every block. The frame is allowed to run off the edge of the map: that is what tells you the viewport sits beside the flow rather than on it. ::: ::: tip Blocks are drawn in one flat gray. A minimap says where things are, not what they are; the color of a card belongs on the card. ::: ## Used components * [Flow](./flow) * [Panel](./panel) --- --- url: 'https://flux-ui.dev/flow/composables/useFlowLayout.md' --- # useFlowLayout `useFlowLayout` turns a graph into a drawing. Hand it your nodes and edges and it returns a position per node id plus the connections between them, ready to bind to `FluxFlowNode` and `FluxFlowConnection`. Where a [Chain](../components/chain) places a run of steps in a line, this places a graph that branches and comes back together. It is a plain function: no component, no DOM and no reactivity. Nodes are laid out in layers, every node lands one layer past its furthest source, and every layer is centred against the widest one, so a straight stretch of the graph stays straight. ## Usage ```ts import { useFlowLayout } from '@flux-ui/flow'; const {positions, connections} = useFlowLayout( [{id: 'intake'}, {id: 'verify'}, {id: 'score'}], [{from: 'intake', to: 'verify'}, {from: 'verify', to: 'score'}] ); // positions: { intake: {x: 0, y: 0}, verify: {x: 0, y: 150}, … } // connections: [{from: 'intake', to: 'verify', fromSide: 'bottom', toSide: 'top'}, …] ``` Both are meant to be spread straight onto the components: ```vue ``` ::: render render=../../code/flow/composables/useFlowLayout/preview.vue ::: ::: tip The function runs without a DOM, so it cannot measure a card. Nodes without a `width` and `height` of their own fall back to `nodeWidth` and `nodeHeight`; pass the size your cards actually have to keep the gaps even. ::: ::: tip The sides come with the connections, so you never name them yourself. Binding a bare `from` and `to` instead leaves each connector picking the shortest axis between the two cards, and in a layer wider than it is deep that is the wrong one. Setting [`axis`](../components/flow) on the surrounding `FluxFlow` fixes that for hand placed nodes too. ::: ## Example ::: example Left to right || A release pipeline laid out with `direction: 'horizontal'`. The retry edge closes a cycle, which the layout cuts open instead of following, so the run still lands in four layers. example=../../code/flow/composables/useFlowLayout/horizontal.vue ::: ## Options ### direction (`'vertical'`) The axis the layers stack on. `vertical` runs top to bottom, `horizontal` runs left to right. ### layerGap (`60`) The space, in pixels, between two layers. ### nodeGap (`45`) The space, in pixels, between two nodes inside one layer. ### nodeWidth (`300`) and nodeHeight (`90`) The size assumed for a node that does not carry one, since the function runs without a DOM. ### x (`0`) and y (`0`) The top-left corner the layout starts from. ## Cycles Only directed acyclic graphs lay out in layers, but a graph that loops back on itself is not an error here. An edge that would close a cycle is cut rather than followed, so a retry or a rollback still produces a usable layout instead of an empty one. A cut edge runs against the flow, and its connection says so: it leaves and enters on the off axis, looping around the diagram instead of cutting back across it. You do not have to work out which edge that was. Edges to a node that was never given, and edges from a node to itself, are dropped. They are missing from `connections` too, so iterating over it never leaves a connector pointing at nothing. ## Type declarations ```ts type FluxFlowLayoutNode = { readonly id: string; readonly width?: number; readonly height?: number; }; type FluxFlowLayoutEdge = { readonly from: string; readonly to: string; }; type FluxFlowLayoutOptions = { readonly x?: number; readonly y?: number; readonly direction?: 'horizontal' | 'vertical'; readonly layerGap?: number; readonly nodeGap?: number; readonly nodeWidth?: number; readonly nodeHeight?: number; }; type FluxFlowLayoutConnection = { readonly from: string; readonly to: string; readonly fromSide: 'top' | 'right' | 'bottom' | 'left'; readonly toSide: 'top' | 'right' | 'bottom' | 'left'; }; type FluxFlowLayoutResult = { readonly positions: Record; readonly connections: readonly FluxFlowLayoutConnection[]; }; declare function useFlowLayout( nodes: readonly FluxFlowLayoutNode[], edges: readonly FluxFlowLayoutEdge[], options?: FluxFlowLayoutOptions ): FluxFlowLayoutResult; ``` --- --- url: 'https://flux-ui.dev/flow/examples.md' --- # Examples The component pages each cover one building block in isolation. This page does the opposite: complete flows, built the way you would build them in an app. Every example is runnable, so open the Code tab to see the whole thing, positions and wiring included. ## Automations ::: example Routing rules || A trigger pill heads the flow, numbered markers run down the trunk, and every condition fans out to a labeled branch. This is the shape most automation builders end up with. example=../code/flow/examples/routing.vue ::: ::: example Onboarding || A chain places the run of steps and wires it up, and a group frames the two that belong together. Only the branch that leaves the chain carries a coordinate of its own. example=../code/flow/examples/onboarding.vue ::: ::: example Deploy pipeline || A CI/CD flow: a push builds an image, tests gate the release, and the outcome branches to a deploy or an alert. Colored and dashed connectors separate the happy path from the failure path. example=../code/flow/examples/deploy.vue ::: ::: example Knowledge graph || Data sources feeding structured skills that compile into an output. It combines card rows, colored and dashed connectors and endpoint markers into one dense canvas. example=../code/flow/examples/knowledge.vue ::: ::: example Branching on ports || A fraud check whose two outcomes each carry their own port, so a branch leaves the card at the answer it belongs to. Terminals open and close the run, and a note explains the manual step. example=../code/flow/examples/ports.vue ::: ## Live flows Nothing about a card is read only. Because the body is plain markup, controls inside it keep working on the canvas, which lets a flow double as the control surface for the process it draws. ::: example Enable and disable || A FluxToggle in the trigger card switches the automation on and off; the downstream cards and connectors follow its state. example=../code/flow/examples/enable.vue ::: ::: example Approval step || A FluxSecondaryButton in a card footer resolves an approval, which activates the next node and fills its connector. example=../code/flow/examples/approval.vue ::: ::: example Run on demand || A FluxPrimaryButton kicks off a run: a FluxStatisticsMeter animates the build while the connectors fill from stage to stage. example=../code/flow/examples/live.vue ::: ::: example Running pipeline || A nightly sync walks its own stages: the step that is busy carries a spinner in place of its icon, its connector fills while it runs, and a finished stage flips to a check and a Done badge. example=../code/flow/examples/running.vue ::: ## Used components * [Flow](./components/flow) * [Node](./components/node) * [Chain](./components/chain) * [Connection](./components/connection) * [Group](./components/group) * [Port](./components/port) * [Card](./components/card) * [Pill](./components/pill) * [Step](./components/step) * [Terminal](./components/terminal) * [Note](./components/note) --- --- url: 'https://flux-ui.dev/application.md' --- # Flux Application Flux Application is a collection of components designed for building modern, route-driven application shells. It provides a complete layout system with a multi-level context menu, sticky top bar, hero header, and right side panel, giving you everything you need to ship a polished application interface without reinventing the layout. The package builds on Vue Router and uses [named views](https://router.vuejs.org/guide/essentials/named-views.html) to render context-specific menus next to each route, so every level of a nested route tree can contribute its own navigation. --- --- url: 'https://flux-ui.dev/application/introduction/installation.md' --- # Installation To start using Flux Application in your Vue application, you'll need to add it to your project. This section provides step-by-step instructions on how to install Flux Application, ensuring you can quickly integrate its components into your development workflow. ::: tip Flux Application relies on [Vue Router](../../guide/introduction/installation/vue-router) for its named-view based context menus. Make sure Vue Router is installed and configured in your project before using the components. ::: ## Plain installation ::: tip This is the most recommended way to use Flux Application. Use this form of installation if you don't need to customize the style of Flux Application or if you simply need to use the components without the source code. ::: ### Step 1 Open your project's root directory in your terminal and run the following command: ::: code-group ```shell [Bun] bun add @flux-ui/application @flux-ui/components ``` ```shell [PNPM] pnpm install @flux-ui/application @flux-ui/components ``` ```shell [Yarn] yarn add @flux-ui/application @flux-ui/components ``` ```shell [NPM] npm install @flux-ui/application @flux-ui/components ``` ::: ### Step 2 Once the installation is complete, you need to add the following line to your `main.ts` file: ```ts [main.ts] import '@flux-ui/application/style.css' import '@flux-ui/components/style.css' ``` ### Step 3 Import the components you want to use, like this: ```vue [App.vue] ``` ## Vite-preset installation ::: tip Only use this form of installation if you need more control of Flux Application and need the Flux Application source code injected into your own project. ::: ### Step 1 Open your project's root directory in your terminal and run the following command: ::: code-group ```shell [Bun] bun add @flux-ui/application @flux-ui/components sass-embedded @basmilius/vite-preset ``` ```shell [PNPM] pnpm install @flux-ui/application @flux-ui/components sass-embedded @basmilius/vite-preset ``` ```shell [Yarn] yarn add @flux-ui/application @flux-ui/components sass-embedded @basmilius/vite-preset ``` ```shell [NPM] npm install @flux-ui/application @flux-ui/components sass-embedded @basmilius/vite-preset ``` ::: ### Step 2 Once the installation is complete, you need to configure your `vite.config.ts` file to use Flux Application. ::: tip For more information on the vite-preset package, please refer to [@basmilius/vite-preset](https://github.com/basmilius/packages/tree/main/packages/vite-preset). ::: ```ts [vite.config.ts] import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { flux, fluxApplication, preset } from '@basmilius/vite-preset' export default defineConfig({ plugins: [ vue(), preset(), flux(), fluxApplication() ] }); ``` ### Step 3 Import the components you want to use as shown in step 3 of the plain installation. --- --- url: 'https://flux-ui.dev/application/components/application.md' --- # Application The application component provides the overall layout structure for the application interface. It defines regions for the menu sidebar, the main content, and an optional side panel. This component also manages the collapsed state of the menu and the active context level, and shares that state with child components through [`useApplicationInjection`](../composables/useApplicationInjection). ## Snippet ::: code-group ```vue \[FluxApplication.vue] ``` ::: --- --- url: 'https://flux-ui.dev/application/components/content.md' --- # Application content The application content component is the main `
` region of the application. It accepts a `layout` prop that controls the maximum width and spacing of the content. The selected layout is also published back into the `FluxApplication` injection, so other components such as [Application top](./top) can adjust their tab bar width to match. The available layouts are `default`, `dashboard`, `full`, `medium` and `narrow`. ## Snippet ::: code-group ```vue \[FluxApplicationContent.vue] ``` ::: --- --- url: 'https://flux-ui.dev/application/components/hero.md' --- # Application hero The application hero introduces a page with a clear title and optional subtitle. It is the recommended starting point of any [Application content](./content) area and supports four positional slots (`start`, `before`, `after` and `end`) for adding contextual elements like back buttons, badges, breadcrumbs, or actions. ::: render render=../../code/application/hero/preview.vue ::: ## Examples ::: example With actions || Render action buttons next to the title using the `end` slot. example=../../code/application/hero/with-actions.vue ::: --- --- url: 'https://flux-ui.dev/application/components/menu.md' --- # Application menu The application menu is the sidebar of `FluxApplication`. It hosts the main menu and any number of context menu panels that slide in horizontally as the user navigates deeper into the route tree. When more than one level is visible, page indicator dots are rendered at the bottom so the user can jump to any level directly. The collapsed state of the menu is shared with the rest of the application through [`useApplicationInjection`](../../composables/useApplicationInjection). ## Snippet ::: code-group ```vue \[FluxApplicationMenu.vue] ``` ::: ## Used components * [Application menu](./) * [Account](./account) * [Context](./context) * [Context stack](./context-stack) * [Promo](./promo) * [Toggle](./toggle) --- --- url: 'https://flux-ui.dev/application/components/menu/account.md' --- # Application menu account The application menu account renders the current user as the last item of the menu footer. Provide a `label` and optionally an avatar through `image-src` or the `avatar` slot. When the `switcher` slot is provided, the item becomes clickable and reveals a flyout with the slot content, a perfect place for an account switcher. ## Snippet ::: code-group ```vue \[FluxApplicationMenuAccount.vue] ``` ::: ## Used components * [Flyout](../../../components/flyout) * [Menu](../../../components/menu) * [Item](../../../components/menu/item) * [Pane](../../../components/pane) --- --- url: 'https://flux-ui.dev/application/components/menu/context.md' --- # Application menu context The application menu context is the header of a context menu panel. It renders the title and subtitle of the current context together with a back button that either navigates to the parent level (when the user has drilled down through the context stack) or follows the route passed via `to`/`href` (when the user opened the context directly). The component automatically registers its title and subtitle in the parent `FluxApplication`, so other components, such as the breadcrumbs in the top bar, can reflect the current context. ## Snippet ::: code-group ```vue \[FluxApplicationMenuContext.vue] ``` ::: ## Used components * [Button](../../../components/button) * [Secondary](../../../components/button/secondary) --- --- url: 'https://flux-ui.dev/application/components/menu/context-stack.md' --- # Application menu context stack The application menu context stack renders a context menu panel for every matched route record that exposes a named view. Each panel slides in horizontally as the user drills deeper into the route tree. To use it, expose a `menu` named view on every route that should contribute a context menu: ```ts [router.ts] const routes: RouteRecordRaw[] = [ { path: '/projects/:id', components: { default: () => import('./views/ProjectOverview.vue'), menu: () => import('./views/ProjectMenu.vue') // [!code focus] } } ]; ``` The matched menu components are then rendered through `` in the order of their depth in `route.matched`. ## Snippet ::: code-group ```vue \[FluxApplicationMenuContextStack.vue] ``` ::: ## Used components * [Application menu](./) * [Menu](../../../components/menu) --- --- url: 'https://flux-ui.dev/application/components/menu/promo.md' --- # Application menu promo The application menu promo is a small content block that you can drop inside the menu sidebar to highlight a feature, advertise a plan upgrade, or surface contextual help. ::: render render=../../../code/application/menu/promo/preview.vue ::: ## Snippet ::: code-group ```vue \[FluxApplicationMenuPromo.vue] ``` ::: ## Used components * [Icon](../../../components/icon) --- --- url: 'https://flux-ui.dev/application/components/menu/toggle.md' --- # Application menu toggle The application menu toggle is the button that collapses or expands the menu sidebar. It is rendered automatically by [Application top](../top), but you can also place it inside the menu itself, for example as a footer item, to give the user an alternative way to collapse the menu. The toggle reads its state from [`useApplicationInjection`](../../composables/useApplicationInjection), so it always reflects the current menu state. ## Snippet ::: code-group ```vue \[FluxApplicationMenuToggle.vue] ``` ::: ## Used components * [Menu](../../../components/menu) * [Item](../../../components/menu/item) --- --- url: 'https://flux-ui.dev/application/components/section.md' --- # Application section The application section groups related content under an optional `

` header. Use it to break the content of a page into clearly labelled blocks. The header can also display a small piece of meta information through the `info` prop and an action through the `end` slot. ::: render render=../../code/application/section/preview.vue ::: ## Snippet ::: code-group ```vue \[FluxApplicationSection.vue] ``` ::: --- --- url: 'https://flux-ui.dev/application/components/side.md' --- # Application side The application side renders an `