grad-vue

Vue.js 3 / Nuxt 4 / Custom Elements component library.

GitHub Repository

Introduction

This is a demo application showcasing the components available in the grad-vue library.

Installation

To install grad-vue, use npm:

npm install @illinois-grad/grad-vue

Some components come with heavy dependencies that are not appropriate for all projects. Those are split into separate packages to allow for more granular installation.

npm install @illinois-grad/grad-vue-rte

Custom Elements (Web Components)

grad-vue includes a custom element build that can be used outside of Vue.js apps, including other frameworks, CMS platforms, and just plain HTML.

Custom Elements Documentation

More Information

More details about the library can be found in the GitHub repository.

MIT License
Copyright © 2025 University of Illinois Board of Trustees

Other copyrights and licenses in embedded content:

Alert Dialog

A modal alert dialog for important user confirmations. Click the button to open the dialog.

Additional Documentation

Alert dialog for confirming or canceling actions.

Clicking on the outside or pressing the escape key will close the dialog and that counts as canceling.

Important

The surrounding page must have an element with the id modal-root, this dialog will be teleported to it, so it can properly be over all other content. The modal-root should be somewhere near the end of the page structure.

Slot default is used as the content of the alert, and also becomes the ARIA description of the alert.

Props
type Props = {
    /**
     * Dialog label
     */
    label?: string;
    /**
     * Accept button text
     */
    buttonText?: string;
    /**
     * Accept button color
     */
    buttonColor?: "primary" | "secondary" | "danger";
}

Result:

Props Configuration

App Header

An application header component.

Additional Documentation

This is a minimal header meant for web apps where a full Illinois brand header would be too large.

Slot left allows replacing the link element in the top-left corner.

Slot title is to the right of the logo.

Slot app-controls is the remaining area to the right.

Props
type Props = {
    /**
     * Whether to show the Illinois logo
     */
    illinois?: boolean;
    /**
     * Top-left corner text
     *
     * You can customize this text element with the "left" slot.
     */
    brand?: string;
};
Portal

Props Configuration

You can customize this text element with the 'left' slot.

Button

A versatile button component with multiple size and theme options.

Additional Documentation

The element or component can be set with the component prop, so it can be a link or router-link component from vue-router. For example:

<GButton component="router-link" to="/some-route">
    Click me
</GButton>

Note that grad-vue doesn't include vue-router as a dependency.

Icons can be added with either the icon prop or a named slot icon:

  • Use the icon prop to pass an icon class string, e.g., "fa-solid fa-plus".
  • If using the icon prop, the icon will be rendered as a span with the aria-hidden attribute set to true.
  • Use a named slot icon to provide custom icon content.
  • If both icon prop and named slot icon are provided, the named slot takes precedence.
Props
type Props = {
    /**
     * Button size
     */
    size?: "small" | "medium" | "large";
    /**
     * Button color theme
     */
    theme?: "primary" | "secondary" | "accent" | "danger" | "none";
    /**
     * Use outlined style
     */
    outlined?: boolean;
    /**
     * Use text style
     */
    text?: boolean;

    /**
     * The to target for when using the button as a router-link
     */
    to?: string | Record<string, any>;

    /**
     * The component to use for the button
     */
    component?: string;

    /**
     * Optional icon classes to render an icon span before the label. Example: "fa-solid fa-plus" or "material-symbols:add". If a named slot `icon` is provided, it takes precedence over this prop.
     */
    icon?: string;
    /**
     * Native button type
     */
    type?: "button" | "submit" | "reset";
}

Props Configuration

Button Sizes

Button Themes

Button Variants

Chat Input

A rich text input component for chat and comments with formatting support.

Additional Documentation

The GChatInput component provides a rich text editing experience using Tiptap. It supports:

  • Bold and italic text formatting
  • Bullet and numbered lists
  • Bubble menu for formatting (appears when text is selected)
  • Press Enter to send, Shift+Enter for new line
  • Undo/redo support

Note: This component is part of the @illinois-grad/grad-vue-rte package, which includes Tiptap dependencies.

