ContainerDraft
<script setup lang="ts">
const breakpoints = [
{ name: 'xl', value: '2400px' },
{ name: 'l', value: '1000px' },
{ name: 'm', value: '840px' },
{ name: 's', value: '620px' },
{ name: 'xs', value: '500px' },
{ name: 'xxs', value: '400px' },
]
</script>
<template>
<ul>
<li
v-for="({ name, value }, key) in breakpoints"
:key
:class="[
`n-container-${name}`,
'n-margin-be-m n-padding-s',
'n-font-size-m n-color-accent n-color-text-on-accent',
]"
>
{{ name }} / {{ value }}
</li>
</ul>
</template>
<template>
<BaseContainer>
<CardInnerSection>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Lorem
</div>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Ipsum
</div>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Dolor
</div>
</CardInnerSection>
</BaseContainer>
</template>
<script setup lang="ts">
import { z } from 'zod'
const containerElement = useTemplateRef('containerRef')
const formElement = useTemplateRef('formRef')
const formSchema = z.object(
Array.from({ length: 12 }, (_, i) => `test${i + 1}`).reduce(
(acc, key) => {
acc[key] = z.string().optional()
return acc
},
{} as Record<string, z.ZodOptional<z.ZodString>>,
),
)
const { handleErrors } = useFormValidation(formElement)
const { handleSubmit } = useForm({
validationSchema: toTypedSchema(formSchema),
})
const containerSizes = useElementSize(containerElement)
const onSubmit = handleSubmit(
(data) => console.log(data),
() => handleErrors(),
)
const resolveWidthToBreakpoint = (width: number) => {
if (width < 500) return 'xs'
if (width < 620) return 's'
if (width < 840) return 'm'
if (width < 1000) return 'l'
return 'xl'
}
const getPlaygroundDetails = computed(() => ({
breakpoint: resolveWidthToBreakpoint(containerSizes.width.value),
containerSizes,
}))
</script>
<template>
<div class="n-stack n-gap-l n-margin-be-xxl">
<h2 slot="header">Container sizes</h2>
<pre>{{ getPlaygroundDetails }}</pre>
<BaseContainer ref="containerRef" mode="form">
<provet-card padding="l">
<h2 slot="header">Form container</h2>
<form ref="formRef" @submit="onSubmit">
<div class="n-stack n-gap-l">
<CardInnerSection class="n-grid">
<FormProvetField label="Full width input" name="test" expand />
<div class="n-grid n-grid-2">
<FormProvetField label="First name" name="test2" expand />
<FormProvetField label="Last name" name="test3" expand />
</div>
<div class="n-grid n-grid-3">
<FormProvetField label="1/3" name="test4" expand />
<FormProvetField label="2/3" name="test5" expand />
<FormProvetField label="3/3" name="test6" expand />
</div>
<DividedStack class="n-grid">
<div class="n-grid">
<FormProvetField
label="Small"
name="test7"
inline-size="160px"
/>
<FormProvetField
label="XS"
name="test8"
inline-size="104px"
/>
</div>
<div class="inline-fluid">
<FormProvetField
label="Small"
name="test9"
inline-size="160px"
/>
<FormProvetField label="Fluid" name="test10" expand />
</div>
<div class="inline-fluid">
<FormProvetField
label="XS"
name="test11"
inline-size="104px"
/>
<FormProvetField label="Fluid" name="test12" expand />
</div>
<CardInnerSection>
<BaseDropdown
title="Lorem"
:options="[
{
label: 'Ipsum',
clickHandler: () =>
console.log(
'Nam et cursus nisi, ac malesuada risus.',
),
},
]"
/>
</CardInnerSection>
</DividedStack>
</CardInnerSection>
</div>
</form>
</provet-card>
</BaseContainer>
</div>
</template>
<template>
<BaseContainer>
<CardInnerSection>
<div class="inline-fluid">
<FormProvetField label="Small" name="test9" inline-size="160px" />
<FormProvetField label="Fluid" name="test10" expand />
</div>
</CardInnerSection>
</BaseContainer>
</template>
<template>
<BaseContainer>
<DividedStack>
<!-- When only child -->
<CardInnerSection>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Lorem
</div>
</CardInnerSection>
<!-- If you want to keep it as 1 column -->
<CardInnerSection class="n-grid">
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Lorem
</div>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Ipsum
</div>
</CardInnerSection>
</DividedStack>
</BaseContainer>
</template>
<template>
<BaseContainer class="n-stack n-gap-l">
<DividedStack>
<CardInnerSection>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Lorem
</div>
<div
class="column-pair n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Ipsum
</div>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Dolor
</div>
</CardInnerSection>
<!-- More complex example example with nested `column-pair` usage -->
<CardInnerSection class="n-grid">
<div class="n-grid-3">
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Lorem
</div>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Ipsum
</div>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Dolor
</div>
</div>
<div class="n-grid-3">
<div class="n-grid column-pair n-grid-2">
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Sit
</div>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Amet
</div>
</div>
</div>
</CardInnerSection>
</DividedStack>
</BaseContainer>
</template>
<script setup lang="ts">
const containerElement = useTemplateRef('containerRef')
const containerSizes = useElementSize(containerElement)
const resolveWidthToBreakpoint = (width: number) => {
if (width < 500) return 'xs'
if (width < 620) return 's'
if (width < 840) return 'm'
if (width < 1000) return 'l'
return 'xl'
}
const getPlaygroundDetails = computed(() => ({
breakpoint: resolveWidthToBreakpoint(containerSizes.width.value),
containerSizes,
}))
</script>
<template>
<div class="n-stack n-gap-l n-margin-be-xxl">
<h2 slot="header">Container sizes</h2>
<pre>{{ getPlaygroundDetails }}</pre>
<BaseContainer ref="containerRef">
<provet-card padding="l">
<h2 slot="header">Readonly container</h2>
<div class="n-stack n-gap-s">
<div class="n-color-background n-padding-m n-border-radius-s">
<CardInnerSection>
<ReadOnlyField label="Holding place number" value="Lorem 12345" />
<ReadOnlyField label="Description" value="Ipsum dolor sit amet" />
<ReadOnlyField label="Address">
<span class="n-color-text-weaker">(Same as farm)</span>
</ReadOnlyField>
</CardInnerSection>
</div>
<div class="n-color-background n-padding-m n-border-radius-s">
<CardInnerSection>
<ReadOnlyField label="Holding place number" value="Consectetur" />
<ReadOnlyField
label="Description"
value="Adipiscing elit sed eiusmod tempor incididunt"
/>
<ReadOnlyField label="Address">
<FormattedAddress
country="NO"
zip-code="0042"
city="Oslo"
street-address="Gård vei 404"
/>
</ReadOnlyField>
</CardInnerSection>
</div>
</div>
</provet-card>
</BaseContainer>
</div>
</template>
<template>
<BaseContainer>
<DividedStack>
<CardInnerSection>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Lorem
</div>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Ipsum
</div>
</CardInnerSection>
<CardInnerSection class="n-grid-2">
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Lorem
</div>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Ipsum
</div>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Dolor
</div>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Sit
</div>
<div
class="n-font-size-m n-color-accent n-color-text-on-accent n-padding-s"
>
Amet
</div>
</CardInnerSection>
</DividedStack>
</BaseContainer>
</template>
Integration
This product pattern is currently only available to use in the New Frontend for Provet Cloud (using Vue & Nuxt).
Troubleshooting
If you experience any issues while using this pattern, please ask for support in the #vet-frontend Slack channel.