Skip to content
28 changes: 14 additions & 14 deletions packages/frontend-main/src/components/posts/PostActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ import { fractionalDigits } from '@/utility/atomics';
import { formatCompactAtomics, formatCompactNumber } from '@/utility/text';
import { showBroadcastingToast } from '@/utility/toast';

import { Button } from '../ui/button';
import Popover from '../ui/popover/Popover.vue';
import PopoverContent from '../ui/popover/PopoverContent.vue';
import PopoverTrigger from '../ui/popover/PopoverTrigger.vue';

const props = defineProps<{ post: Post }>();
const buttonWrapperClass = 'flex items-center flex-1 min-w-[84px]';
const buttonClass = 'flex flex-row items-center gap-1 p-2 rounded-full hover:bg-accent active:bg-accent transition-colors';
const amountTextClass = 'text-[#A2A2A9] text-xs font-medium hover:underline active:underline transition-colors';
const amountTextClass = 'text-muted-foreground text-xs font-normal hover:underline active:underline transition-colors';
const amountPopoverContentClass = 'py-2 px-3 size-fit';
const fullAmountTextClass = 'text-sm ';

Expand Down Expand Up @@ -107,9 +107,9 @@ async function onClickFlag() {
<template>
<div :class="cn('flex flex-row items-center justify-between pr-2 flex-wrap')">
<div :class="buttonWrapperClass">
<button :class="buttonClass" @click.stop="onClickReply">
<MessageCircle class="size-5" color="#A2A2A9" />
</button>
<Button variant="icon" size="icon" class="p-2" @click.stop="onClickReply">
<MessageCircle class="size-5" />
</Button>
<Popover>
<PopoverTrigger @click.stop>
<span :class="amountTextClass">{{ formatCompactNumber(post.replies) }}</span>
Expand All @@ -121,9 +121,9 @@ async function onClickFlag() {
</div>

<div :class="buttonWrapperClass">
<button :class="buttonClass" @click.stop="onClickLike">
<ThumbsUp class="size-5" color="#A2A2A9" />
</button>
<Button variant="icon" size="icon" class="p-2" @click.stop="onClickLike">
<ThumbsUp class="size-5" />
</Button>
<Popover>
<PopoverTrigger @click.stop>
<span :class="amountTextClass">{{ formatCompactAtomics(post.likes_burnt, fractionalDigits) }}</span>
Expand All @@ -135,9 +135,9 @@ async function onClickFlag() {
</div>

<div :class="buttonWrapperClass">
<button :class="buttonClass" @click.stop="onClickDislike">
<ThumbsDown class="size-5 scale-x-[-1]" color="#A2A2A9" />
</button>
<Button variant="icon" size="icon" class="p-2 opacity-60" @click.stop="onClickDislike">
<ThumbsDown class="size-5 scale-x-[-1]" />
</Button>
<Popover>
<PopoverTrigger @click.stop>
<span :class="amountTextClass">{{ formatCompactAtomics(post.dislikes_burnt, fractionalDigits) }}</span>
Expand All @@ -149,9 +149,9 @@ async function onClickFlag() {
</div>

<div :class="buttonWrapperClass">
<button :class="buttonClass" @click.stop="onClickFlag">
<Flag class="size-5" color="#A2A2A9" />
</button>
<Button variant="icon" size="icon" class="p-2 opacity-60" @click.stop="onClickFlag">
<Flag class="size-5" />
</Button>
<Popover>
<PopoverTrigger @click.stop>
<span :class="amountTextClass">{{ formatCompactAtomics(post.flags_burnt, fractionalDigits) }}</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const parsedMessage = computed((): MessageSegment[] => {
</script>

<template>
<div class="leading-6 text-sm">
<div class="leading-relaxed text-sm">
<template v-for="(segment, index) in parsedMessage" :key="`${index}-${segment.content}`">
<span v-if="segment.type === 'text'">{{ segment.content }}</span>
<a
Expand Down
11 changes: 6 additions & 5 deletions packages/frontend-main/src/components/posts/PostMoreActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import type { Post } from 'api-main/types/feed';
import { useClipboard } from '@vueuse/core';
import { Ellipsis, Link2 } from 'lucide-vue-next';

import { Button } from '@/components/ui/button';
import Icon from '@/components/ui/icon/Icon.vue';
import Popover from '@/components/ui/popover/Popover.vue';
import PopoverContent from '@/components/ui/popover/PopoverContent.vue';
import PopoverTrigger from '@/components/ui/popover/PopoverTrigger.vue';
import { useConfigStore } from '@/stores/useConfigStore';
import { cn } from '@/utility';

import Button from '../ui/button/Button.vue';
import Icon from '../ui/icon/Icon.vue';

const { post } = defineProps<{ post: Post }>();
const configStore = useConfigStore();

Expand All @@ -35,8 +34,10 @@ function gotoMintscan() {

<template>
<Popover>
<PopoverTrigger class="p-2 rounded-full hover:bg-accent active:bg-accent transition-colors" @click.stop>
<Ellipsis class="size-5" color="#A2A2A9" />
<PopoverTrigger as-child>
<Button variant="icon" size="icon" class="p-2" @click.stop>
<Ellipsis class="size-5" color="#A2A2A9" />
</Button>
</PopoverTrigger>

<PopoverContent class="p-2">
Expand Down
8 changes: 5 additions & 3 deletions packages/frontend-main/src/components/tma/TMAInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { ChevronDown, ChevronRight, Globe, Smartphone } from 'lucide-vue-next';
import { computed, onMounted, ref } from 'vue';

import { Button } from '@/components/ui/button';
import { useTMAStore } from '@/stores/useTMAStore';

import TelegramLogo from './telegram-logo.svg';
Expand Down Expand Up @@ -39,8 +40,9 @@ function toggleExpanded() {
<template>
<div v-if="tmaInfo.isInitialized" class="border-y md:border-x md:rounded-lg bg-background">
<!-- Summary -->
<button
class="w-full flex items-center justify-between p-4 text-left hover:bg-accent/50 transition-colors"
<Button
variant="ghost"
class="w-full flex items-center justify-between p-4 text-left h-auto"
@click="toggleExpanded"
>
<div class="flex items-center gap-3">
Expand Down Expand Up @@ -68,7 +70,7 @@ function toggleExpanded() {
class="size-4 text-muted-foreground transition-transform"
/>
</div>
</button>
</Button>

<!-- Details -->
<div
Expand Down
1 change: 1 addition & 0 deletions packages/frontend-main/src/components/ui/button/Button.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const props = withDefaults(defineProps<Props>(), {
:as="as"
:as-child="asChild"
:class="cn(buttonVariants({ variant, size }), props.class)"
v-bind="$attrs"
>
<slot />
</Primitive>
Expand Down
9 changes: 9 additions & 0 deletions packages/frontend-main/src/components/ui/button/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,23 @@ export const buttonVariants = cva(
'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80 active:bg-secondary/80',
ghost:
'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 active:bg-accent active:text-accent-foreground dark:active:bg-accent/50',
navigation:
'justify-start rounded-md hover:bg-accent/50 active:bg-accent transition-colors',
icon:
'rounded-full hover:bg-accent active:bg-accent transition-colors p-0',
link: 'text-primary underline-offset-4 hover:underline active:underline',
elevated:
'rounded-md border border-border/70 bg-background/60 backdrop-blur-sm shadow-[0_1px_3px_0_rgba(0,0,0,0.08)] hover:border-border hover:bg-background/85 hover:shadow-[0_2px_6px_0_rgba(0,0,0,0.12)] active:bg-background/95 active:shadow-[0_1px_2px_0_rgba(0,0,0,0.08)] transition-all duration-200',
},
size: {
default: 'h-13 px-4 has-[>svg]:px-3',
xs: 'h-8 rounded-xs gap-1 px-2 has-[>svg]:px-1.5',
sm: 'h-10 rounded-xs gap-1.5 px-3 has-[>svg]:px-2.5',
nav: 'h-11 px-3 gap-2.5',
lg: 'h-15 rounded-xs px-6 has-[>svg]:px-4',
icon: 'size-10',
iconSm: 'size-[40px]',
iconMd: 'size-[52px]',
},
},
defaultVariants: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ function inverseExponentialScale(amount: Decimal): number {
</script>

<template>
<div class="flex flex-col gap-4">
<label class="font-semibold text-sm">{{ $t('components.Filter.posts') }}</label>
<div class="flex flex-col gap-3">
<label class="text-xs font-medium text-muted-foreground/70 uppercase tracking-wider">{{ $t('components.Filter.posts') }}</label>
<Slider v-model="sliderValue" :min="min" :max="max" :step="step" class="cursor-pointer" />
<span class="text-sm">
<span class="text-xs text-muted-foreground/80">
{{ `${$t('components.Filter.amount')}: ${displayValue}` }}
</span>
</div>
Expand Down
17 changes: 10 additions & 7 deletions packages/frontend-main/src/components/ui/search/SearchInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@ function gotoExplore() {

<template>
<div class="relative">
<div class="flex items-center gap-2 relative z-10">
<Input v-model="query" :placeholder="$t('placeholders.search')" @keyup.enter="gotoExplore" />
<div class="flex flex-col gap-2">
<label class="text-xs font-medium text-muted-foreground/70 uppercase tracking-wider">Search</label>
<div class="flex items-center gap-2 relative z-10">
<Input v-model="query" :placeholder="$t('placeholders.search')" @keyup.enter="gotoExplore" />

<CircleX
v-if="query"
class="size-6 absolute right-2 top-1/2 -translate-y-1/2 cursor-pointer"
@click="clearSearch"
/>
<CircleX
v-if="query"
class="size-4 absolute right-2 top-1/2 -translate-y-1/2 cursor-pointer text-muted-foreground/60 hover:text-muted-foreground transition-colors"
@click="clearSearch"
/>
</div>
</div>

<div
Expand Down
68 changes: 42 additions & 26 deletions packages/frontend-main/src/components/ui/switch/ColorModeSwitch.vue
Original file line number Diff line number Diff line change
@@ -1,38 +1,54 @@
<script setup lang="ts">
import { useDark, useMediaQuery, useToggle } from '@vueuse/core';
import { Moon, Sun } from 'lucide-vue-next';
import { SwitchRoot, SwitchThumb } from 'reka-ui';
import { useMediaQuery } from '@vueuse/core';
import { Atom, Moon, Sun } from 'lucide-vue-next';
import { computed } from 'vue';

import { useColorTheme } from '@/composables/useColorTheme';
import { cn } from '@/utility';

const isSmallScreen = useMediaQuery(`(max-width: 480px)`);
const isDarkMode = useDark({ disableTransition: false });
const toggleColorMode = useToggle(isDarkMode);
const { theme, cycleTheme } = useColorTheme();

const themeIcon = computed(() => {
switch (theme.value) {
case 'dark':
return Moon;
case 'atomone':
return Atom;
default:
return Sun;
}
});

const themePosition = computed(() => {
switch (theme.value) {
case 'dark':
return 'translate-x-[1.5rem]';
case 'atomone':
return 'translate-x-[3rem]';
default:
return 'translate-x-0';
}
});
</script>

<template>
<div class="flex">
<SwitchRoot
data-slot="switch"
:model-value="isDarkMode"
<button
type="button"
:class="cn(
'relative h-10 rounded-full bg-input transition-colors',
isSmallScreen ? 'w-10' : 'w-[5.75rem]',
)"
:aria-label="`Switch to ${theme === 'light' ? 'dark' : theme === 'dark' ? 'atomone' : 'light'} mode`"
@click="cycleTheme"
>
<div
:class="cn(
'relative h-10 rounded-full bg-input',
isSmallScreen ? 'w-10' : 'w-16',
'absolute top-0.5 left-0.5 size-9 rounded-full bg-background !transition-transform duration-300 ease-in-out shadow-sm flex items-center justify-center',
themePosition,
)"
@update:model-value="toggleColorMode"
>
<SwitchThumb
data-slot="switch-thumb"
:class="cn(
'absolute top-1 left-1 size-8 rounded-full bg-background !transition-transform duration-300 ease-in-out',
!isSmallScreen && 'data-[state=checked]:translate-x-[1.5rem]',
)"
>
<div class="flex h-full w-full items-center justify-center">
<Moon v-if="isDarkMode" class="size-5" />
<Sun v-else class="size-5" />
</div>
</SwitchThumb>
</SwitchRoot>
</div>
<component :is="themeIcon" class="size-4 text-muted-foreground" />
</div>
</button>
</template>
8 changes: 4 additions & 4 deletions packages/frontend-main/src/components/ui/tabs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ import { cva } from 'class-variance-authority';
export { default as Tabs } from './RouterTabs.vue';

export const tabVariants = cva(
'inline-flex items-center justify-center whitespace-nowrap ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 relative rounded-none border-b-2 bg-transparent font-semibold shadow-none transition-none',
'inline-flex items-center justify-center whitespace-nowrap ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 relative rounded-none border-b bg-transparent font-medium shadow-none transition-colors',
{
variants: {
size: {
default: 'p-4 text-base border-b-2',
lg: 'p-6 text-lg border-b-4',
default: 'px-4 py-3 text-sm border-b-2',
lg: 'px-5 py-4 text-base border-b-2',
},
layout: {
default: '',
fill: 'flex-1',
},
state: {
active: 'border-b-primary text-foreground',
inactive: 'border-b-transparent text-muted-foreground',
inactive: 'border-b-transparent text-muted-foreground/70',
},
},
defaultVariants: {
Expand Down
8 changes: 5 additions & 3 deletions packages/frontend-main/src/components/users/UserAvatar.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<script lang="ts" setup>
import type { UserAvatarUsernameProps } from './UserAvatarUsername.vue';

import { useColorMode } from '@vueuse/core';
import { computed } from 'vue';

import { useColorTheme } from '@/composables/useColorTheme';
import { cn } from '@/utility';

import Avatar from '../ui/avatar/Avatar.vue';
Expand All @@ -11,12 +12,13 @@ import AvatarImage from '../ui/avatar/AvatarImage.vue';

defineProps<UserAvatarUsernameProps>();

const mode = useColorMode();
const { theme } = useColorTheme();
const isDarkTheme = computed(() => theme.value === 'dark' || theme.value === 'atomone');
</script>

<template>
<Avatar :class="cn(size === 'lg' ? 'size-[64px]' : size === 'sm' ? 'size-[32px]' : 'size-[40px]', !disabled && 'active:opacity-60 hover:opacity-60 transition-opacity', 'z-10')">
<AvatarImage v-if="userAddress" :class="mode === 'dark' && 'filter-[invert(0.96))]'" :src="`https://api.dicebear.com/9.x/notionists-neutral/svg?seed=${userAddress}`" alt="user-avatar-image" />
<AvatarImage v-if="userAddress" :class="isDarkTheme && 'filter-[invert(0.96))]'" :src="`https://api.dicebear.com/9.x/notionists-neutral/svg?seed=${userAddress}`" alt="user-avatar-image" />
<AvatarFallback v-else class="bg-[#D9D9D9] size-full" />
</Avatar>
</template>
2 changes: 1 addition & 1 deletion packages/frontend-main/src/components/users/Username.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ defineProps<UserAvatarUsernameProps>();
</script>

<template>
<span :class="cn(size === 'lg' ? 'text-lg' : size === 'sm' ? 'text-sm' : 'text-base', !disabled && 'active:underline hover:underline decoration-2', 'font-semibold')">{{ shorten(userAddress || '...............', 8, 4) }}</span>
<span :class="cn(size === 'lg' ? 'text-lg' : size === 'sm' ? 'text-sm' : 'text-sm', !disabled && 'active:underline hover:underline decoration-2', 'font-medium text-muted-foreground')">{{ shorten(userAddress || '...............', 8, 4) }}</span>
</template>
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<script lang="ts" setup>
import { MoreVertical } from 'lucide-vue-next';
import { computed, ref } from 'vue';
import { RouterLink } from 'vue-router';

import { Button } from '@/components/ui/button';
import {
Expand All @@ -22,20 +24,32 @@ const connectedState = computed(() => !isConnecting.value && loggedIn.value && !
</script>

<template>
<div>
<!-- Normal signed in account display -->
<div class="w-full">
<template v-if="connectedState">
<Popover>
<PopoverTrigger class="w-full">
<UserAvatarUsername :user-address="address" disabled class="h-[52px] px-4 gap-3 rounded-sm hover:bg-accent active:bg-accent transition-colors" />
</PopoverTrigger>

<WalletConnectPopoverContent />
</Popover>
<div class="flex w-full items-center gap-2.5 rounded-md px-3 py-2 hover:bg-accent/50 transition-colors">
<RouterLink
:to="`/profile/${address}`"
class="flex flex-1 items-center gap-2.5 active:opacity-70 transition-opacity"
>
<UserAvatarUsername :user-address="address" size="sm" disabled />
</RouterLink>

<Popover>
<PopoverTrigger class="p-1 rounded hover:bg-accent/70 active:bg-accent transition-colors shrink-0">
<MoreVertical class="size-4 text-muted-foreground" />
</PopoverTrigger>
<WalletConnectPopoverContent />
</Popover>
</div>
</template>

<template v-else>
<Button class="w-[207px]" @click="walletDialogStore.showDialog">
<Button
variant="elevated"
size="sm"
class="w-full"
@click="walletDialogStore.showDialog"
>
{{ $t('components.WalletConnect.button') }}
</Button>
</template>
Expand Down
Loading