Props
type Props = {
    /**
     * Placeholder text
     */
    placeholder?: string;
    /**
     * Disabled
     */
    disabled?: boolean;
    /**
     * Maximum number of rows
     */
    maxRows?: number;
    /**
     * Accessible label
     */
    label?: string;
}

Props Configuration

Checkbox Group

A group of checkboxes with label, instructions, and error support.

Additional Documentation

A group of checkboxes (or radio buttons) with styling for a label, instructions, and error messages.

When more than one option is provided (or radio mode is used), a fieldset + legend provides semantic grouping. With a single checkbox a plain div is rendered instead.

Each option renders as a native <input type="checkbox"> (or type="radio" when radio is true) so that keyboard navigation and browser/assistive-technology support come for free.

In standard Vue usage, this registers with the nearest parent GForm via injection. In custom-elements mode, use matching form-key values to pair with a GForm.

Errors are provided as an array of strings or computed values. Multiple errors will all be displayed.

Props
type Props = {
    /**
     * Legend / accessible label for the group
     */
    label?: string;
    /**
     * List of checkbox options
     */
    options: CheckboxOption[];
    /**
     * Instructions shown below the legend
     */
    instructions?: string;
    /**
     * Error messages array (supports multiple validation errors)
     */
    errors?: string[];
    /**
     * Mark the group as required
     */
    required?: boolean;
    /**
     * Render as radio buttons (single-select)
     */
    radio?: boolean;
    /**
     * Name for form registration and native input `name` attribute
     */
    name?: string;
    /**
     * Form channel key for custom elements mode
     */
    formKey?: string;
};
Choose options
This option has a hint
Selected:[]

Props Configuration

Checkbox Group in radio mode (single-select).

Pick one
This option has a hint
Selected:[]

Checkbox Group with error messages.

Required selection
This option has a hint

Clipboard

Scaffolded demo for GClipboard.

Additional Documentation

Displays text with a clipboard button that copies the text to the clipboard. The text can be hidden in cases where it's already displayed differently.

If for some reason the user's browser doesn't support a clipboard, the tooltip will indicate that when they try to copy.

Props
type Props = {
    /**
     * Text
     */
    text: string;

    /**
     * Hide the visible text
     */
    hideText?: boolean;

    /**
     * Copy button label
     */
    copyLabel?: string;
}
This is some text to get copied

Props Configuration

Currency Input

Basic Currency Input

A currency input component for US dollars with a $ prefix.

Additional Documentation

A currency input component for US dollars.

This component is a wrapper around a text input with a prefix and appropriate input type for currency values.

In standard Vue usage, this registers with the nearest parent GForm via injection. In custom-elements mode, use matching form-key values to pair with a GForm.

Props
type Props = {
    /**
     * Label
     */
    label?: string;
    /**
     * Placeholder text
     */
    placeholder?: string;
    /**
     * Disabled
     */
    disabled?: boolean;

    /**
     * Error messages array (supports multiple validation errors)
     */
    errors?: string[];
    /**
     * Instructions
     */
    instructions?: string;
    /**
     * Name for form registration
     */
    name?: string;
    /**
     * Form channel key for custom elements mode
     */
    formKey?: string;
};
$
Value:

Props Configuration

Date Input

Basic Date Input

A date input component using the browser's native date picker.

Additional Documentation

A date input component.

This component is a wrapper around GTextInput with type="date" for proper date selection using the browser's native date picker.

In standard Vue usage, this registers with the nearest parent GForm via injection. In custom-elements mode, use matching form-key values to pair with a GForm.

Props
type Props = {
    /**
     * Label
     */
    label?: string;
    /**
     * Placeholder text
     */
    placeholder?: string;
    /**
     * Disabled
     */
    disabled?: boolean;

    /**
     * Error messages array (supports multiple validation errors)
     */
    errors?: string[];
    /**
     * Instructions
     */
    instructions?: string;
    /**
     * Name for form registration
     */
    name?: string;
    /**
     * Form channel key for custom elements mode
     */
    formKey?: string;
};
Value:

