From 4e9e6dce2aef799ea4d42bc2d00817f25f826c9f Mon Sep 17 00:00:00 2001 From: Daan Meijer Date: Tue, 16 Jun 2026 14:13:08 +0200 Subject: [PATCH] front-end restructuring, chat shows message ownership --- resources/css/app.css | 2 + resources/css/components.css | 16 ++ resources/css/components/app-content.css | 5 + resources/css/components/app-logo.css | 20 ++ resources/css/components/appearance-tabs.css | 35 +++ resources/css/components/auth-layout.css | 46 ++++ resources/css/components/chat.css | 210 ++++++++++++++++++ resources/css/components/heading.css | 22 ++ resources/css/components/input-error.css | 5 + resources/css/components/lightbox.css | 25 +++ resources/css/components/password-input.css | 21 ++ resources/css/components/sidebar-header.css | 14 ++ resources/css/components/text-link.css | 10 + resources/css/components/user-info.css | 19 ++ resources/js/app.ts | 2 +- resources/js/components/AppContent.vue | 8 - resources/js/components/AppLogo.vue | 20 -- resources/js/components/AppSidebarHeader.vue | 12 - resources/js/components/AppearanceTabs.vue | 24 -- resources/js/components/Chat.vue | 189 ++-------------- resources/js/components/CreateLedgerForm.vue | 26 ++- resources/js/components/Heading.vue | 24 -- resources/js/components/InputError.vue | 8 - resources/js/components/LedgerList.vue | 12 +- resources/js/components/ParticipantsList.vue | 9 +- resources/js/components/PasswordInput.vue | 20 -- resources/js/components/TextLink.vue | 8 - resources/js/components/UserInfo.vue | 20 -- .../js/layouts/auth/AuthSimpleLayout.vue | 44 ---- resources/js/pages/Dynamics/Show.vue | 8 +- resources/js/pages/Ledgers/Show.vue | 36 +-- 31 files changed, 516 insertions(+), 404 deletions(-) create mode 100644 resources/css/components.css create mode 100644 resources/css/components/app-content.css create mode 100644 resources/css/components/app-logo.css create mode 100644 resources/css/components/appearance-tabs.css create mode 100644 resources/css/components/auth-layout.css create mode 100644 resources/css/components/chat.css create mode 100644 resources/css/components/heading.css create mode 100644 resources/css/components/input-error.css create mode 100644 resources/css/components/lightbox.css create mode 100644 resources/css/components/password-input.css create mode 100644 resources/css/components/sidebar-header.css create mode 100644 resources/css/components/text-link.css create mode 100644 resources/css/components/user-info.css diff --git a/resources/css/app.css b/resources/css/app.css index 783e69c..97767d0 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -2,6 +2,8 @@ @import 'tw-animate-css'; +@import './components.css'; + @source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php'; @source '../../storage/framework/views/*.php'; diff --git a/resources/css/components.css b/resources/css/components.css new file mode 100644 index 0000000..a6906da --- /dev/null +++ b/resources/css/components.css @@ -0,0 +1,16 @@ +/* ========================================================================== + BEM UI Components Index Manifest (Tailwind CSS v4) + ========================================================================== */ + +@import './components/heading.css'; +@import './components/input-error.css'; +@import './components/text-link.css'; +@import './components/app-logo.css'; +@import './components/user-info.css'; +@import './components/sidebar-header.css'; +@import './components/app-content.css'; +@import './components/appearance-tabs.css'; +@import './components/password-input.css'; +@import './components/auth-layout.css'; +@import './components/chat.css'; +@import './components/lightbox.css'; diff --git a/resources/css/components/app-content.css b/resources/css/components/app-content.css new file mode 100644 index 0000000..f19c554 --- /dev/null +++ b/resources/css/components/app-content.css @@ -0,0 +1,5 @@ +/* 7. AppContent Layout Component */ +.app-content { + @apply mx-auto flex h-full w-full max-w-7xl flex-1 flex-col gap-4; + border-radius: var(--radius); +} diff --git a/resources/css/components/app-logo.css b/resources/css/components/app-logo.css new file mode 100644 index 0000000..fc7e468 --- /dev/null +++ b/resources/css/components/app-logo.css @@ -0,0 +1,20 @@ +/* 4. AppLogo Component */ +.app-logo__icon-container { + @apply flex aspect-square size-8 items-center justify-center; + border-radius: var(--radius); + background-color: var(--sidebar-primary); + color: var(--sidebar-primary-foreground); + + .app-logo__icon { + @apply size-5 fill-current; + } +} + +.app-logo__text-container { + @apply ml-1 grid flex-1 text-left text-sm; + + .app-logo__text { + @apply mb-0.5 truncate leading-tight font-semibold; + color: var(--foreground); + } +} diff --git a/resources/css/components/appearance-tabs.css b/resources/css/components/appearance-tabs.css new file mode 100644 index 0000000..462f7c7 --- /dev/null +++ b/resources/css/components/appearance-tabs.css @@ -0,0 +1,35 @@ +/* 8. AppearanceTabs Component */ +.appearance-tabs { + @apply inline-flex gap-1 p-1; + border-radius: var(--radius); + background-color: var(--muted); + + .appearance-tabs__tab { + @apply flex cursor-pointer items-center px-3.5 py-1.5 transition-colors; + border-radius: calc(var(--radius) - 2px); + color: var(--muted-foreground); + + &:hover { + color: var(--foreground); + background-color: rgba(0, 0, 0, 0.05); + } + + &.appearance-tabs__tab--active { + background-color: var(--card); + color: var(--card-foreground); + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); + + &:hover { + background-color: var(--card); + } + } + } + + .appearance-tabs__icon { + @apply -ml-1 h-4 w-4; + } + + .appearance-tabs__label { + @apply ml-1.5 text-sm; + } +} diff --git a/resources/css/components/auth-layout.css b/resources/css/components/auth-layout.css new file mode 100644 index 0000000..9a7e3d7 --- /dev/null +++ b/resources/css/components/auth-layout.css @@ -0,0 +1,46 @@ +/* 10. AuthSimpleLayout Component */ +.auth-layout { + @apply flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10; + background-color: var(--background); + + .auth-layout__container { + @apply w-full max-w-sm; + + .auth-layout__inner { + @apply flex flex-col gap-8; + + .auth-layout__header { + @apply flex flex-col items-center gap-4; + + .auth-layout__logo-link { + @apply flex flex-col items-center gap-2 font-medium; + + .auth-layout__logo-box { + @apply mb-1 flex h-9 w-9 items-center justify-center; + border-radius: var(--radius); + background-color: var(--sidebar-primary); + + .auth-layout__logo { + @apply size-9 fill-current; + color: var(--sidebar-primary-foreground); + } + } + } + + .auth-layout__title-box { + @apply space-y-2 text-center; + + .auth-layout__title { + @apply text-xl font-medium; + color: var(--foreground); + } + + .auth-layout__description { + @apply text-center text-sm; + color: var(--muted-foreground); + } + } + } + } + } +} diff --git a/resources/css/components/chat.css b/resources/css/components/chat.css new file mode 100644 index 0000000..a383573 --- /dev/null +++ b/resources/css/components/chat.css @@ -0,0 +1,210 @@ +/* 11. Chat Component */ +.c-chat { + @apply mt-8; + + .c-chat__title { + @apply text-lg font-medium; + color: var(--foreground); + } + + .c-chat__list { + @apply mt-4 flex flex-col gap-3; + + .c-chat__message { + @apply overflow-hidden p-4 shadow-sm sm:rounded-lg; + border: 1px solid var(--border); + + &.c-chat__message--system { + @apply w-full self-center border-0 bg-transparent p-0 shadow-none; + } + + &.c-chat__message--own { + @apply self-end rounded-br-none text-right; + max-width: 80%; + background-color: var(--primary); + border-color: var(--primary); + + .c-chat__message-header { + @apply flex-row-reverse; + } + .c-chat__message-author { + color: var(--primary-foreground); + } + .c-chat__message-time { + color: var(--primary-foreground); + opacity: 0.7; + } + .c-chat__message-text { + color: var(--primary-foreground); + } + } + + &.c-chat__message--other { + @apply self-start rounded-bl-none; + max-width: 80%; + background-color: var(--muted); + border-color: var(--border); + + .c-chat__message-author { + color: var(--foreground); + } + .c-chat__message-time { + color: var(--muted-foreground); + } + .c-chat__message-text { + color: var(--foreground); + } + } + + .c-chat__system-inner { + @apply flex items-center gap-2 px-3 py-1.5 text-xs; + background-color: var(--muted); + border: 1px solid var(--border); + border-radius: calc(var(--radius) - 2px); + color: var(--muted-foreground); + + .c-chat__system-icon { + @apply size-3.5 shrink-0; + color: var(--muted-foreground); + } + + .c-chat__system-text { + @apply flex-1 font-medium; + } + + .c-chat__system-time { + @apply shrink-0 text-[10px]; + color: var(--muted-foreground); + } + } + + .c-chat__message-header { + @apply flex justify-between; + + .c-chat__message-author { + @apply font-semibold; + color: var(--foreground); + } + + .c-chat__message-time { + @apply text-xs; + color: var(--muted-foreground); + } + } + + .c-chat__message-text { + @apply mt-2 text-sm; + color: var(--foreground); + } + + .c-chat__message-media { + @apply mt-3 flex flex-wrap gap-2; + + .c-chat__media-item { + @apply relative max-w-[240px] overflow-hidden bg-black; + border-radius: calc(var(--radius) - 2px); + border: 1px solid var(--border); + + .c-chat__image { + @apply h-auto max-h-[180px] w-full object-cover; + } + + .c-chat__video { + @apply h-auto max-h-[180px] w-full; + } + + .c-chat__play-overlay { + @apply absolute inset-0 flex items-center justify-center bg-black/40 text-2xl font-bold text-white; + } + } + } + } + } + + .c-chat__empty { + color: var(--muted-foreground); + } + + .c-chat__form { + @apply mt-6 space-y-6; + + .c-chat__form-group { + @apply space-y-2; + + .c-chat__label { + @apply block text-sm font-medium; + color: var(--foreground); + } + + .c-chat__textarea { + @apply mt-1 block w-full shadow-sm; + border-radius: var(--radius); + border: 1px solid var(--border); + background-color: var(--background); + color: var(--foreground); + } + + .c-chat__error { + @apply text-sm; + color: var(--destructive); + } + + .c-chat__attachment-container { + @apply mt-2 flex items-center; + + .c-chat__attach-btn { + @apply inline-flex cursor-pointer items-center gap-1.5 text-xs transition-colors; + color: var(--muted-foreground); + + &:hover { + color: var(--foreground); + } + + .c-chat__attach-icon { + @apply size-3.5; + } + } + } + + .c-chat__preview-list { + @apply mt-2 flex flex-wrap gap-2; + + .c-chat__preview-item { + @apply relative inline-flex items-center gap-2 p-1.5 pr-8 text-xs; + border-radius: calc(var(--radius) - 2px); + border: 1px solid var(--border); + background-color: var(--muted); + + .c-chat__preview-name { + @apply max-w-[150px] truncate; + color: var(--foreground); + } + + .c-chat__preview-remove { + @apply absolute top-1.5 right-1.5 cursor-pointer text-[10px]; + color: var(--muted-foreground); + + &:hover { + color: var(--destructive); + } + } + } + } + } + + .c-chat__submit-box { + @apply flex items-center gap-4; + + .c-chat__button { + @apply inline-flex items-center border border-transparent px-4 py-2 text-xs font-semibold tracking-widest uppercase transition duration-150 ease-in-out focus:ring-2 focus:outline-none; + border-radius: var(--radius); + background-color: var(--primary); + color: var(--primary-foreground); + + &:hover { + opacity: 0.9; + } + } + } + } +} diff --git a/resources/css/components/heading.css b/resources/css/components/heading.css new file mode 100644 index 0000000..ca58613 --- /dev/null +++ b/resources/css/components/heading.css @@ -0,0 +1,22 @@ +/* 1. Heading Component */ +.c-heading { + @apply mb-8 space-y-0.5; + + &.c-heading--small { + @apply mb-0 space-y-0; + + .c-heading__title { + @apply mb-0.5 text-base font-medium tracking-normal; + } + } + + .c-heading__title { + @apply text-xl font-semibold tracking-tight; + color: var(--foreground); + } + + .c-heading__description { + @apply text-sm; + color: var(--muted-foreground); + } +} diff --git a/resources/css/components/input-error.css b/resources/css/components/input-error.css new file mode 100644 index 0000000..fbae00d --- /dev/null +++ b/resources/css/components/input-error.css @@ -0,0 +1,5 @@ +/* 2. InputError Component */ +.c-input-error__message { + @apply text-sm; + color: var(--destructive); +} diff --git a/resources/css/components/lightbox.css b/resources/css/components/lightbox.css new file mode 100644 index 0000000..e1cee73 --- /dev/null +++ b/resources/css/components/lightbox.css @@ -0,0 +1,25 @@ +/* 12. Reusable Lightbox Component */ +.c-lightbox { + @apply fixed inset-0 z-50 flex items-center justify-center p-4; + background-color: rgba(0, 0, 0, 0.95); + + .c-lightbox__close { + @apply absolute top-6 right-6 cursor-pointer text-3xl text-white transition-colors duration-200; + + &:hover { + color: var(--destructive); + } + } + + .c-lightbox__content { + @apply max-h-full max-w-full; + + .c-lightbox__image { + @apply max-h-[90vh] max-w-full rounded object-contain shadow-lg; + } + + .c-lightbox__video { + @apply max-h-[90vh] max-w-full rounded shadow-lg; + } + } +} diff --git a/resources/css/components/password-input.css b/resources/css/components/password-input.css new file mode 100644 index 0000000..fa3cc35 --- /dev/null +++ b/resources/css/components/password-input.css @@ -0,0 +1,21 @@ +/* 9. PasswordInput Component */ +.password-input { + @apply relative; + + .password-input__field { + @apply pr-10; + } + + .password-input__toggle { + @apply absolute inset-y-0 right-0 flex items-center rounded-r-md px-3 focus-visible:outline-none; + color: var(--muted-foreground); + + &:hover { + color: var(--foreground); + } + } + + .password-input__icon { + @apply size-4; + } +} diff --git a/resources/css/components/sidebar-header.css b/resources/css/components/sidebar-header.css new file mode 100644 index 0000000..2d07dcc --- /dev/null +++ b/resources/css/components/sidebar-header.css @@ -0,0 +1,14 @@ +/* 6. AppSidebarHeader Component */ +.sidebar-header { + @apply flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear md:px-4; + border-bottom: 1px solid var(--sidebar-border); + background-color: var(--sidebar-background); +} + +.sidebar-header__inner { + @apply flex items-center gap-2; +} + +.group-has-data-[collapsible='icon']/sidebar-wrapper:h-12 .sidebar-header { + @apply h-12; +} diff --git a/resources/css/components/text-link.css b/resources/css/components/text-link.css new file mode 100644 index 0000000..415d2da --- /dev/null +++ b/resources/css/components/text-link.css @@ -0,0 +1,10 @@ +/* 3. TextLink Component */ +.c-text-link { + @apply underline underline-offset-4 transition-colors duration-300 ease-out; + color: var(--foreground); + text-decoration-color: var(--border); + + &:hover { + text-decoration-color: var(--foreground); + } +} diff --git a/resources/css/components/user-info.css b/resources/css/components/user-info.css new file mode 100644 index 0000000..f382ef4 --- /dev/null +++ b/resources/css/components/user-info.css @@ -0,0 +1,19 @@ +/* 5. UserInfo Component */ +.user-info__avatar { + @apply h-8 w-8 overflow-hidden; + border-radius: var(--radius); +} + +.user-info__details { + @apply grid flex-1 text-left text-sm leading-tight; + + .user-info__name { + @apply truncate font-medium; + color: var(--foreground); + } + + .user-info__email { + @apply truncate text-xs; + color: var(--muted-foreground); + } +} diff --git a/resources/js/app.ts b/resources/js/app.ts index 46d341c..45e170b 100644 --- a/resources/js/app.ts +++ b/resources/js/app.ts @@ -19,7 +19,7 @@ configureEcho({ forceTLS: false, enabledTransports: ['ws', 'wss'], }); -if (window) { +if (typeof window !== 'undefined') { (window as any).echoConfigured = true; } diff --git a/resources/js/components/AppContent.vue b/resources/js/components/AppContent.vue index bc99919..82f1a5e 100644 --- a/resources/js/components/AppContent.vue +++ b/resources/js/components/AppContent.vue @@ -22,11 +22,3 @@ const className = computed(() => props.class); - - diff --git a/resources/js/components/AppLogo.vue b/resources/js/components/AppLogo.vue index 313eff5..b6f7296 100644 --- a/resources/js/components/AppLogo.vue +++ b/resources/js/components/AppLogo.vue @@ -10,23 +10,3 @@ import AppLogoIcon from '@/components/AppLogoIcon.vue'; Laravel Starter Kit - - diff --git a/resources/js/components/AppSidebarHeader.vue b/resources/js/components/AppSidebarHeader.vue index 1af9362..0973fef 100644 --- a/resources/js/components/AppSidebarHeader.vue +++ b/resources/js/components/AppSidebarHeader.vue @@ -23,15 +23,3 @@ withDefaults( - - diff --git a/resources/js/components/AppearanceTabs.vue b/resources/js/components/AppearanceTabs.vue index 8663291..af2a1df 100644 --- a/resources/js/components/AppearanceTabs.vue +++ b/resources/js/components/AppearanceTabs.vue @@ -27,27 +27,3 @@ const tabs = [ - - diff --git a/resources/js/components/Chat.vue b/resources/js/components/Chat.vue index 9bea09b..2cb75a3 100644 --- a/resources/js/components/Chat.vue +++ b/resources/js/components/Chat.vue @@ -1,6 +1,6 @@