Frontend Component Rules
SkillDev toolsVue component structure, styling, derived state, modals, icons, DaisyUI/Tailwind frontend component conventions. Use when editing Vue components, SCSS, or frontend src TypeScript.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Frontend Component Rules skill
What this skill tells your AI
The instructions your AI receives, as published by nerds-odd-e/doughnut in .agents/skills/frontend-component/SKILL.md and read by ahel’s review.
File Organization
- Frontend code lives in
frontend/src/. - Test code lives in
frontend/tests/. - Generated backend API code is in
frontend/src/generated/backend.
Core Technologies
- Vue 3 with TypeScript.
- DaisyUI + Tailwind for styling: unprefixed Tailwind utilities (
flex,text-primary, …) anddaisy--prefixed DaisyUI component classes (daisy-btn,daisy-card, …). - Vitest for testing with Playwright browser mode.
- Biome for linting and formatting.
Icons
- Prefer Lucide for normal UI icons via
@lucide/vue(import { IconName } from "@lucide/vue"). Import only the icons each file needs; rely oncurrentColorso icons follow text/theme color. @lucide/vuedefaults to 24x24 via thesizeprop. Use:size="..."and/or Tailwindw-*,h-*, orsize-*on icons.
Naming Conventions
- Component files should use PascalCase, for example
NoteShow.vueorGlobalBar.vue. - Test files should match component names with a
.spec.tssuffix. - Use
.vuefor components and.tsfor TypeScript files.
Component Structure
<script setup lang="ts">
import { computed, onMounted, ref } from "vue"
const props = defineProps<{
value: string
}>()
const emit = defineEmits<{
(e: "update:value", value: string): void
}>()
const loading = ref(false)
const displayValue = computed(() => props.value.toUpperCase())
const handleClick = () => {
emit("update:value", "new value")
}
onMounted(() => {
// ...
})
</script>
<template>
<div class="daisy-component">
<!-- template content -->
</div>
</template>
<style scoped lang="scss">
// scoped styles
</style>
Modals And Dialogs
- Use
Modalfrom@/components/commons/Modal.vuefor modal overlays. It wraps a native<dialog>teleported tobodyand centralizes stacking, ESC, backdrop click, and route-change close. The dim background is the native::backdroppseudo-element. - Put panel content in
#body, optionally#header. Listen for@close_requestto hide the modal, such as parentv-ifor clearing model state. The overlay X is optional viashowCloseButtononModal. - Use
v-ifonModalwhen the dialog opens, or keepModalmounted and drive visibility from props; wireclose_requestand cancel buttons to the same close handler. - Layout variants:
alignToppins the panel to the top of the viewport,sidebar="left" | "right"renders a full-height side panel. UseisPopupfor nested popups viausePopupsso they do not participate in the ESC modal stack. - In tests, the dialog renders inside
document.body. Query the DOM viadocument.querySelector("dialog"),.close-button,.modal-container,.modal-sidebar, or.modal-mask, not the dialog's internal layout wrapper.
Derived State
- Avoid cache state in refs. Do not keep a separate
reforreactivefield that mirrors props, other refs, or store data and that you update in watchers,onUpdated, or event handlers to stay in sync. - Prefer
computedwhenever a value is fully determined by reactive inputs. Computed values stay correct when dependencies change and avoid manual sync. - Use
ref/reactivefor real mutable state: user input, explicit UI toggles, or data you own and mutate.
CSS And Styling
- Use DaisyUI classes with the
daisy-prefix, for exampledaisy-btnordaisy-alert. - Avoid Bootstrap classes.
- Choose theme-neutral colors.
- Use scoped styles with SCSS.
- Follow mobile-first responsive design.
Signals
- GitHub stars
- 49
- Forks
- 72
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
frontend-component- Source
- github.com/nerds-odd-e/doughnut