Props Configuration

Date Range Input

Basic Date Range Input

A date range input with start and end dates laid out horizontally.

Additional Documentation

A date range input component with start and end dates.

This component uses two GDateInput components laid out horizontally to allow selecting a date range.

In standard Vue usage, this registers with the nearest parent GForm via injection. In custom-elements mode, use matching form-key values to pair with a GForm.

Props
type Props = {
    /**
     * Label for the component
     */
    label?: string;
    /**
     * Label for the start date input
     */
    startLabel?: string;
    /**
     * Label for the end date input
     */
    endLabel?: string;
    /**
     * Disabled
     */
    disabled?: boolean;

    /**
     * Error messages array (supports multiple validation errors)
     */
    errors?: string[];
    /**
     * Instructions
     */
    instructions?: string;
    /**
     * Name for form registration
     */
    name?: string;
    /**
     * Form channel key for custom elements mode
     */
    formKey?: string;
};
Value:{ "start": null, "end": null }

Props Configuration

Detail List

Displays labeled values in a grid or vertical layout.

Additional Documentation

This component is used with the GDetailListItem component to display a list of key-value pairs in a grid or vertical layout.

For example:

<GDetailList>
    <GDetailListItem label="Name">John Doe</GDetailListItem>
    <GDetailListItem label="Age">30</GDetailListItem>
    <GDetailListItem label="City">New York</GDetailListItem>
</GDetailList>
Props
type Props = {
    /**
     * Layout style for the items.
     */
    variant?: "grid" | "vertical";
}
Description
Engineering: Energy Systems
Major
Engineering
Department Code
123
College Name
Grainger Engineering

Props Configuration

Email Input

Basic Email Input

An email input component with proper email validation.

Additional Documentation

An email input component.

This component is a wrapper around GTextInput with type="email" for proper email validation and mobile keyboard optimization.

Props
type Props = {
    /**
     * Label
     */
    label?: string;
    /**
     * Placeholder text
     */
    placeholder?: string;
    /**
     * Disabled
     */
    disabled?: boolean;

    /**
     * Error messages array (supports multiple validation errors)
     */
    errors?: string[];
    /**
     * Instructions
     */
    instructions?: string;
    /**
     * Name for form registration
     */
    name?: string;
};
Value:

Props Configuration

File Input

Single File

A basic file input for selecting a single file.

Additional Documentation

A file input component for accessible file uploads.

If label is omitted, an accessible label must be provided some other way.

In standard Vue usage, this registers with the nearest parent GForm via injection. In custom-elements mode, use matching form-key values to pair with a GForm.

Errors are provided as an array of strings. Multiple errors will all be displayed. Client-side validation errors from maxFileSize and maxFiles are shown alongside any provided errors.

Props
type Props = {
    /**
     * Label
     */
    label?: string;
    /**
     * Instructions
     */
    instructions?: string;
    /**
     * Disabled
     */
    disabled?: boolean;
    /**
     * Error messages array (supports multiple validation errors)
     */
    errors?: string[];
    /**
     * Required
     */
    required?: boolean;
    /**
     * Name for form registration
     */
    name?: string;
    /**
     * Form channel key for custom elements mode
     */
    formKey?: string;
    /**
     * Accepted file types (e.g. ".pdf,.docx" or "image/*")
     */
    accept?: string;
    /**
     * Allow multiple file selection
     */
    multiple?: boolean;
    /**
     * Maximum file size in bytes for client-side validation
     */
    maxFileSize?: number;
    /**
     * Maximum number of files allowed for client-side validation
     */
    maxFiles?: number;
};
Selected:None

Props Configuration

Form

A form wrapper component that automatically manages form state using reactive patterns.

Additional Documentation

A form wrapper component that automatically manages form state and connects to child input components.

Child input components that have a name prop will automatically register with the form, and their values will be tracked in the form model.

Features

  • Automatic value tracking for child input components with the name prop
  • Reactive error handling by providing a computed list of errors
  • Optionally manage your own form state in a parent component by providing a form injection
  • In web components mode, use the form-key prop to pair a form with matching inputs/buttons across custom element app boundaries

