-
Notifications
You must be signed in to change notification settings - Fork 3
Code conventions
Optimizing code for readability - we spend much more time looking at the code. Better write more of encapsulated code than fewer lines of code on one place.
- Postcss https://postcss.org/
- BEM https://en.bem.info/methodology/
- ITCSS https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/
- Pinia store https://pinia.vuejs.org/
- Composition API https://vuejs.org/guide/extras/composition-api-faq.html
- Aha Programming - Avoid Hasty abstractions. A bit of duplication is fine. Optimizing code for change. https://kentcdodds.com/blog/aha-programming/
- Inspiration comes from Bootstrap. If on doubt from many valid patterns, let's take inspiration from https://getbootstrap.com
In BEM every styled element needs to be named. Also has the advantage when considering specificity.
❌ Bad:
video {
width: 100%
}
✔️ Good:
.preview-file__video {
width: 100%
}
Classname should express what element is, not what it looks like.
❌ Bad:
.element--yellow {
color: yellow;
}
✔️ Good:
.element--warning {
color: yellow;
}
This is actually BEM antipattern. Creating this dependency is the nastiest part of CSS causing unwanted results. Come up with better BEM naming or componentize one level more.
❌ Bad:
.button .icon {
color: red
}
✔️ Good:
.button__icon {
color: red
}
The element
part of the naming should be as flat as possible. Avoid unnecessary dependent naming
❌ Bad:
<ul :class="user__list">
<li :class="user__list-item">
<a class="user__list-item-link"/>
</li>
</ul>
✔️ Good:
<ul :class="user__list">
<li :class="user__item">
<a class="user__link"/>
</li>
</ul>
For sizing we use bootstrap style sizing https://getbootstrap.com/docs/4.1/layout/grid/
[xs] [sm] [md] [lg] [xl]
If sizing run out of scale of 5 levels - use just numbers -1
, -2
, ...
❌ Bad:
<button class="button button--huge"/>
✔️ Good:
<button class="button button--xl"/
If there is no technical limitation - use full names to avoid mental mapping. Exception could be widely domain-known shorthand(such as: tx)
❌ Bad:
<button class="btn btn-dbu"/>
✔️ Good:
<button class="button button--disabled"/>
You can come up with naming from UI or product perspective for the same element. The preferred is UI perspective as long as it makes sense in context (of component)
✔️ Good (preferred):
<input class="user-form__input"/>
✔️ Good:
<input class="user-form__first-name"/>
Its time saving and more readable when every component holds the same convention. Put positioning related properties
like flex
, display
, position
at the top. Colors and whitespacings like background
, margin
, padding
can be
at the bottom. Try to glue similar things like font-size
, line-height
, font-weight
together for context.
No strict rules here, just make it nice to read and consistent over the app. You can always inspire from surrounding components. If you wanna play nice do some Enter paddings .]
❌ Bad:
.loading {
background: var(--gray-300);
font-size: 14px;
line-height: 19px;
flex-direction: column;
display: flex;
animation: scale 4.5s ease-in-out infinite;
align-items: center;
height: 240px;
border-radius: 100%;
margin-top: var(--space-4);
}
✔️ Good:
.loading {
display: flex;
flex-direction: column;
align-items: center;
height: 240px;
border-radius: 100%;
font-size: 14px;
line-height: 19px;
margin-top: var(--space-4);
background: var(--gray-300);
animation: scale 4.5s ease-in-out infinite;
}
The intention of these suggestions is consistency and avoiding pitfalls.
Use body
over content
. Means the same, but body
is extensible to accommodate with headers and footers.
❌ Bad:
<div class="loading__content"/>
✔️ Good:
<div class="loading__body"/>
For technical CSS limitations, sometimes is needed to wrap an element.
Let's call it container
, not wrap
nor wrapper
❌ Bad:
<div class="loading__wrap"/>
✔️ Good:
<div class="loading__container"/>
Container for buttons or action elements is called controls
❌ Bad:
<div class="dialogue-message-consumer__container">
<button @click="parse"/>
<button @reset-clicked="clear"/>
</div>
✔️ Good:
<div class="dialogue-message-consumer__controls">
<button @click="parse"/>
<button @reset-clicked="clear"/>
</div>
Here are some common mistakes when naming variables or functions and some suggestions on how to fix them. These examples may be confusing, too general, quickly goes into conflict, or express f subjective evaluation. There may be cases where these would be valid of course
data -> details
info -> description
type -> variant
type -> [whatever else more specific]Type
item -> [whatever else more specific]
item -> [whatever else more specific]Item
value -> formattedValue
result -> response -> [whatever else more specific]
text -> heading
text -> paragraph
text -> description
text -> [whatever else more specific]Text
box -> container
box -> input
pretty -> formatted
New Entity
-> (fill details) -> Create Entity
Edit Entity
-> (change details) -> Save Entity
Delete Entity
-> Are you sure? modal -> Delete Entity Forever
For proper component isolation, component root element should be free of whitespacing. Spacing of component should be done on parent level. This should be done on styles level. No need to parametrize styles through props.
❌ Bad:
<template>
<user-item>
<user-item>
<user-item :no-bottom-padding="true">
</template>
✔️ Good:
<template>
<user-item class="user-list__item">
<user-item class="user-list__item">
<user-item class="user-list__item">
</template>
<styles>
.user-list__item {
margin: 16px;
&:last-of-type {
margin: 0;
}
}
</styles>
As for the method length, components easily grow larger. In most cases, there is no such thing aso over-componentization. The opposite true. Lets keep components on reasonable length. Personal preference 150 lines of code.
Event represents action and bound method represents reaction. So the way that you read is: when something happened -> then do this. This is a self-imposed rule, but its nothing against Vue styleguide.
❌ Bad:
<button @send-button-press="uploadImage()"/>
✔️ Good:
<button @send-button-pressed="uploadImage()"/>
Keep the template part free from logic. A nice place to accommodate logic is in computed
block. If the condition should be
a composite of 2 or more conditions, extract them to computed
. The new name of the computed condition should reflect what UI is
doing.
❌ Bad:
<template>
<button v-if="!isLoading || userCount > 1 && isTraining">
</template>
✔️ Good:
<template>
<button v-if="isButtonHidden"/>
</template>
<script>
computed: {
isButtonHidden () {
return this.isLoading || this.userCount > 1 && this.isTraining
}
}
</script>
Components are written inPascalCase, minimum 2 words.
Component name should consist of Domain of the feature and Element type (preferably imitating known UI patterns).
Component can also be named with the modifier state. Mostly when componentizing complex state
behaviour. dialogue__message--delivered
-> DialogueMessageDelivered.vue
❌ Bad:
ComingSoon.vue
LayoutLogin.vue
✔️ Good:
LoginLayout.vue
ChatForm.vue
BotCard.vue
DialogueActionMenu.vue
TrainingButton.vue
raw
as an input for data manipulation (getter) we need to somehow manipulate.
❌ Bad:
const details = ref(null)
const detailsFomatted = computed(() => adaptDetails(details .value)
✔️ Good:
const rawDetails = ref(null)
const details = computed(() => adaptDetails(rawDetails.value)