How NutUI’s Collapse Panel Boosts Development Efficiency with Vue3

This article explains the design and implementation of NutUI’s Collapse component, covering its basic interaction, animation techniques using height and transform, flexible header customization, slot-based extensions, SCSS variable usage, and Vue3 provide/inject communication, all illustrated with practical code examples.

JD.com Experience Design Center
JD.com Experience Design Center
JD.com Experience Design Center
How NutUI’s Collapse Panel Boosts Development Efficiency with Vue3

Collapse Panel Design

Collapse panels are common UI components that can expand or collapse content areas, useful for navigation, detail sections, and filter categories. NutUI provides a mobile‑first component library built with Vue, supporting TypeScript, on‑demand imports, theming, and Vue3 syntax.

Implement Expand/Collapse

The basic interaction toggles a boolean variable to show or hide the content. A simple implementation uses a show ref and a click handler to invert its value.

<template>
  <div class="container">
    <div class="title" @click="handle">标题</div>
    <div class="content" v-show="show">测试内容测试内容测试内容</div>
  </div>
</template>
<script setup lang="ts">
  import { ref } from 'vue'
  const show = ref(false)
  const handle = () => { show.value = !show.value }
</script>

For smoother animations the component controls the height style directly, calculating the content’s offsetHeight and applying a transition with transform and the CSS will-change property.

will-change informs the browser about upcoming changes, allowing it to optimise rendering for faster, smoother animations.
const wrapperRefEle = wrapperRef.value;
const contentRefEle = contentRef.value;
if (!wrapperRefEle || !contentRefEle) return;
const offsetHeight = contentRefEle.offsetHeight || 'auto';
if (offsetHeight) {
  const contentHeight = `${offsetHeight}px`;
  wrapperRefEle.style.willChange = 'height';
  wrapperRefEle.style.height = proxyData.openExpanded ? contentHeight : 0;
}

Flexible Header

The header can display an icon that rotates 180° when the panel expands. The rotation is controlled by a CSS rotate transform based on the component’s expanded state.

if (parent.props.icon && !proxyData.openExpanded) {
  proxyData.iconStyle['transform'] = 'rotate(0deg)';
} else {
  proxyData.iconStyle['transform'] = `rotate(${parent.props.rotate}deg)`;
}

APIs are exposed for custom icons, rotation angles, and subtitle configuration, enabling diverse use‑cases such as news feeds or notification badges.

Configuration Upgrade

Additional props like sub-title and slot:extraRender allow developers to inject extra content or custom titles via slots, enhancing extensibility.

<view v-if="$slots.extraRender" class="collapse-extraWrapper">
  <div class="collapse-extraRender">
    <slot name="extraRender"></slot>
  </div>
</view>

A disabled prop disables interaction, applying a style that changes cursor and colour.

.nut-collapse-item-disabled {
  color: #c8c9cc;
  cursor: not-allowed;
  pointer-events: none;
}

SCSS Variable Usage

Vue3 allows CSS variables to be bound to component data, enabling dynamic styling directly in the style block.

<template>
  <span>NutUI</span>
</template>
<script>
export default {
  data() { return { color: 'red' } }
}
</script>
<style vars="{ color }" scoped>
  span { color: var(--color); }
</style>

Component Communication (Provide/Inject)

Parent and child components share data via Vue’s provide and inject APIs. The provide function adds key/value pairs to the component’s provides object, while inject looks up the value through the prototype chain, optionally returning a default.

// a.vue – provide
import { defineComponent, provide } from 'vue'
export default defineComponent({
  setup() {
    const msg = 'Hello NutUI'
    provide('msg', msg)
  }
})

// b.vue – inject
import { defineComponent, inject } from 'vue'
export default defineComponent({
  setup() {
    const msg = inject('msg') || ''
  }
})

When using provide in Vue3, the data must be reactive if the consumer expects reactivity. The implementation relies on prototype inheritance to propagate provided values down the component tree.

Summary

The article introduced NutUI’s Collapse component, detailing its design philosophy, animation implementation, flexible header, slot‑based extensions, SCSS variable styling, and Vue3 provide/inject communication, providing practical code snippets to help developers integrate and extend the component efficiently.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Component DesignVue3nutuiCollapse
JD.com Experience Design Center
Written by

JD.com Experience Design Center

Professional, creative, passionate about design. The JD.com User Experience Design Department is committed to creating better e-commerce shopping experiences.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.