Basic example

<GForm v-model="formData" @submit="handleSubmit">
  <template #default="{ isSubmitting, hasErrors }">
    <GTextInput name="firstName" label="First Name" :errors="firstNameErrors" />
    <GSubmitButton :disabled="hasErrors">Submit</GSubmitButton>
  </template>
</GForm>
Props
type Props = {
    /**
     * Action URL (optional, for native form submission)
     */
    action?: string;
    /**
     * HTTP method (optional, for native form submission)
     */
    method?: string;
    /**
     * Form channel key for custom elements mode
     */
    formKey?: string;
}
Value:Form Data: {}

Props Configuration

Hamburger Menu

A hamburger menu button.

Additional Documentation

A hamburger menu button that toggles a sidebar, intended for the GAppHeader and GSidebar components.

Use with the useSidebar composable function that takes care of passing state between the different components.

Here's an example, this could be your App.vue or a layout file:

<script setup lang="ts">
import { computed, h, onMounted, provide, ref, useTemplateRef } from "vue";
import { useSidebar } from "../src/compose/useSidebar";

const sidebar = useSidebar();
provide("sidebar", sidebar);

// Or optionally a custom breakpoint
// const sidebar = useSidebar("(max-width: 600px)");
</script>

As long as GHamburgerMenu and GSidebar are descendants of the component that provides the sidebar, they will be able to communicate with each other.

Note

This button hides itself automatically according to the useSidebar media query. In web components mode, use the sidebar-key prop to pair this menu with a matching GSidebar instance.

Props
type Props = {
    /**
     * Accessible label
     */
    label?: string;
    /**
     * Sidebar channel key for custom elements mode
     */
    sidebarKey?: string;
}

Props Configuration

History Scroller

Scroller that starts at the bottom.

Additional Documentation

A scroller that is used for content that's typically shown like a chat log, meaning it starts at the bottom, and you scroll up for older entries.

The scroller automatically starts at the bottom. When scrolled up, a button appears that jumps to the bottom. This button is also the first focusable element for accessibility.

If the label is provided, the scroller will have the ARIA role="log" and the label as the aria-label.

Slot default is what will be rendered for each entry in the entries. For example:

<GHistoryScroller
    v-bind="props"
    :entries="historyEntries"
    class="history-scroller">
    <template #default="{ entry }">
        <div class="history-entry">
            This is history for: {{ entry.id }}
        </div>
    </template>
</GHistoryScroller>
Props
type Props = {
    /**
     * Accessible label
     */
    label?: string;

    /**
     * History entries passed to default slot
     */
    entries: T[];
};
This is history for: one
This is history for: two
This is history for: three
This is history for: four
This is history for: five
This is history for: six
This is history for: seven
This is history for: eight
This is history for: nine
This is history for: ten
This is history for: eleven
This is history for: twelve

Props Configuration

Multi Select

A multi-select combobox with search/filter support and removable chip tags.

Additional Documentation

A multi-select combobox that allows selecting multiple values with optional search/filter support.

Selected values are displayed as removable chips inside the control. The dropdown listbox shows all (or filtered) options with a checkmark next to each selected option.

The options prop accepts an array of strings or { label, value } objects. The v-model binds to an array of string | number values.

In standard Vue usage, this registers with the nearest parent GForm via injection. In custom-elements mode, use matching form-key values to pair with a GForm.

Keyboard navigation:

  • Down Arrow / Up Arrow: move through options (opens menu if closed)
  • Enter: toggle the focused option
  • Space: toggle the focused option when the search field is empty
  • Escape: close the dropdown
  • Home / End: jump to first / last option
  • Backspace: remove the last chip when the search field is empty
