• Stars
    star
    1,132
  • Rank 41,129 (Top 0.9 %)
  • Language
  • License
    MIT License
  • Created over 3 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

πŸ“ Front-end Guideline by Juntos Somos Mais

juntos-somos-devs

Front-end - Guideline

Guideline Webpage

GitHub contributors GitHub contributors

"Every line of code should appear to be written by a single person, no matter the number of contributors." - Chinese Proverb.

The following document describes generic rules of writing in development languages that we use on our Front-end projects, that HTML, CSS, JavaScript, React, and Vue

The idea of this repository is not to be a complete guideline, the target is just to help developers who participate in our projects to be able to inform the coding standards used.

As this is a live document, some rules may not have been applied in old projects and changes can occur at any time.

We are hiring! πŸ”₯

If you are looking opportunities as Front-end Developer we are hiring!

You can check all our job opportunities and apply if you like it 😁

This is our Front-end Challenge

πŸ“– Summary

  1. General Code Patterns
  2. Architecture
  3. Git
  4. HTML
  5. CSS
  6. JavaScript
  7. React
  8. Vue
  9. Storybook
  10. Testing
  11. Typescript
  12. Google Tag Manager

1. General Code Patterns

1.1 Code Syntax

Use soft tabs with two spaces. You need to configure your editor for this.

βœ… Good:

const obj = {
  prop: 'value',
  prop2: 'value2',
  prop3: 'value3',
}
.foo {
  color: red;
}
<div>
  <p>Hello World</p>
</div>

❌ Bad:

const obj = {
    prop: 'value',
    prop2: 'value2',
    prop3: 'value3',
}
.foo {
    color: red;
}
<div>
    <p>Hello World</p>
</div>

1.2 Refactoring

Refactoring makes part of JSMLover's way of being, doing it every day and task by task. We have good practices and conditions to do that, though.

if(!isWholeCodeCoveraged) return
  • We can only refactor codes that have tests (and that tests!), which means 100% coverage! This way, we can improve or code safely.

  • Keep the current tests and make them pass! Once the current code is tested and can be refactored. We must make sure that the new changes will not break the current tests.

1.3 Imports

If the data to be imported belongs to the same module/scope, use relative path.

Relative Path Example

