Files
Kotyata/apps/client/pages/_.vue
2026-03-17 13:24:22 +03:00

834 lines
20 KiB
Vue

<template>
<div
ref="root"
class="root"
>
<!-- UiButton -->
<div class="doc-block">
<strong>UiButton</strong>
<h1>Кнопки и ссылки</h1>
<div style="display: flex; flex-direction: column; gap: 16px">
<template
v-for="type in ['filled', 'outlined', 'ghost', 'link']"
:key="type"
>
<div
v-for="color in ['primary', 'secondary']"
:key="color"
class="buttons-rows"
>
<div
v-for="size in ['large', 'medium', 'small']"
:key="size"
class="buttons-grid"
>
<template
v-for="(props, index) in [
{
bind: { type, size, color },
icon: size === 'large' ? 'plus' : 's-plus',
chevron:
size === 'large' ? 'chevron-down' : 's-chevron-down',
},
]"
:key="index"
>
<UiButton v-bind="props.bind">
Button
</UiButton>
<UiButton
v-bind="props.bind"
:icon="props.icon"
>
Button
</UiButton>
<UiButton
v-bind="props.bind"
:right-icon="props.icon"
>
Button
</UiButton>
<UiButton
v-bind="props.bind"
:left-icon="props.icon"
:right-icon="props.chevron"
>
Button
</UiButton>
<UiButton
v-bind="props.bind"
loading
>
Button
</UiButton>
<UiButton
v-bind="props.bind"
:icon="props.icon"
/>
<UiButton
v-bind="props.bind"
:left-icon="props.icon"
:right-icon="props.chevron"
/>
<UiButton
v-bind="props.bind"
:icon="props.icon"
loading
/>
</template>
</div>
</div>
</template>
</div>
</div>
<!-- UiSelect -->
<div class="doc-block">
<strong>UiSelect</strong>
<h1>Select</h1>
<div class="two-columns">
<h4 class="group-heading">
Default
</h4>
<h4 class="group-heading">
Multiple
</h4>
<div
v-for="(multiple, index) in [false, true]"
:key="index"
class="bg-clr-grey-100 p-8"
style="display: inline-flex; gap: 8px; justify-self: center"
>
<UiSelect
:id="!multiple ? 'select' : 'select2'"
label="Select"
:options="selectOptions"
:multiple="multiple"
/>
<UiSelect
:id="!multiple ? 'select' : 'select2'"
label="Searchable"
:options="selectOptions"
searchable
:multiple="multiple"
/>
<UiSelect
:id="!multiple ? 'select' : 'select2'"
label="Clearable"
:options="selectOptions"
clearable
:multiple="multiple"
/>
</div>
</div>
</div>
<!-- UiDropdown -->
<div class="doc-block half">
<strong>UiDropdown</strong>
<h1>Dropdown \ Выпадающий список</h1>
<UiDropdown>
<UiButton
right-icon="s-chevron-down"
size="small"
>
Trigger
</UiButton>
<template #dropdown>
<UiDropdownItem
v-for="i in 5"
:key="i"
>
Item {{ i }}
</UiDropdownItem>
</template>
</UiDropdown>
</div>
<!-- UiCalendar -->
<div class="doc-block half">
<strong>UiCalendar</strong>
<h1>Calendar</h1>
<div class="d-inline-block bg-clr-grey-100 p-8">
<UiCalendar style="border-radius: 12px" />
</div>
</div>
<!-- UiInput -->
<div class="doc-block half">
<strong>UiInput</strong>
<h1>Поля ввода</h1>
<div class="two-columns">
<!-- <template v-for="state in []"></template> -->
<h4 class="group-heading">
Normal
</h4>
<h4 class="group-heading">
Disabled
</h4>
<UiInput
id="input1"
label="Basic"
/>
<UiInput
id="input1"
label="Basic"
disabled
/>
<UiInput
id="input2"
label="With caption"
caption="Caption"
/>
<UiInput
id="input2"
label="With caption"
caption="Caption"
disabled
/>
<UiInput
id="input3"
label="Clearable"
clearable
model-value="Value"
/>
<UiInput
id="input3"
label="Clearable"
clearable
disabled
/>
<UiInput
id="input4"
label="Copyable"
copyable
model-value="Value"
/>
<UiInput
id="input4"
label="Copyable"
copyable
disabled
/>
<UiInput
id="input5"
label="Password"
native-type="password"
model-value="superPassword"
/>
<UiInput
id="input5"
label="Password"
native-type="password"
disabled
/>
</div>
</div>
<!-- UiSearch -->
<div class="doc-block half">
<strong>UiSearch</strong>
<h1>Поиск</h1>
<div class="two-columns">
<h4 class="group-heading">
Normal
</h4>
<h4 class="group-heading">
Disabled
</h4>
<UiSearch
v-model="searchTerm"
size="large"
label="Large"
/>
<UiSearch
v-model="searchTerm"
size="large"
label="Large"
disabled
/>
<UiSearch
v-model="searchTerm"
size="medium"
label="Medium"
/>
<UiSearch
v-model="searchTerm"
size="medium"
label="Medium"
disabled
/>
<UiSearch
v-model="searchTerm"
size="small"
label="Small"
/>
<UiSearch
v-model="searchTerm"
size="small"
label="Small"
disabled
/>
</div>
</div>
<!-- UiSwitch -->
<div class="doc-block third">
<strong>UiSwitch</strong>
<h1>Switch</h1>
<div class="two-columns justify-items-center">
<h4 class="group-heading">
Normal
</h4>
<h4 class="group-heading">
Disabled
</h4>
<UiSwitch id="switch" />
<UiSwitch
id="switch"
disabled
/>
<UiSwitch
id="switch2"
:loading="switchLoading"
:before-change="beforeChange"
/>
<UiSwitch
id="switch2"
:loading="switchLoading"
disabled
/>
</div>
</div>
<!-- UiCheckbox -->
<div class="doc-block third">
<strong>UiCheckbox</strong>
<h1>Checkbox</h1>
<div class="two-columns">
<h4 class="group-heading">
Normal
</h4>
<h4 class="group-heading">
Disabled
</h4>
<UiCheckbox
id="checkbox"
label="Label"
true-value="checkbox1"
/>
<UiCheckbox
id="checkbox"
label="Label"
true-value="checkbox1"
disabled
/>
<UiCheckbox
id="checkbox"
true-value="checkbox2"
/>
<UiCheckbox
id="checkbox"
true-value="checkbox2"
disabled
/>
</div>
</div>
<!-- UiRadio -->
<div class="doc-block third">
<strong>UiRadio</strong>
<h1>Radio</h1>
<div class="two-columns">
<h4 class="group-heading">
Normal
</h4>
<h4 class="group-heading">
Disabled
</h4>
<UiRadio
id="radio"
label="Label"
value="radio1"
/>
<UiRadio
id="radio"
label="Label"
value="radio1"
disabled
/>
<UiRadio
id="radio"
value="radio2"
/>
<UiRadio
id="radio"
value="radio2"
disabled
/>
</div>
</div>
<!-- UiAccordion -->
<div class="doc-block">
<strong>UiAccordion</strong>
<h1>Спойлер \ Аккордеон</h1>
<div style="width: 600px; margin: 0 auto">
<UiAccordion>
<UiAccordionItem title="Title">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad
commodi, culpa delectus deleniti doloribus ducimus eaque eos eveniet
expedita harum, in incidunt itaque magnam, nulla quam ratione
recusandae reprehenderit veniam?
</UiAccordionItem>
<UiAccordionItem title="Title 2">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor
exercitationem iusto obcaecati placeat sunt! Dicta dolorem ducimus
minima molestias obcaecati odio omnis ratione recusandae,
voluptatum? Aspernatur autem commodi praesentium sint? Lorem ipsum
dolor sit amet, consectetur adipisicing elit. Expedita optio, vitae.
Aut consectetur cum dolores est exercitationem facilis fugiat
incidunt iste maiores modi nobis quia rerum, sit vel veniam vero!
<br>
<br>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor
exercitationem iusto obcaecati placeat sunt! Dicta dolorem ducimus
minima molestias obcaecati odio omnis ratione recusandae,
voluptatum? Aspernatur autem commodi praesentium sint? Lorem ipsum
dolor sit amet, consectetur adipisicing elit. Expedita optio, vitae.
Aut consectetur cum dolores est exercitationem facilis fugiat
incidunt iste maiores modi nobis quia rerum, sit vel veniam vero!
</UiAccordionItem>
<UiAccordionItem title="Title 3">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor
exercitationem iusto obcaecati placeat sunt! Dicta dolorem ducimus
minima molestias obcaecati odio omnis ratione recusandae,
voluptatum? Aspernatur autem commodi praesentium sint? Lorem ipsum
dolor sit amet, consectetur adipisicing elit. Expedita optio, vitae.
Aut consectetur cum dolores est exercitationem facilis fugiat
incidunt iste maiores modi nobis quia rerum, sit vel veniam vero!
<br>
<br>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor
exercitationem iusto obcaecati placeat sunt! Dicta dolorem ducimus
minima molestias obcaecati odio omnis ratione recusandae,
voluptatum? Aspernatur autem commodi praesentium sint? Lorem ipsum
dolor sit amet, consectetur adipisicing elit. Expedita optio, vitae.
Aut consectetur cum dolores est exercitationem facilis fugiat
incidunt iste maiores modi nobis quia rerum, sit vel veniam vero!
</UiAccordionItem>
</UiAccordion>
</div>
</div>
<!-- UiAlert -->
<div class="doc-block">
<strong>UiAlert</strong>
<h1>Алерты</h1>
<div
class="three-columns"
style="justify-items: center"
>
<div
class="w-100"
style="max-width: 400px"
>
<UiAlert
v-for="type in [
'neutral',
'positive',
'warning',
'negative',
'marketing',
]"
:key="type"
class="my-8"
:type="type"
text="Текст сообщения"
/>
</div>
<div
class="w-100"
style="max-width: 400px"
>
<UiAlert
v-for="type in [
'neutral',
'positive',
'warning',
'negative',
'marketing',
]"
:key="type"
class="my-8"
:type="type"
title="Заголовок"
text="Текст сообщения"
/>
</div>
<div
class="w-100"
style="max-width: 400px"
>
<UiAlert
v-for="type in [
'neutral',
'positive',
'warning',
'negative',
'marketing',
]"
:key="type"
:type="type"
class="my-8"
title="Заголовок"
text="Текст сообщения"
>
<template #action>
<UiButton type="link">
Действие
</UiButton>
</template>
</UiAlert>
</div>
</div>
</div>
<!-- UiBadge -->
<div class="doc-block">
<strong>UiBadge</strong>
<h1>Бейджы</h1>
<div
class="three-columns"
style="justify-items: center"
>
<div>
<UiBadge
v-for="type in [
'neutral',
'positive',
'warning',
'negative',
'marketing',
]"
:key="type"
class="my-8"
:type="type"
text="Текст бейджа"
/>
</div>
<div>
<UiBadge
v-for="type in [
'neutral',
'positive',
'warning',
'negative',
'marketing',
]"
:key="type"
class="my-8"
:type="type"
text="Текст бейджа"
:icon="randomIcon()"
/>
</div>
<div>
<UiBadge
v-for="type in [
'neutral',
'positive',
'warning',
'negative',
'marketing',
]"
:key="type"
:type="type"
class="my-8"
text="Текст бейджа"
>
<template #prefix>
<i :class="`icon-${randomIcon()}`" />
</template>
<template #suffix>
<i :class="`icon-${randomIcon()}`" />
</template>
</UiBadge>
</div>
</div>
</div>
<!-- Notification -->
<div class="doc-block">
<strong>useNotify \ $notify</strong>
<h1>Уведомления</h1>
<div
style="
display: grid;
grid-template-columns: repeat(2, 150px);
justify-content: center;
gap: 8px;
"
>
<UiButton @click="randomNotification('top-left')">
Top left
</UiButton>
<UiButton @click="randomNotification('top-right')">
Top Right
</UiButton>
<UiButton @click="randomNotification('bottom-left')">
Bottom left
</UiButton>
<UiButton @click="randomNotification('bottom-right')">
Bottom Right
</UiButton>
</div>
</div>
<!-- CopyButton -->
<div class="doc-block">
<strong>UiCopyButton</strong>
<h1>Кнопка копирования</h1>
<div
style="
display: grid;
grid-template-columns: repeat(1, 150px);
justify-content: center;
gap: 8px;
"
>
<UiCopyButton
title="Payment link"
pressed-title="Link copied"
value="Test value"
/>
</div>
</div>
<!-- Icons -->
<!-- <div -->
<!-- v-for="(font, index) in [icons, smallIcons]" -->
<!-- :key="font.metadata.name" -->
<!-- class="doc-block half" -->
<!-- > -->
<!-- <strong> -->
<!-- {{ _ === 0 ? '<i class="icon-*" />' : '<i class="icon-s-*" />' }} -->
<!-- </strong> -->
<!-- <h1>Иконки - {{ font.metadata.name }}</h1> -->
<!-- <div> -->
<!-- <div -->
<!-- v-for="(iconSet, index) in font.iconSets" -->
<!-- :key="_" -->
<!-- class="icons-grid" -->
<!-- > -->
<!-- <div -->
<!-- v-for="icon in iconSet.selection" -->
<!-- :key="icon.name" -->
<!-- class="preview-icon" -->
<!-- @click="copy(icon.name)" -->
<!-- > -->
<!-- <i :class="`${font.preferences.fontPref.prefix}${icon.name}`" /> -->
<!-- <span>{{ icon.name }}</span> -->
<!-- </div> -->
<!-- </div> -->
<!-- </div> -->
<!-- </div> -->
</div>
</template>
<script setup lang="ts">
import { useForm } from 'vee-validate'
import { ALERT_TYPES } from 'ui-layer/components/alert/types'
import type { NotificationPlacement } from 'ui-layer/components/notification/types'
import { sample } from 'lodash-es'
import icons from '#build/ui/available-icons'
definePageMeta({
layout: 'empty',
dev: true,
})
const searchTerm = ref<string>()
const switchLoading = ref(false)
useForm()
function copy(value: string) {
navigator.clipboard.writeText(value)
}
async function beforeChange() {
switchLoading.value = true
const result = await new Promise(resolve =>
setTimeout(() => resolve(true), 1000),
)
switchLoading.value = false
return result
}
const selectOptions = computed(() => {
return Array.from(Array(300).keys()).map(i => `Option ${i + 1}`)
})
let notificationTypeCounter = 0
function randomNotification(placement: NotificationPlacement) {
const notify = useNotify()
notify({
placement,
text: 'Текст',
title: 'Заголовок',
type: ALERT_TYPES[notificationTypeCounter],
})
notificationTypeCounter++
notificationTypeCounter %= ALERT_TYPES.length
}
function randomIcon() {
return sample(icons.filter(icon => icon.startsWith('s-')))
}
</script>
<style lang="scss" scoped>
.root {
padding: 30px;
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 30px;
}
.doc-block {
background-color: $clr-white;
border-radius: 30px;
padding: 40px 60px;
grid-column: span 6;
&.third {
grid-column: span 2;
}
&.half {
grid-column: span 3;
}
> strong {
color: $clr-grey-600;
}
> h1 {
margin-bottom: 40px;
}
}
.separator {
width: 100%;
}
.two-columns {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
.three-columns {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.buttons-rows {
display: flex;
flex-direction: column;
gap: 6px;
}
.buttons-grid {
display: flex;
gap: 6px;
}
.icons-grid {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-top: 6px;
}
.preview-icon {
display: flex;
border-radius: 8px;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
width: 85px;
height: 65px;
text-align: center;
background-color: $clr-grey-100;
cursor: pointer;
user-select: none;
transition: background-color 0.2s ease-out;
&:hover,
&:focus {
background-color: $clr-grey-200;
}
&:active {
background-color: $clr-grey-300;
}
span {
@include txt-s-m;
}
}
.group-heading {
text-align: center;
color: $clr-grey-500;
}
</style>