Props
type Props = {
    /**
     * List of options to choose from
     */
    options: Array<string | MultiSelectOption>;
    /**
     * Accessible label
     */
    label: string;
    /**
     * Hide the label visually
     */
    hiddenLabel?: boolean;
    /**
     * Placeholder text shown when no values are selected
     */
    placeholder?: string;
    /**
     * Disabled
     */
    disabled?: boolean;
    /**
     * Name for form registration
     */
    name?: string;
    /**
     * Error messages array (supports multiple validation errors)
     */
    errors?: string[];
    /**
     * Instructions shown below the label
     */
    instructions?: string;
    /**
     * Form channel key for custom elements mode
     */
    formKey?: string;
};
Selected:[]

Props Configuration

Multi Select with string options (no objects required).

Selected:[]

Multi Select with pre-selected values and error messages.

Pick your top fruits
  • Apple
Selected:[ "apple" ]

Disabled Multi Select.

  • Apple
  • Banana

Note Input

A rich text input component for writing notes and descriptions with an always-visible toolbar.

Additional Documentation

The GNoteInput component provides a rich text editing experience using Tiptap for writing notes. It supports:

  • Bold and italic text formatting
  • Bullet and numbered lists
  • Always visible toolbar for formatting
  • Undo/redo support

Note: This component is part of the @illinois-grad/grad-vue-rte package, which includes Tiptap dependencies.

Props
type Props = {
    /**
     * Placeholder text
     */
    placeholder?: string;
    /**
     * Accessible label
     */
    label?: string;
}

Props Configuration

Rich Text Content

Renders a JSON string of tiptap content as HTML. Supports all formatting produced by GChatInput and GNoteInput.

Additional Documentation

Renders a JSON string of tiptap content as HTML. Supports all formatting produced by GChatInput and GNoteInput: bold, italic, ordered lists, and bullet lists.

  • Empty content is handled gracefully (renders nothing).
  • Displays an error message when the content cannot be parsed or rendered.

The rendering only happens in the client when used with Nuxt.js.

Security note: rendered HTML is produced by tiptap's generateHTML, which only serializes recognized document nodes - it does not inject raw HTML from the JSON.

Note: This component is part of the @illinois-grad/grad-vue-rte package, which includes Tiptap dependencies.

Props
type Props = {
    /**
     * Error message when rendering fails
     */
    error?: string;

    /**
     * JSON-encoded tiptap content string to render.
     */
    content: string;
}

Rendered output:

Props Configuration

Popover

A popover overlay component that appears relative to a trigger element.

Additional Documentation

Popover that appears next to or over a trigger element, staying visible in the viewport as much as possible.

Slot trigger is optional. When provided, it should contain an interactive element for opening the popover and it is used for aria-labelledby. The trigger is passed a prop toggle which is a function that toggles the popover's open state.

Without a trigger slot, open the popover programmatically via show() or toggle() on the component instance / custom element.

Slot default is the content of the popover.

Example:

<GPopover>
    <template #trigger="{ toggle }">
        <GButton @click="toggle">
            Can Popovers have Popovers?
        </GButton>
    </template>
    <div>In theory, but I wouldn't recommend it.</div>
</GPopover>
Props
type Props = {
    /**
     * Render without padding
     */
    minimal?: boolean;
    /**
     * v-model binding for the open state. Also works as a plain prop/attribute in custom-element mode where `defineModel` would revert local state.
     */
    modelValue?: boolean;
}

Props Configuration

Progress

A progress indicator component.

Additional Documentation

A component that can show progress from 1 to 100 or an indeterminate spinner. If a value is omitted, the progress will be indeterminate.

If no label is specified, the default accessible label will be "Loading".

If a value is provided, the element will have the ARIA role progressbar with the appropriate ARIA value attributes.

If no value is provided, the element will have the ARIA role status.

Note

This element announces to assistive technologies, so make sure to limit its use to cases where that's appropriate.

Props
type Props = {
    /**
     * Accessible label
     */
    label?: string;
    /**
     * Progress 1-100 or blank
     */
    value?: number;
    /**
     * Progress circle size
     */
    size?: "tiny" | "small" | "medium" | "large";
};
Progress:%

Props Configuration

Select

A dropdown select component with customizable options.

Additional Documentation

By default, this component behaves like a normal select element with custom styling.

