brutalism design

This commit is contained in:
2026-05-22 05:08:02 +06:00
parent abf4d41c23
commit e4ed785911
51 changed files with 940 additions and 1171 deletions

View File

@@ -1,38 +1,64 @@
<template>
<div class="chat-messages">
<div v-if="messages" ref="scroll" class="chat-messages__list">
<template v-for="(page, pageIdx) in messages.pages" :key="pageIdx">
<ChatMessage v-for="message in page.messages" :key="message.id" :message="message" />
</template>
<ChatMessage v-for="message in messages" :key="message.id" :message="message" />
<ChatMessage v-for="item in feedItems" :key="item.id" :message="item" />
</div>
<ChadSpinner v-if="isFetching" class="chat-messages__spinner" />
<button v-if="!arrivedState.start" class="chat-messages__scroll-to-bottom" @click="scrollToStart()">
<ArrowDown />
</button>
</div>
</template>
<script setup lang="ts">
import { ArrowDown } from '@lucide/vue'
import ChadSpinner from '@shared/components/ui/Spinner.vue'
import { useInfiniteScroll } from '@vueuse/core'
import { useEventBus } from '@shared/composables/use-event-bus.ts'
import { useChatScroll } from '@widgets/chat/composables/use-chat-scroll.ts'
import ChatMessage from '@widgets/chat/ui/ChatMessage.vue'
import { useTemplateRef } from 'vue'
import { onUnmounted, ref, useTemplateRef, watch } from 'vue'
import { useChat } from '../composables/use-chat'
const eventBus = useEventBus()
const scrollRef = useTemplateRef('scroll')
const { messages, hasMoreMessages, fetchNextPage, isFetching } = useChat()
const { messages, feedItems, hasMoreMessages, fetchNextPage, isFetching } = useChat()
useInfiniteScroll(
scrollRef,
() => {
const hasUnreadMessages = ref(false)
const { arrivedState, scrollToStart } = useChatScroll(scrollRef, {
startOffset: 100,
endOffset: 100,
})
watch(() => arrivedState.end, (arrived) => {
if (!arrived)
return
if (hasMoreMessages.value) {
fetchNextPage()
},
{
distance: 500,
direction: 'top',
interval: 300,
canLoadMore: () => hasMoreMessages.value && !isFetching.value,
},
)
}
})
watch(() => arrivedState.start, () => {
hasUnreadMessages.value = false
})
eventBus.on('chat:new-message', onNewChatMessage)
onUnmounted(() => {
eventBus.off('chat:new-message', onNewChatMessage)
})
function onNewChatMessage() {
if (!arrivedState.start) {
hasUnreadMessages.value = true
}
}
</script>
<style lang="scss">
@@ -49,11 +75,34 @@ useInfiniteScroll(
}
&__list {
overflow-x: hidden;
overflow-y: auto;
overflow-y: overlay;
display: flex;
flex-direction: column-reverse;
height: 100%;
position: relative;
max-height: 100%;
}
&__scroll-to-bottom {
position: absolute;
cursor: pointer;
width: 40px;
aspect-ratio: 1;
text-align: center;
line-height: 40px;
bottom: var(--space-4);
right: var(--space-4);
outline: var(--border-w) solid var(--ink);
outline-offset: calc(var(--border-w) * -1);
border: none;
background-color: var(--grey-1);
padding: 0;
&:hover,
&:focus,
&:active {
background-color: var(--grey-2);
}
}
}
</style>