HeaderButton.js importing style from header/styles.css`

┣ πŸ“‚ src/components \
┣ ┣ πŸ“‚ header \
┣ ┃ ┣ πŸ“‚ components
┣ ┃ ┣ ┣ πŸ“‚ Buttons
┣ ┃ ┣ ┣ ┣ πŸ“œ HeaderButton.js
┣ ┃ ┣ ┣ ┣ πŸ“œ RedirectButton.js
┣ ┃ ┣ ┣ ┣ πŸ“œ EspecificButton.js
┣ ┃ ┣ ┣ πŸ“‚ Card 
┣ ┃ ┣ ┣ πŸ“‚ Modal 
┣ ┃ ┣ πŸ“‚ __tests__
┣ ┃ πŸ“œ index.js
┣ ┃ πŸ“œ styles.css
┣ ┃ πŸ“œ index.stories.mdx
┣ ┃ πŸ“œ index.spec.js

use this:

import { HeaderButtonClass } from '../../../styles'

If the data to be imported belongs to another module/scope, use an absolute path.

Absolute Path Example

HeaderPopup.js importing an enum from src/enum/errors.js

┣ πŸ“‚ src \
┣ ┣ πŸ“‚ components \
┣ ┃ ┣ πŸ“‚ header \
┣ ┃ ┃ ┣ πŸ“‚ components
┣ ┃ ┃ ┃ ┣ πŸ“‚ Card 
┣ ┃ ┃ ┃ ┣ πŸ“‚ Popup
┣ ┃ ┃ ┃ ┃ ┣ πŸ“œ HeaderPopup.js
┣ ┃ ┃ ┃ ┃ ┣ πŸ“œ RedirectPopup.js
┣ ┃ ┃ ┃ ┃ ┣ πŸ“œ EspecificPopup.js
┣ ┃ ┃ ┣ πŸ“‚ __tests__
┣ ┃ ┣ πŸ“œ index.js
┣ ┃ ┣ πŸ“œ styles.scss
┣ ┃ ┣ πŸ“œ index.stories.mdx
┣ ┃ ┣ πŸ“œ index.spec.js
┣ ┃ πŸ“‚ enums \
┣ ┃ ┣ πŸ“œ errors.js
┣ ┃ ┣ πŸ“œ pages.js
┣ ┃ ┣ πŸ“œ routes.js
┣ ┃ ┣ πŸ“œ environments.js
┣ ┃ ┣ πŸ“œ index.js

use this:

import { UploadError } from '~/enums'

Note:

Is also a good practice to create an index.js file for exporting data belonging to the same folder, as we can see example above.

export * from './errors'
export * from './pages'
export * from './routes'
export * from './environments'

2. Architecture

The proper architecture for projects, and how to create and name files and folders.

2.1 File Name

βœ… Good:

  • UserProfile/UserProfile.vue
  • UserProfile/index.js
  • UserProfile/index.ts
  • UserProfile/styles.js
  • UserProfile/UserProfile.scss
  • UserProfile/UserProfile.stories.mdx

❌ Bad:

  • UserProfile/component.vue
  • src/UserProfile.js
  • UserProfile/component.ts
  • UserProfile/style.scss
  • UserProfileStyles.js
  • UserProfile/UserProfile.mdx

2.2 Folder Architecture

Global Components/Helpers

Global Components should only be components used in more than one place.

For example:

┣ πŸ“‚ src/components \
┣ ┣ πŸ“‚ component \
┣ ┃ ┣ πŸ“œ index.js
┣ ┃ ┣ πŸ“œ styles.js
┣ ┃ ┣ πŸ“œ index.spec.js
┣ ┃ ┣ πŸ“œ index.stories.mdx

Scoped Components

We need to add inside pages/**/components, for example, all components that is need used just a context or scope, like a components that be used just a some place or specific page.

If we need to used the component again in another context or page it need to be moved to src/components.

For example:

┣ πŸ“‚ pages \
┣ ┣ πŸ“‚ Home \
┣ ┃ ┣ πŸ“œ Home.js \
┣ ┃ ┣ πŸ“œ Home.style.js \
┣ ┃ ┣ πŸ“œ Home.spec.js \
┣ ┃ ┣ πŸ“‚ components \
┣ ┃ ┃ ┣ πŸ“‚ UserProfile \
┣ ┣ ┃ ┃ ┣ πŸ“œ UserProfile.style.js \
┣ ┣ ┃ ┃ ┣ πŸ“œ UserProfile.spec.js \
┣ ┣ ┃ ┃ ┣ πŸ“œ UserProfile.stories.mdx \

Scoped Files

We need to add inside pages/**/{utils, helpers, context, hooks, etc...} and use camelCase as Naming Convention.

For example:

┣ πŸ“‚ pages \
┣ ┣ πŸ“‚ Home \
┣ ┃ ┣ πŸ“‚ utils \
┣ ┃ ┣ ┣ πŸ“œ someUtils.js
┣ ┃ ┣ πŸ“‚ helpers \
┣ ┣ ┣ ┣ πŸ“œ someHelper.js
┣ ┃ ┣ πŸ“‚ hooks \
┣ ┣ ┣ ┣ πŸ“œ useSomeHook.js

If we need use these files again in another context or page it need to be moved to src/{utils, helpers, context, hooks}.

┣ πŸ“‚ src
┣ ┣ πŸ“‚ utils \
┣ ┃ ┣ πŸ“œ someUtils.js
┣ ┣ πŸ“‚ helpers \
┣ ┃ ┣ πŸ“œ someHelper.js
┣ ┣ πŸ“‚ hooks \
┣ ┃ ┣ πŸ“œ useSomeHook.js

⬆ back to summary


3. Git

3.1 Commit Messages

In order to facilitate the contribution of anyone in a project, all commit messages must be in English.

We also use conventional commit messages, that is, the commit message must be in the form of a sentence, with the first word being an action, and the rest of the sentence a describing text.

βœ… Good:

git commit -m "feat: allow provided config object to extend configs"
git commit -m "docs: correct spelling of CHANGELOG"
git commit -m "feat(lang): add the Portuguese language"

❌ Bad:

git commit -m "Add placeholder on input"

⬆ back to summary


4. HTML

We main reference for HTML good patterns is W3C and MDN, behind these docs we could learn a lot with semantic and another good practices.

4.1 HTML Component Scope

We don't guest the scope of HTML components inside page, so when we start a new component, we should use a semantic tag, like section or article for example, to be able to starting to use the heading tags by context.

βœ… Good:

<section class="component">
  <h1 class="title">Title</h1>
  <p>Paragraph</p>
</section>

❌ Bad:

<div class="component">
  <h4 class="title">Title</h4>
  <p>Paragraph</p>
</div>

5. CSS

The tips above could be used in any CSS framework or preprocessor, like SCSS, Styled Components and etc

5.1 CSS Syntax

Keep one declaration per line.

βœ… Good:

.selector-1,
.selector-2,
.selector-3 {
  ...
}

❌ Bad:

.selector-1, .selector-2, .selector-3 {
  ...
}

Separate each ruleset by a blank line.

βœ… Good:

.selector-1 {
  ...
}

.selector-2 {
  ...
}

❌ Bad:

.selector-1 {
  ...
}
.selector-2 {
  ...
}

Use lowercase and avoid specifying units is zero-values.

βœ… Good:

.selector-1 {
  color: #aaa;
  margin: 0;
}

❌ Bad:

.selector-1 {
  color: #aaaaaa;
  margin: 0px;
}

5.2 CSS Declaration Order

The declarations should be added in alphabetical order.

βœ… Good:

.selector {
  background: #fff;
  border: #333 solid 1px;
  color: #333;
  display: flex;
  height: 200px;
  margin: 5px;
  padding: 5px;
  width: 200px;
}

❌ Bad:

.selector {
  padding: 5px;
  height: 200px;
  background: #fff;
  margin: 5px;
  width: 200px;
  color: #333;
  border: #333 solid 1px;
  display: flex;
}

5.3 CSS Class Names

Keep class lowercase and use dashes to separate the classname.

βœ… Good:

.page-header { ... }

❌ Bad:

.pageHeader { ... }
.page_header { ... }

Is a good idea follows a BEM naming convention to avoid conflicts with other components. If you are using CSS-in-JS like a Styled-Component, you can use BEM if you need to nesting elements inside parent.

The main pattern is use single dash to element name, double underline to element block and double dash to style modification.

βœ… Good:

/* Good */
.page-header__title { ... }
.page-header--active { ... }

.button--active { ... }

❌ Bad:

.page-header-title { ... }
.page-header-active { ... }

.active { ... }
.primary { ... }

Dashes and underline serve as natural breaks in related class. Prefix class based on the closest parent or base class.

βœ… Good:

.nav { ... }
.nav__item { ... }
.nav__link { ... }

❌ Bad:

.item-nav { ... }
.link-nav { ... }

Avoid giving too short names for class and always choose meaningful names that provide the class function.

βœ… Good:

/* Good */
.button { ... }
.page-header { ... }
.progress-bar { ... }

❌ Bad:

.s { ... }
.btn { ... }
.ph { ... }
.block { ... }

5.4 CSS Good Practices

Avoid use values like colors, spacing and etc directly in the elements, use variables instead, and it can be CSS variables or some preprocessor variables, always check the context.

βœ… Good:

.button {
  color: var(--color-primary);
  padding: var(--space-sm);
}

❌ Bad:

.button {
  color: #333;
  padding: 16px;
}

Never use IDs to style elements, always use classes instead.

βœ… Good:

.header { ... }
.section { ... }

❌ Bad:

#header { ... }
#section { ... }

Do not style directly the elements, it will create a lot of conflicts, always use classes instead.

βœ… Good:

.form-control { ... }
.header { ... }
.section { ... }

❌ Bad:

input[type="text"] { ... }
header
section

Avoid nesting elements, because it decrease performance and increase the specificity of the CSS, always use classes instead.

βœ… Good:

.navbar { ... }
.nav { ... }
.nav__item { ... }
.nav__link { ... }

❌ Bad:

.navbar ul { ... }
.navbar ul li { ... }
.navbar ul li a { ... }

5.5 CSS Media Queries

Start the development with generic rules and add media queries inside scope using mobile first. Also is important keep the media queries as close to their relevant rule sets whenever possible.

βœ… Good:

.navbar {
  margin-bottom: var(--space);

  @media (min-width: 480px) {
    padding: 10px;
  }

  @media (min-width: 768px) {
    position: absolute;
    top: 0;
    left: 0;
  }

  @media (min-width: 992px) {
    position: fixed;
  }
}

❌ Bad:

.navbar {
  position: fixed;
  top: 0;
  left: 0;

  @media (max-width: 767px) {
    position: static;
    padding: var(--space-sm);
  }
}

5.6 Spacing and size of image and components

Is a commom problem to use width and height or all dynamic or all hardcoded, but each one has it own purpose. We should avoid using magic numbers at all times.

"Magic numbers are those numbers that appear in code without explanation, but that 'magically' make things work." Are numbers that dont have a why, but works.

5.6.1 Dynamic values

If you are using padding, margin, gap should use our Venices's spacing variables. Any space that override it values must be validated once our Design System is well defined around these values and our UX Teams guide must follow it. Icons, width and height that are relative to our Design System or that have sizes based on calc upon our spacing variable must also use Venices's spacing variables instead of magic numbers.

βœ… Good:

.logout__icon {
  height: var(--spacing-xxlarge);
  width: var(--spacing-xxlarge);
}

.icon__button {
  min-width: var(--spacing-giant);
} 

❌ Bad:

.logout__icon {
  height: 25px;
  width: 25px;
}

.icon__button {
  min-width: 34px;
}

5.6.2 Images and well defined components

If you are using a image, or a component that has a design size and it sizes at maximum vary from desktop/mobile, use the value of it:

βœ… Good:

.shopfrom__banner {
  height: 900px;
  width: 480px;
  
  @media (min-width: 991px) {
    height: 740px;
    width: 240px;
  }
}

❌ Bad:

.shopfrom__banner {
  height: calc(4 * var(--spaceing-xxxlarge);
  width: calc(2 * var(--spacing-giant);
}
// or
.shopfrom__banner {
  height: 480px;
  width: 170px;
  
  @media (max-width: 746px) {
    height: 740px;
    width: 240px;
  }
  
  @media (max-width: 991px) {
    height: 900px;
    width: 320px;
  }
  
  @media (max-width: 1024px) {
    height: 980px;
    width: 300px;
  }
}

⬆ back to summary

6. JavaScript

6.1 JavaScript Code Syntax

Never use semicolons.

βœ… Good:

const foo = 'bar'
const baz = 'qux'
const func = () => {}

❌ Bad:

const foo = 'bar';
const baz = 'qux';
const func = () => {};

Always use single quotes or template literals

βœ… Good:

const string = 'foo'
const template = `foo`

❌ Bad:

const string = "foo"
const template = "foo"

For strict equality checks === should be used in favor of ==.

βœ… Good:

if (foo === 'foo') {
  statement
}

❌ Bad:

if (foo == 'foo') {
  statement
}

6.2 Variables

Use meaningful, pronounceable, and in English variable names.

βœ… Good:

const currentDate = new Date().toLocaleDateString('pt-BR')

❌ Bad:

const xpto = new Date().toLocaleDateString('pt-BR')

6.3 Descriptive validations (if)

Creating const to describe validations.

βœ… Good:

const hasFullUserName = user.firstName && user.lastname

if (hasFullUserName) {
  //do awesome something
}

❌ Bad:

if (user.firstName && user.lastname) {
  //do something
}

6.4 Avoid multiple if's

Use an execution map instead a multiple if validations.

βœ… Good:

const messagingChannels = {
  whatsapp: (message) => {
    // send message to whatsapp
  },
  email: (message) => {
    // send message to email
  }
}

const sendMessage = (message, channel) => {
  const send = messagingChannels[channel];
  return send && send(message);
}

❌ Bad:

const sendWhatsapp = (message) => {
  // send message to whatsapp
}

const sendEmail = (message) => {
  // send message to email
}

const sendMessage = (message, channel) => {
  if (channel === 'whatsapp') {
    sendWhatsapp(message)
  } else if (channel === 'email') {
    sendEmail(message)
  }
}

6.5 Code Comments

Avoid writing comments to explain the code. Use comments to answer β€œWhy?” instead β€œHow?”. Some cases you could write a code comment: warnings, complex expressions, or unusual decision clarification.

βœ… Good:

  const TIME_IN_SECONDS = 60 * 40 // 40 minutes

  // xxxx@xxxx.xxx
  const regex = /^[a-z0-9.]+@[a-z0-9]+\.[a-z]+\.([a-z]+)?$/i

  const calculateProductsPrice = () => {
    // do something
  }

❌ Bad:

  // This coolFunction calculates the prices of the products
  const coolFunction = () => {
    // do something
  }

6.6 Avoid errors while destructuring

Its a common mistake destructuring while the object is null or undefined, the destructuring will throw an error.

βœ… Good:

  const { age } = { ...null } // undefined
  const { age } = null || {} // undefined

  // other values won't throw an error
  const { emptyString } = '';
  const { nan } = NaN;
  const { emptyObject } = {};

  function foo(bar = {}) {
    const { age } = bar;
  }
  
  foo() // undefined
  

❌ Bad:

  const { age } = null // will throw an typeError
  const { age } = undefined // will throw an typeError

6.7 Prefer early return

Prefer early return over conditional wrapping to enhance code readability and reduce nesting.

βœ… Good:

function foo() {
  if (!someValidation) return // or throw error

  // do something here

  if (!anotherValidation) return

  return 'bar'
}

❌ Bad:

function foo() {
  if (someValidation) {
    // do something here

    if (anotherValidation) {
      return 'bar'
    }
  }
}

⬆ back to summary


7. React

7.1 Keys in lists

The best way to pick a key is to use a string that uniquely identifies a list item among its siblings.

It is not recommended to use indexes for keys if the order of items can change. This can negatively affect performance and can cause problems with the component's state.

βœ… Good:

array.map((item, index) => <Component key={item.id} {...item}>)

❌ Bad:

array.map((item, index) => <Component key={index} {...item}>)

7.2 useState functional updates

If the new state is calculated using the previous state, you can pass a function to setState. Thus avoiding competition between states and preventing possible bugs.

βœ… Good:

const [number, setNumber] = useState(1)

return (
  <div>
    <h1>{number}</h1>
    <button onClick={() => setNumber((prevNumber) => prevNumber + 1)}>
      Increase
    </button>
    <button onClick={() => setNumber((prevNumber) => prevNumber - 1)}>
      Decrease
    </button>
  </div>
)

❌ Bad:

const [number, setNumber] = useState(1)

return (
  <div>
    <h1>{number}</h1>
    <button onClick={() => setNumber(number + 1)}>Increase</button>
    <button onClick={() => setNumber(number - 1}>Decrease</button>
  </div>
)

7.3 useEffect dependencies array

Use the useEffect dependency array to trigger side effects, and make your code cleaner.

βœ… Good:

const [page, setPage] = useState(1)

useEffect(() => {
  requestListUser()
  // calls useEffect when page state changes
}, [page])

return (
  <div>
    <button onClick={() => setPage((prevState) => prevState + 1)}>
      Next Page
    </button>
  </div>
)

❌ Bad:

const [page, setPage] = useState(1)

useEffect(() => {
  requestListUser()
}, [])

const requestListUser = () => {
  setPage((prevState) => prevState + 1)
  // ...
  // any code to return user list
}

return (
  <div>
    <button onClick={() => requestListUser()}>Next Page</button>
  </div>
)

7.4 Readable components

Avoid creating very large components. If possible divided into sub-components, improving the understanding and reading of the code.

βœ… Good:

const Screen = () => (
  <Container>
    <Header>
      <Title />
      <Button background="black">Filter</Button>
    </Header>

    <Main>
      <List>
        {data.map((item) => (
          <Card key={item.id} name={item.name} />
        ))}
      </List>
    </Main>
  </Container>
)

❌ Bad:

const Screen = () => (
  <Box padding={1}>
    <Box alignItems="center">
      <Text>Titulo</Text>
      <Button background="black">Filter</Button>
    </Box>
    <Box marginTop={5}>
      <Box>
        {data.map((item) => (
          <Box key={item.id}>
            <Text color="red">{item.name}</Text>
          </Box>
        ))}
      </Box>
    </Box>
  </Box>
)

7.5 Styled Component Naming Convention

Use PascalCase as a convention in styled-components

βœ… Good:

export const CustomText = styled.p`
  color: 'red'