In standard Vue usage, this registers with the nearest parent GForm via injection. In custom-elements mode, use matching form-key values to pair with a GForm.

The component can be marked searchable to enable search functionality. This turns it into a text input that filters the options. Filtering is done with a simple lower-case string search.

The options prop can be an array of strings or objects with label and value properties.

Props
type Props = {
    /**
     * List of options to choose from
     */
    options: Array<string | OptionType>;
    /**
     * Accessible label
     */
    label: string;
    /**
     * Hide the label visually
     */
    hiddenLabel?: boolean;
    /**
     * Placeholder
     *
     * Only used if the component is searchable.
     */
    placeholder?: string;
    /**
     * Disabled
     */
    disabled?: boolean;

    /**
     * Name for form registration
     */
    name?: string;
    /**
     * Searchable
     */
    searchable?: boolean;
    /**
     * Show clear button
     */
    clearButton?: boolean;
    /**
     * Compact
     */
    compact?: boolean;

    /**
     * Error messages array (supports multiple validation errors)
     */
    errors?: string[];
    /**
     * Form channel key for custom elements mode
     */
    formKey?: string;
}
Select an option
Selected:

Props Configuration

Only used if the component is searchable.

Select Button

A button-style select component for choosing between options.

Additional Documentation

This component is just a radio button group with special styling.

In standard Vue usage, this registers with the nearest parent GForm via injection. In custom-elements mode, use matching form-key values to pair with a GForm.

Use the options prop to provide a list of choices. Each option can be a string or an object with label and value properties.

In addition to v-model, a change event is emitted when the option changes from user interaction.

Props
type Props = {
    /**
     * List of options to select from
     */
    options: Array<string | OptionType>;
    /**
     * Accessible label
     */
    label: string;
    /**
     * Size
     */
    size?: "small" | "medium" | "large";
    /**
     * Name for form registration
     */
    name?: string;
    /**
     * Disabled
     */
    disabled?: boolean;

    /**
     * Error messages array (supports multiple validation errors)
     */
    errors?: string[];
    /**
     * Form channel key for custom elements mode
     */
    formKey?: string;
}
Select Option
Selected:option1

Props Configuration

Table

Highly efficient and accessible data table.

Additional Documentation

A data table component with support for grouping, sorting, filtering, and pagination.

A heavy focus has been on performance. The table body doesn't use any Vue components, it's pure render functions. We've used it with 4000 rows and 14 columns loaded without issues.

This is a bit complicated to use, so an example has been omitted here. Instead, look at the source for this demo: GTable Demo Source.

Here are some of the key points.

Table content is provided with:

  • columns configuration using the TableColumn type.
    • At minimum the configuration must include key for which field of the data objects to use, and label for the column header.
    • sortable: true makes the column sortable.
    • filter can be used to provide a TableColumnFilter configuration.
    • display accepts a custom render function for the column data.
    • trClass and tdClass can be used to provide custom classes for table rows and cells.
  • data array with objects containing fields for the columns.

Rows can be made clickable with row-clickable. In this case, one of the cells must contain a link. Clicking a row will emit a row-click event with the link href from the first link in the row.

Grouping can be enabled by passing a column key to groupBy.

