I'm working on a vue.js / nuxt.js project, applying the Atomic Design methodology, I need to do one to set the grid layout and using CSS Grid Layout.
I already did the component, but I think I did not do it the best way ... the code is great and not very smart, lots of manual work, I would like your opinion and help to make this component better
GridLayout.vue
<template>
<div class="grid">
<style>
{{ css }}
</style>
<slot />
</div>
</template>
<script>
export default {
props: {
columns: String,
rows: String,
areas: String,
gap: String,
columnGap: String,
rowGap: String,
// breakpoints
small: Object,
medium: Object,
large: Object
},
computed: {
css () {
let large = ''
let finalStyle = ''
// generic
let generic = ''
if (this.columns) generic += `grid-template-columns: ${this.columns};`
if (this.rows) generic += `grid-template-rows: ${this.rows};`
if (this.areas) generic += `grid-template-areas: "${this.areas}";`
if (this.gap) generic += `grid-gap: ${this.gap};`
if (this.columnGap) generic += `grid-column-gap: ${this.columnGap};`
if (this.rowGap) generic += `grid-row-gap: ${this.rowGap};`
finalStyle += ` .grid { ${generic} }`
// small
let small = ''
if (this.small) {
if (this.small.columns) small += `grid-template-columns: ${this.small.columns};`
if (this.small.rows) small += `grid-template-rows: ${this.small.rows};`
if (this.small.areas) small += `grid-template-areas: "${this.small.areas}";`
if (this.small.gap) small += `grid-gap: ${this.small.gap};`
if (this.small.columnGap) small += `grid-column-gap: ${this.small.columnGap};`
if (this.small.rowGap) small += `grid-row-gap: ${this.small.rowGap};`
finalStyle += `@media (max-width: 600px) { .grid { ${small} } } `
}
// medium
let medium = ''
if (this.medium) {
if (this.medium.columns) medium += `grid-template-columns: ${this.medium.columns};`
if (this.medium.rows) medium += `grid-template-rows: ${this.medium.rows};`
if (this.medium.areas) medium += `grid-template-areas: "${this.medium.areas}";`
if (this.medium.gap) medium += `grid-gap: ${this.medium.gap};`
if (this.medium.columnGap) medium += `grid-column-gap: ${this.medium.columnGap};`
if (this.medium.rowGap) medium += `grid-row-gap: ${this.medium.rowGap};`
finalStyle += `@media (min-width: 600px) and (max-width: 992px) { .grid { ${medium} } } `
}
return finalStyle
},
},
}
</script>
<style lang="scss" scoped>
.grid {
display: grid;
}
</style>
using component on any page.vue
<template>
<GridLayout
columns="1fr 1fr 1fr 1fr"
rows="auto"
gap="10px"
:medium="{
columns: '1fr 1fr',
rows:'auto auto'
}"
:small="{
columns: '1fr',
rows: 'auto auto auto auto',
}"
>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>3</h1>
</GridLayout>
</template>
<script>
import { GridLayout } from '@/components/bosons'
export default {
components: {
GridLayout
}
}
</script>
problems
1 - the style tag
<style>
inside ` needs to be scoped, applying only in the component itself2 - whenever I want new properties for the GridLayout, for example, '' child align '', I will have to add everywhere in computed, that is,
generic
,small
,medium
,large
Anyway, I honestly did not like what I did, I would like your opinion and help you guys.