Vue DevUI

repository·dev·Indexed 22 days ago

https://github.com/devcloudfe/vue-devui

A Vue 3 component library based on the DevUI Design system, featuring 55 high-quality components with built-in support for TypeScript, Nuxt3, and theme customization. The ecosystem includes the DevUI CLI for scaffolding component templates and library entry files, as well as specialized implementations for complex components like Cascader, DatePicker, and a plugin-based useTree composable for tree structure management.

Tokens
260.1K
Snippets
917
Records
1.1K
Agent score
77%

What's inside vue-devui

  1. Overview of Vue DevUI components and features

    dev

    Vue DevUI is a comprehensive component library containing 77 flexible and powerful components. The library is organized into various categories, and components are tracked by their development status and feature completeness.

    Component Status Indicators:

    • Completed: Fully functional components.
    • 🚧 In Development: Components currently being worked on.
    • Pending: Components awaiting implementation or claim.

    Component Metadata:

    • Complexity: Some components are marked with a star (⭐) to indicate higher complexity.
    • Version: Components are associated with specific versions.
    • Deprecation: Deprecated components are visually flagged.
    • Features: Each component includes a set of specific features, which are linked to detailed documentation for each feature.
  2. Use the Splitter component for dynamic layouts

    dev

    The d-splitter component allows you to create layouts where different areas can be dynamically resized by the user. It consists of a container (d-splitter) and multiple panes (d-splitter-pane) provided via the DSplitterPane slot.

    Key Concepts

    • Orientation: Use horizontal (default) to split side-by-side or vertical to split top-to-bottom.
    • Panes: Each d-splitter-pane represents a section of the layout. You can control their size, minimum/maximum constraints, and whether they are resizable or collapsible.
    • Nesting: You can nest d-splitter components inside d-splitter-pane to create complex, multi-dimensional grid layouts.
    <template>
      <d-splitter orientation="horizontal" :splitBarSize="'2px'">
        <template v-slot:DSplitterPane>
          <d-splitter-pane size="30%" :collapsible="true">
            <div>Left Content</div>
          </d-splitter-pane>
          <d-splitter-pane>
            <div>Right Content</div>
          </d-splitter-pane>
        </template>
      </d-splitter>
    </template>
  3. Customize DatePickerPro panel with slots

    dev

    You can extend the appearance of the date picker panel using two slots:

    • rightArea: Used to add content to the right side of the calendar panel (e.g., quick date selection buttons).
    • footer: Used to add content to the bottom of the panel (e.g., 'Clear' or 'Today' buttons).
    <template>
      <d-date-picker-pro v-model="datePickerProValue" :showTime="true">
        <template #rightArea>
          <ul>
            <li><d-button @click="setDate(-7)">Last Week</d-button></li>
          </ul>
        </template>
        <template #footer>
          <div class="date-picker-footer">
            <d-button variant="solid" @click="setToday">Today</d-button>
          </div>
        </template>
      </d-date-picker-pro>
    </template>
  4. Use circular progress bars

    dev

    To display a circular progress bar, set the isCircle prop to true.

    Key features for circular mode:

    • strokeWidth: Sets the thickness of the progress ring (as a percentage of the canvas width).
    • showContent: A boolean to determine if the default percentage text should be displayed inside the circle. If set to false, you can use slots to provide custom content (like icons) inside the circle.
    • Custom content can be centered using CSS absolute positioning within the component.
    <template>
        <!-- Basic Circle -->
        <d-progress :isCircle="true" :percentage="80" />
    
        <!-- Circle with custom stroke width -->
        <d-progress :isCircle="true" :percentage="80" :strokeWidth="8" />
    
        <!-- Circle with custom icon content -->
        <d-progress :isCircle="true" :percentage="80" :showContent="false">
            <span class="icon-position">
                <d-icon name="right" color="#3dcca6" />
            </span>
        </d-progress>
    </template>
  5. Avatar display rules and priority

    dev

    Display Priority

    When multiple sources are provided, the component follows this priority order:

    1. imgSrc
    2. customText
    3. name

    Character Generation Rules (for name)

    If the component generates an avatar from the name string, it follows these rules:

    • Starts with Chinese characters: Uses the last two characters.
    • Starts with English characters: Uses the first two characters.
    • Multiple English names: Uses the first two letters of the first English name.
    • Other (non-Chinese/English): Uses the first two characters.

    Empty or Missing States

    • No data: If name, customText, and imgSrc are all missing, the component indicates the user does not exist.
    • Empty data: If name, customText, or imgSrc are provided but are empty strings, the component displays a default avatar.
  6. Prevent Panel collapse using before-toggle

    dev

    You can control or prevent the panel from folding by using the before-toggle property. This property accepts a function that is called before the collapse status changes.

    • To prevent folding: If the before-toggle function returns false, the panel will not fold (though it remains unaffected if it was already unfolded).
    • To control collapse asynchronously: The function receives a done callback. You can perform asynchronous operations and then call done() to trigger the actual collapse/expand action.
    // Example: Asynchronous toggle using done()
    let beforeToggle = (e, done) => {
      if (!opened) {
        setTimeout(() => {
          done();
        }, 1000);
        opened = true;
      }
    }
    
    // Example: Simple prevention
    const beforeToggle = (e) => {
      return panelToggle.value; // returns false to prevent toggle
    };
  7. Implement multi-level tree dragging

    dev

    For hierarchical/tree structures, configure v-dDroppable with allowDropOnItem: true. This allows items to be dropped into other items (nesting) rather than just between them. Use nestingTargetRect to define the sensitive area (height) for nesting and dragOverItemClass to style the item being hovered over for nesting.

    Key properties for tree dragging:

    • allowDropOnItem: Boolean to enable nesting.
    • nestingTargetRect: Object specifying the { height: number } area of an item that triggers a nesting drop.
    • dragOverItemClass: CSS class applied to an item when a draggable is hovering over it for nesting.
    <div
      v-dDroppable="{
        dropScope: 'drop-area',
        allowDropOnItem: true,
        nestingTargetRect: { height: 30 },
        dragOverItemClass: 'drag-over-item',
        '@dropEvent': (e) => onDrop(e, data.list2)
      }"
    >
      <ul v-dSortable>
        <li v-for="item in data.list2" v-dDraggable="{ ... }">
          {{ item.name }}
          <!-- Recursive component for children -->
          <demo-item v-if="item.children" :parentItem="item" />
        </li>
      </ul>
    </div>
  8. Prevent radio selection changes with before-change

    dev

    Both d-radio and d-radio-group support a before-change prop. This prop accepts a function or a Promise that returns a boolean. If the function returns false, the selection change is cancelled.

    This is useful for validation or conditional logic (e.g., preventing a user from selecting a specific option based on current state).

    <template>
      <d-radio
        v-for="item in filterList"
        v-model="filterChoose"
        :key="item"
        :value="item"
        :beforeChange="filterBeforeChange"
      >
        {{ item }}
      </d-radio>
    </template>
    
    <script>
    import { defineComponent, ref } from 'vue';
    
    export default defineComponent({
      setup() {
        const filterList = ref(['Item1', 'Item2', 'Item3']);
        let filterChoose = ref('Item1');
    
        return {
          filterList,
          filterChoose,
          filterBeforeChange(value) {
            // Prevent switching to 'Item2'
            return value !== 'Item2';
          },
        };
      },
    });
    </script>
  9. Understand CommentPosition data structure

    dev

    The CommentPosition interface describes where a comment is placed.

    In line-by-line mode, left and right represent line numbers for the left and right columns respectively.

    • If the position is an unchanged line, both left and right are the line number.
    • If the position is a deleted line, left is the line number and right is -1.
    • If the position is an added line, left is -1 and right is the line number.

    When allow-checked is enabled, the object includes a details property for multi-line selections:

    interface CommentPosition {
      left: number;
      right: number;
      details?: {
        lefts: Array<number>;
        rights: Array<number>;
        codes: Array<string> | {
          leftCode: Array<string>;
          rightCode: Array<string>;
        }
      }
    }