Props
type Props = {
    /**
     * Accessible label
     */
    label: string;
    /**
     * The data to display in the table
     *
     * The data should be an array of objects, each representing a row in the table. Each object should have a unique `key` property that can be used to identify the row.
     */
    data: T[];
    /**
     * The columns to display in the table
     *
     * Each column's key needs to match the key of a property in the data objects, which determines the data to display in that column by default. You can also provide a custom display function to customize the data display.
     */
    columns: C[];
    /**
     * Result count for all of the possible results (not just the current page)
     *
     * This is shown in the toolbar.
     */
    resultCount?: number;
    /**
     * A column key to group the data by
     *
     * If provided, the `groupRender` render function will be used to render the group header.
     */
    groupBy?: keyof T;
    /**
     * A render function to customize the display of the group header.
     *
     * @param groupValue The value of the group key for the current row @param row The row object for the first row in the group
     */
    groupRender?: (groupValue: any, row: T) => VNode;
    /**
     * Filtering object created with useFiltering()
     */
    filtering?: UseFilteringReturn<any>;
    /**
     * Make the table rows clickable
     */
    rowClickable?: boolean;
    /**
     * A function to customize the classes applied to table rows @param row The row object
     */
    rowClass?: (row: T) => string | string[] | undefined;
    /**
     * The starting index for this page
     *
     * This is used for the ARIA rowindex attribute, and is VERY important to not get wrong.
     */
    startIndex: number;
    /**
     * Enable bulk selection with checkboxes
     */
    bulkSelectionEnabled?: boolean;
    /**
     * Array of actions to show in the sticky toolbar when rows are selected
     */
    bulkActions?: BulkAction[];

    /**
     * Optional change tracker for editable tables. Pass a composable from useTableChanges() to track user edits.
     */
    changeTracker?: UseTableChangesReturn<T>;

    /**
     * Explicitly show the pagination bar even if the slot is empty
     */
    showPagination?: boolean;
};
16 results
LTCarle Illinois College of MedicineYes
KLCollege of Agricultural, Consumer and Environmental Sciences (ACES)Yes
KYCollege of Applied Health SciencesYes
KNCollege of EducationYes
KRCollege of Fine and Applied ArtsYes

Props Configuration

Editable Table

Table with editable columns for in-place data entry.

5 results
Product
Category
Price
Quantity
Weight
Laptop
$
kg
Mouse
$
kg
Keyboard
$
kg
Monitor
$
kg
Webcam
$
kg

Term Selector

A button to show and select a term.

Additional Documentation

A button that shows the selected term. Clicking it opens a popover that allows jumping to a different term.

Props
type Props = {
    /**
     * Title for the popover.
     */
    title?: string;

    /**
     * Label for year select.
     */
    yearLabel?: string;

    /**
     * Label for period select.
     */
    periodLabel?: string;

    /**
     * List of possible term years
     */
    termYears?: string[];

    /**
     * List of possible term names
     */
    termNames?: string[];
}
Selected:{ "year": "2026", "name": "Spring" }

Props Configuration

Text Input

A text input component.

Additional Documentation

A text input with styling for a label, instructions, and error messages.

If label is omitted, an accessible label must be provided some other way. All non-prop attributes are passed through to the input element, including id.

In standard Vue usage, this registers with the nearest parent GForm via injection. In custom-elements mode, use matching form-key values to pair with a GForm.

Errors are provided as an array of strings or computed values. Multiple errors will all be displayed.

Props
type Props = {
    /**
     * Label
     */
    label?: string;
    /**
     * Placeholder text
     */
    placeholder?: string;
    /**
     * Disabled
     */
    disabled?: boolean;

    /**
     * Error messages array (supports multiple validation errors)
     */
    errors?: string[];
    /**
     * Instructions
     */
    instructions?: string;
    /**
     * Prefix text (displayed before input)
     */
    prefix?: string;
    /**
     * Suffix text (displayed after input)
     */
    suffix?: string;
    /**
     * Debounce in milliseconds
     */
    debounce?: number;

    /**
     * Name for form registration
     */
    name?: string;
    /**
     * Form channel key for custom elements mode
     */
    formKey?: string;
};
Value:

Props Configuration

Textarea

A multi-line plain text input.

Additional Documentation

A multi-line plain text input with styling for a label, instructions, and error messages.

If label is omitted, an accessible label must be provided some other way. All non-prop attributes are passed through to the textarea element, including id.

In standard Vue usage, this registers with the nearest parent GForm via injection. In custom-elements mode, use matching form-key values to pair with a GForm.

Errors are provided as an array of strings or computed values. Multiple errors will all be displayed.