`

❌ Bad:

export const customText = styled.p`
  color: 'red'
`

7.6 Using Styled Component in React Components

Import Styled Component as S

βœ… Good:

import * as S from './styles'

const MyComponent = () => (
  <S.CustomText>
    text example
  </S.CustomText>
)

❌ Bad:

import * as Style from './styles'

const MyComponent = () => (
  <Style.CustomText>
    text example
  </Style.CustomText>
)


import { CustomText } from './styles'

const MyComponent = () => (
  <CustomText>
    text example
  </CustomText>
)

7.7 Avoid compare directly strings

When know all possible values we can use enum to achieve better readability and control.

βœ… Good:

const FEEDBACK = {
  CORRECT: 'correct',
  INCORRECT: 'incorrect',
}

const MyComponent = (type) => {
  const text = type === FEEDBACK.CORRECT ? '😎' : '😒'
  
  return (
    <Emoji>
      {text}
    </Emoji>
  )
}

❌ Bad:

const MyComponent = (type) => {
  const text = type === 'correct' ? '😎' : '😒'

  return (
    <Emoji>
      {text}
    </Emoji>
  )
}

7.8 Using spread operator

When creating a component wrapper we can spread the types from our original component. That way the wrapper extends all the props from the original component automatically. This is useful to avoid creating a custom interface for our wrapper with missing props from the original component.

βœ… Good:

import { MenuItem, TextField } from '@mui/material';
import { TextFieldProps } from '@mui/material';

export type SelectOption = { value: string; label: string, id: string, };

export type SelectProps = TextFieldProps & {
  options: SelectOption[];
};

const Select = ({ options, ...props }: SelectProps) => {
  return (
    <TextField {...props}>
      {options.map((option) => (
        <MenuItem key={option.id} value={option.value}>
          {option.label}
        </MenuItem>
      ))}
    </TextField>
  );
};

❌ Bad:

import { MenuItem, TextField } from '@mui/material';

export type SelectOption = { value: string; label: string, id: string, };

export type SelectProps = {
  options: SelectOption[];
  disabled: boolean;
  onChange: () => void;
  value: string;
  onBlur: () => void;
};

const Select = ({
  options,
  disabled,
  onChange,
  value,
  onBlur,
} : SelectProps) => {
  return (
    <TextField
      disabled={disabled}
      onChange={handleOnChange}
      value={value}
      onBlur={handleOnBlur}
    >
      {options.map((option) => (
        <MenuItem key={option.id} value={option.value}>
          {option.label}
        </MenuItem>
      ))}
    </TextField>
  );
};

7.9 Conditional Rendering

7.9.1 Using short circuit

when we only need to validate a logical case and return a component, we can directly use the short circuit

βœ… Good:

import { useState } from 'react'
import Welcome from '../components/Welcome'

const HomePage = () => {
  const [showWelcome, setShowWelcome] = useState(true)
  return showWelcome && <Welcome />
};

❌ Bad:

import { useState } from 'react'
import Welcome from '../components/Welcome'

const HomePage = () => {
  const [showWelcome, setShowWelcome] = useState(true)
  return showWelcome ? <Welcome /> : <></>
};

7.9.2 Using ternary operator

when we need to validate two logical cases and return a component in both cases, we can use the ternary instead of the if...else

βœ… Good:

import { useState } from 'react'
import Welcome from '../components/Welcome'
import Dashboard from '../components/Dashboard'

const HomePage = () => {
  const [showWelcome, setShowWelcome] = useState(false)
  return showWelcome ? <Welcome /> : <Dashboard />
};

❌ Bad:

import { useState } from "react"
import Welcome from "../components/Welcome"
import Dashboard from "../components/Dashboard"

const HomePage = () => {
  const [showWelcome, setShowWelcome] = useState(false)

  if (!showWelcome) {
    return <Dashboard />
  }

  return <Welcome />
};

⬆ back to summary


8. Vue

8.1 Keys in lists

The best way to pick a key is to use a string that uniquely identifies a list item among its siblings.

It is not recommended to use indexes for keys if the order of items can change. This can negatively affect performance and can cause problems with the component's state.

βœ… Good:

<template v-for="item in items">
   <Component :key="item.id" v-bind="{...item}">
</template>

❌ Bad:

<template v-for="(item, index) in items">
   <Component :key="index" v-bind="{...item}">
</template>

8.2 Use Computed for real time updates

If you need listen changes at data use computeds instead of methods

βœ… Good:

computed: {
  fullName(){
    return `${this.name} ${this.lastName}`
  }
}

❌ Bad:

methods: {
  fullName() {
    this.fullName = `${this.name} ${this.lastName}`
  }
}

8.3 Multi-word component names

Component names should always be multi-word, except for root App components, and built-in components provided by Vue.

This prevents conflicts with existing and future HTML elements, since all HTML elements are a single word.

βœ… Good:

export default {
  name: 'TodoItem',
  // ...
}

❌ Bad:

export default {
  name: 'Todo',
  // ...
}

8.4 Prop definitions

In committed code, prop definitions should always be as detailed as possible, specifying at least type(s).

βœ… Good:

export default {
  status: {
    type: String,
    required: true
  }
  // ...
}

❌ Bad:

export default {
  props: ['status']
  // ...
}

8.5 Vue property decorator

Vue prop decorator should not be used, use Vue.extend instead

βœ… Good:

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  name: 'MyComponent',
})
</script>

❌ Bad:

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'

@Component({})
export default class MyComponent extends Vue {
  name: 'MyComponent'
}
</script>

⬆ back to summary


9. Storybook

9.1 Story file

Create a file with the same name of your component, or index, and with the suffix .stories.mdx.

βœ… Good:

  • Button.stories.mdx
  • Dialog/index.stories.mdx

❌ Bad:

  • Input.mdx
  • Dialog/index.mdx

⬆ back to summary


10. Testing

10.1 Write tests with "it"

Write tests with the alias "it" instead "test" method.

βœ… Good:

describe('yourModule', () => {
  it('should do this thing', () => {});
});

❌ Bad:

describe('yourModule', () => {
  test('if it does this thing', () => {});
});

10.2 Using test-id

To get components during tests we use test-id custom html attributes with unique id and our own convention deeply inpired by the css's BEM. To define the test-id to a component use the follow structure: [page-name||component-name]__[element-type]--[type]

βœ… Good:

  • forgot-password__input--email
  • header__select--cnpjList
  • login__button--forgot-password

❌ Bad:

  • forgot-email-input
  • header__cnpjList
  • button--forgot-password

10.3 Selecting component

To select a component in order to test a behavior of to trigger any event we must use ou test-id attribute to select it.

βœ… Good:

describe('yourModule', () => {
  it('should do trigger click event', () => {
    const button = wrapper.find('[data-testid="login__button--forgot-password"]')
  });
});

❌ Bad:

describe('yourModule', () => {
  it('should do trigger click event', () => {
    const button = wrapper.find('button.btn-primary')
  });
});

⬆ back to summary


11. Typescript

11.1 Do not use any type

Avoid using any type. It's best to use the type that is more specific whenever possible. Prefer to use unknown when necessary.

βœ… Good:

function foo(x: unknown) {}

function foo(): unknown {}

❌ Bad:

function foo(x: any) {}

function foo(): any {}

11.2 Naming convention

For convention, use PascalCase for type names.

βœ… Good:

type MyBeautifulType = {
  name: string
  age: number
}

❌ Bad:

type myBeautifulType = {
  name: string
  age: number
}

The same to Enum keys.

βœ… Good:

enum UserResponse {
  NotSuccess = 0,
  Success = 1,
}

❌ Bad:

enum UserResponse {
  NOT_SUCCESS = 0,
  success = 1,
}

11.3 Exporting types

Do not export types/functions unless you need to use it across multiple components.

11.4 Types within a file

Within a file, type definitions should come first.

βœ… Good:

// imports...

type MyBeautifulType = {
  name: string
  age: number
}

// rest of the file...

❌ Bad:

// imports...

// part of the file...

type MyBeautifulType = {
  name: string
  age: number
}

// rest of the file...

11.5 Increase legible

Create a type for increase legible

βœ… Good:

type PersonType = {
  name: string
  age: number
  birthDate: string
};

const Person = ({ name, age, birthDate }: PersonType) => {
  // ...
};

❌ Bad:

const Person = ({
  name,
  age,
  birthDate,
}: {
  name: string,
  age: number,
  birthDate: string,
}) => {
  // ...
};

12. Google Tag Manager

12.1 What is Google Tag Manager

It is a free installation tool, which simplifies tag integration and concentrates all tags on a single board. Essential for tracking site-wide metrics.

12.2 Tags GTM

Tags are small snippets of code created to monitor actions. Example: analytics tags, conversion Tags, event monitoring tags, Third-party tags...

12.3 What are triggers and what types of GTM triggers

They serve as the basis for the tag that we will trigger in GTM. This means that every tag installed on our site will have a trigger configured to fulfill the established function. Some of them are: click, time, form, browser history, page views...

12.4 What are variables inside GTM

They are used for harvesting, storing and transmit data between different GTM Components. Variables can be created from: Environment, Data, System, customized. And, just like triggers, they must be configured correctly so that this monitoring is carried out as assertively as possible.

12.5 linked tools

link Google Analytics and Google Tag Manager: In the lower left corner of the screen, click on the "Administrator" button. This administration page is divided into two halves: on the left we have Account Settings; on the right, Property Settings. and in the second column we will click on Data flow. On this next page, the website linked to this Analytics account will be shown in the center of the screen: Site JS+ (https://loja.juntossomosmais.com.br/) What we want from all this information is the "Metric ID". It is essential to link this account to GTM. Example METRIC ID: G-QEE13F3VJW After finishing all the settings in the GTM container, we click on "Send" in the upper right corner of the page and then on "Publish". We can go back to the Analytics tab, under the "Workspace" section and check the tag code termination. We see, in the upper right corner of the screen: GTM-XXXXXXX This code matches one of the container codes listed by the extension. This means that the tag has been correctly installed on our website and within that tag Google Analytics is already installed.

12.6 Test tag

There are different ways to test this tag: we can use the Google Analytics platform itself or go to our website and see if the tag has been installed using an extension called Google Tag Assistant. To install the extension, go to: https://get.google.com/tagassistant/.

12.7 Using data-gtm

we use the structure page__component__action-name

βœ… Good:

- password-confirmation__create-new-user-password
- home-banner__want-to-register
- catalog__multi__see-more-filters

❌ Bad:

- create-new-user-password
- want-to--register
- multi--see-more-filters

12.8 Adding data-gtm attribute in component

By adding the data-gtm attribute to all relevant website elements, the Digital team can identify and track user actions that occur on different pages of the website.

<Button class="btn" data-gtm="password-confirmation__create-new-user-password">
  Criar usuΓ‘rio
</Button>

⬆ back to summary

More Repositories

1

frontend-challenge

πŸš€ Our hiring challenge to Front-end Developers
477
star
2

atomium

Atomium is an internal design system for 'Juntos Somos Mais' using Web Components
TypeScript
156
star
3

venice

[outdated] Design System of @juntossomosmais
TypeScript
147
star
4

code-challenge

Conheça nosso desafio para trabalhar conosco como engenheiro de software
46
star
5

django-outbox-pattern

A django application to make it easier to use the transactional outbox pattern
Python
46
star
6

time-out-market

Time Out Market is a market of shared JavaScript libraries to help you save time and effort
JavaScript
45
star
7

django-stomp

πŸ”ƒ A simple implementation of STOMP with Django
Python
37
star
8

regex4ocr

Plug regular expression models into OCR string results of document pictures to extract structured data!
Python
23
star
9

frontend-dojo

Coding Dojo - Frontend
JavaScript
20
star
10

jsm-component-generator

VSCode Extension to generate code
TypeScript
13
star
11

gitflow

A repository with the gitflows used by JS+ teams
12
star
12

python-fluentd-testing

Test your fluentd configuration leaving manual approach aside
Python
11
star
13

react-native-responsys

Use Oracle Responsys SDK in your React Native project
Objective-C
11
star
14

request-id-django-log

πŸ”– A simple way to implement request_id in Django
Python
10
star
15

JSM.FluentValidation.AspNet.AsyncFilter

ASP.NET filter that performs async validation using FluentValidation
C#
9
star
16

opentelemetry-instrumentation-django-stomp

This library will help you to use opentelemetry traces and metrics on Django STOMP usage library.
Python
7
star
17

JsTalks-testesFrontend

JavaScript
6
star
18

poc-couchdb

C#
6
star
19

auth0-samples

Having trouble integrating with Auth0? Just look at this repository and understand this process once and for all.
Python
5
star
20

serilog-enrichers-request-user-id

Enrich Serilog log events with the request's user Id from ClaimsPrincipal
C#
5
star
21

code-challenge-qa

Conheça nosso desafio para trabalhar conosco como profissional de QA
4
star
22

django-stomp-debug-callback

App to help us to understand database calls on consumer used on django-stomp
Python
3
star
23

http-utils

A simple requests session wrapper.
Python
3
star
24

terraform-development-image

Use it to play with Terraform using AZ CLI, AWS CLI, and other tools.
3
star
25

JSM.Swashbuckle.AspNetCore

Add new functionality to Swashbuckle.AspNetCore
C#
2
star
26

drf-link-navigation-pagination

Yet another pagination class for DRF to set host address by header
Python
2
star
27

jedi-academy

JS+ playbook
JavaScript
2
star