-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(grid): add
<SGrid>
component (#313)
Co-authored-by: Cue <[email protected]>
- Loading branch information
Showing
9 changed files
with
253 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
<script setup lang="ts"> | ||
import SGrid from 'sefirot/components/SGrid.vue' | ||
import SGridItem from 'sefirot/components/SGridItem.vue' | ||
</script> | ||
|
||
# SGrid | ||
|
||
`<SGrid>` is a utility component to handle CSS grid layout. | ||
|
||
<Showcase | ||
path="/components/SGrid.vue" | ||
story="/stories-components-sgrid-01-playground-story-vue" | ||
> | ||
<SGrid cols="4" gap="24"> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
</SGrid> | ||
</Showcase> | ||
## Usage | ||
|
||
Use `<SGrid>` and `<SGridItem>` component to construct the grid structure. | ||
|
||
```vue | ||
<script setup lang="ts"> | ||
import SGrid from '@globalbrain/sefirot/lib/components/SGrid.vue' | ||
import SGridItem from '@globalbrain/sefirot/lib/components/SGridItem.vue' | ||
</script> | ||
<template> | ||
<SGrid cols="4"> | ||
<SGridItem span="2"> | ||
<div>...</div> | ||
</SGridItem> | ||
<SGridItem span="1"> | ||
<div>...</div> | ||
</SGridItem> | ||
</SGrid> | ||
</template> | ||
``` | ||
|
||
You have the flexibility to define the `:cols` and `:gap` props when using the `<SGrid>` component, allowing you to have full control over the grid layout. | ||
|
||
The `cols` prop serves as a shorthand for the `grid-template-columns` CSS property. Similarly, the `gap` prop acts as a shorthand for the `gap` CSS property. | ||
|
||
Notably, the `gap` prop automatically appends the required `px` unit to the value, so there is no need to include it explicitly. | ||
|
||
```ts | ||
interface Props { | ||
cols?: string | number | ||
gap?: string | number | ||
} | ||
``` | ||
|
||
```vue-html | ||
<SGrid cols="4" gap="48"> | ||
... | ||
</SGrid> | ||
``` | ||
|
||
Once you have defined the grid layout, you can use the `span` prop on the `<SGridItem>` component to define the number of columns that the item should span. The `span` prop serves as a shorthand for the `grid-column` CSS property. | ||
|
||
```ts | ||
interface Props { | ||
span?: string | number | ||
} | ||
``` | ||
|
||
```vue-html | ||
<SGrid cols="4" gap="48"> | ||
<SGridItem span="2">...</SGridItem> | ||
<SGridItem span="2">...</SGridItem> | ||
</SGrid> | ||
``` | ||
|
||
## Responsive design | ||
|
||
If you need to adjust the overall grid layout based on different screen sizes or other conditions, it is recommended to use CSS instead of props. The props are provided for convenience, but for more complex layout structures, CSS should be used. | ||
|
||
```vue | ||
<template> | ||
<SGrid class="grid"> | ||
<SGridItem class="name">...</SGridItem> | ||
<SGridItem class="age">...</SGridItem> | ||
<SGridItem class="email">...</SGridItem> | ||
</SGrid> | ||
</template> | ||
<style scoped> | ||
.grid { | ||
grid-template-columns: 1fr; | ||
gap: 16px; | ||
} | ||
@media (min-width: 768px) { | ||
.grid { | ||
grid-template-columns: 1fr 1fr; | ||
gap: 24px; | ||
} | ||
.email { | ||
grid-column: span 2; | ||
} | ||
} | ||
</style> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<script setup lang="ts"> | ||
import { computed } from 'vue' | ||
const props = defineProps<{ | ||
cols?: string | number | ||
gap?: string | number | ||
}>() | ||
const styles = computed(() => { | ||
return { | ||
gridTemplateColumns: `repeat(${props.cols ?? 1}, minmax(0, 1fr))`, | ||
gap: `${props.gap ?? 0}px` | ||
} | ||
}) | ||
</script> | ||
|
||
<template> | ||
<div class="SGrid" :style="styles"> | ||
<slot /> | ||
</div> | ||
</template> | ||
|
||
<style scoped lang="postcss"> | ||
.SGrid { | ||
display: grid; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<script setup lang="ts"> | ||
defineProps<{ | ||
span?: string | number | ||
}>() | ||
</script> | ||
|
||
<template> | ||
<div | ||
class="SGridItem" | ||
:style="{ gridColumn: span ? `span ${span}` : undefined }" | ||
> | ||
<slot /> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { type App } from 'vue' | ||
import SGrid from '../components/SGrid.vue' | ||
import SGridItem from '../components/SGridItem.vue' | ||
|
||
export function mixin(app: App): void { | ||
app.mixin({ | ||
components: { | ||
SGrid, | ||
SGridItem | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<script setup lang="ts"> | ||
import SGrid from 'sefirot/components/SGrid.vue' | ||
import SGridItem from 'sefirot/components/SGridItem.vue' | ||
const title = 'Components / SGrid / 01. Playground' | ||
const docs = '/components/grid' | ||
</script> | ||
|
||
<template> | ||
<Story :title="title" source="Not available" auto-props-disabled> | ||
<Board :title="title" :docs="docs"> | ||
<SGrid cols="4" gap="24"> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
<SGridItem> | ||
<div class="h-64 rounded-6 bg-info" /> | ||
</SGridItem> | ||
</SGrid> | ||
</Board> | ||
</Story> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { mount } from '@vue/test-utils' | ||
import SGrid from 'sefirot/components/SGrid.vue' | ||
import SGridItem from 'sefirot/components/SGridItem.vue' | ||
|
||
describe('components/SGrid', () => { | ||
describe('SGrid', () => { | ||
test('renders `SGrid` element', () => { | ||
const wrapper = mount(SGrid) | ||
expect(wrapper.find('.SGrid').exists()).toBe(true) | ||
}) | ||
}) | ||
|
||
describe('SGridItem', () => { | ||
test('renders `SGridItem` element', () => { | ||
const wrapper = mount(SGridItem) | ||
expect(wrapper.find('.SGridItem').exists()).toBe(true) | ||
}) | ||
}) | ||
}) |