Props
type Props = {
    /**
     * Label
     */
    label?: string;
    /**
     * Placeholder text
     */
    placeholder?: string;
    /**
     * Disabled
     */
    disabled?: boolean;
    /**
     * Read-only
     */
    readonly?: boolean;
    /**
     * Required
     */
    required?: boolean;
    /**
     * Error messages array (supports multiple validation errors)
     */
    errors?: string[];
    /**
     * Instructions
     */
    instructions?: string;
    /**
     * Number of visible text rows
     */
    rows?: number;
    /**
     * Maximum number of characters allowed
     */
    maxlength?: number;
    /**
     * Automatically grow the textarea height to fit content
     */
    autoGrow?: boolean;
    /**
     * Name for form registration
     */
    name?: string;
    /**
     * Form channel key for custom elements mode
     */
    formKey?: string;
};
0 /
Value:

Props Configuration

Three Way Toggle

A switch or toggle with three different states.

Additional Documentation

This component acts like a radio button group condensed into a compact element with the goal of making it easy to go over many of them at once.

In addition to the arrow keys changing the selected value, special key bindings exist for 'y' and 'n' to set yes and no respectively.

A describedby prop can be passed with an ID to an element to be used as the aria-describedby for the group element.

When the value changes, v-model is updated. A change event is also emitted if the value changed from user interaction.

Slots:

  • label: Custom label content. Defaults to label prop if not provided.
Props
type Props = {
    /**
     * Accessible label
     */
    label: string;

    /**
     * ID of an element that describes the input
     */
    describedby?: string;

    /**
     * Error message
     */
    error?: string;

    /**
     * Disabled
     */
    disabled?: boolean;
}
Three-way toggle

Props Configuration

Tree Menu

A hierarchical sidebar menu for book-like or nested-section navigation. Items with children collapse and expand individually. Supports keyboard navigation (↑↓ to move, →← to expand/collapse, Home/End).

Additional Documentation

A hierarchical sidebar menu component suitable for book-like or nested-section navigation. Items with children start collapsed and can be expanded/collapsed individually.

Props:

  • title - optional heading and accessible name for the nav landmark.
  • items - array of TreeMenuItem objects. Each item may have:
    • label - display text (required).
    • href or to - link destination. When to is provided and vue-router is present the link is rendered as a <router-link>.
    • children - nested TreeMenuItem[] for sub-levels (unlimited depth).
  • listType - ul (default) or ol. Use ol for numbered hierarchies such as book chapters.
  • theme - light (default) or dark.

Keyboard navigation (tree-view style):

  • Up Arrow / Down Arrow - move between visible menu items.
  • Right Arrow - expand a collapsed item; if already expanded, move to its first child.
  • Left Arrow - collapse an expanded item; if already collapsed, move focus to its parent.
  • Home / End - jump to the first or last visible item.
Props
type Props = {
    /**
     * Title and accessible name for the nav landmark
     */
    title?: string;
    /**
     * Items for the menu
     */
    items: TreeMenuItem[];
    /**
     * List element type - use `ol` for numbered hierarchies like book chapters
     */
    listType?: "ul" | "ol";
    /**
     * Theme
     */
    theme?: "light" | "dark";
};

Props Configuration

User Menu

User menu component with avatar, email display, and account links.

Additional Documentation

User menu component for toolbars. Displays a button with the user's initials inside a colored circle. When clicked, it opens a popover with the user's email and a menu for account-related links.

Slots:

  • default contains menu items (links or buttons) that will be wrapped in an unordered list for accessibility.

Props:

  • initials - User's initials to display in the avatar
  • email - User's email to display in the popover
  • color - Background color for the avatar (should be deterministic)
  • label - Accessible label for the menu button. The initial will be prepended to this for the full label.

Example:

<GUserMenu
    initials="J"
    email="j@example.com"
    color="#4A90E2"
>
    <router-link to="/profile">Profile</router-link>
    <a href="/settings">Settings</a>
    <button @click="handleLogout">Logout</button>
</GUserMenu>
Props
type Props = {
    /**
     * User initial(s)
     */
    initials: string;
    /**
     * User email
     */
    email: string;
    /**
     * Background color
     */
    color?: string;
    /**
     * Accessible label
     */
    label?: string;
}

Props Configuration