refactor(web): use separator component

This commit is contained in:
daniel31x13
2025-06-24 14:52:09 -04:00
parent 803a97b7e0
commit 7bf4db9b25
43 changed files with 223 additions and 170 deletions

View File

@@ -2,6 +2,7 @@ import React, { ReactNode } from "react";
import { Button } from "@/components/ui/button";
import { useTranslation } from "next-i18next";
import Modal from "./Modal";
import { Separator } from "./ui/separator";
type Props = {
toggleModal: Function;
@@ -24,7 +25,7 @@ export default function ConfirmationModal({
return (
<Modal toggleModal={toggleModal} className={className}>
<p className="text-xl font-thin">{title}</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="mb-3 mt-1" />
{children}
<div className="w-full flex items-center justify-end gap-2 mt-3">
<Button

View File

@@ -24,6 +24,7 @@ import LinkIcon from "./LinkViews/LinkComponents/LinkIcon";
import LinkFormats from "./LinkViews/LinkComponents/LinkFormats";
import LinkTypeBadge from "./LinkViews/LinkComponents/LinkTypeBadge";
import LinkPin from "./LinkViews/LinkComponents/LinkPin";
import { Separator } from "./ui/separator";
export function DashboardLinks({
links,
@@ -174,7 +175,7 @@ export function Card({ link, editMode }: Props) {
</div>
)}
</div>
<hr className="divider my-0 border-t border-neutral-content h-[1px]" />
<Separator />
</div>
)}
@@ -191,7 +192,7 @@ export function Card({ link, editMode }: Props) {
{(show.collection || show.date) && (
<div>
<hr className="divider mt-0 mb-1 last:hidden border-t border-neutral-content h-[1px]" />
<Separator className="mb-1" />
<div className="flex justify-between items-center text-xs text-neutral px-3 pb-1 gap-2">
{show.collection && !isPublicRoute && (

View File

@@ -9,6 +9,7 @@ import clsx from "clsx";
import Link from "next/link";
import { useTranslation } from "next-i18next";
import { Button } from "./ui/button";
import { Separator } from "./ui/separator";
type Props = {
onClose: Function;
@@ -28,7 +29,8 @@ const HighlightDrawer = ({ onClose }: Props) => {
direction="left"
>
<div>
<h2 className="text-lg font-semibold mb-5">{t("notes_highlights")}</h2>
<h2 className="text-lg font-semibold">{t("notes_highlights")}</h2>
<Separator className="my-5" />
{data && data.length > 0 ? (
data.map((highlight) => {
const formattedDate = new Date(highlight.createdAt).toLocaleString(

View File

@@ -36,6 +36,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { Separator } from "./ui/separator";
type Props = {
className?: string;
@@ -521,7 +522,7 @@ export default function LinkDetails({
link={link}
downloadable={true}
/>
<hr className="m-3 border-t border-neutral-content" />
<Separator className="my-3" />
</>
) : undefined}
@@ -538,7 +539,7 @@ export default function LinkDetails({
link={link}
downloadable={true}
/>
<hr className="m-3 border-t border-neutral-content" />
<Separator className="my-3" />
</>
) : undefined}
@@ -551,7 +552,7 @@ export default function LinkDetails({
link={link}
downloadable={true}
/>
<hr className="m-3 border-t border-neutral-content" />
<Separator className="my-3" />
</>
) : undefined}
@@ -563,7 +564,7 @@ export default function LinkDetails({
format={ArchivedFormat.readability}
link={link}
/>
<hr className="m-3 border-t border-neutral-content" />
<Separator className="my-3" />
</>
) : undefined}

View File

@@ -28,6 +28,7 @@ import useLocalSettingsStore from "@/store/localSettings";
import LinkPin from "./LinkPin";
import LinkFormats from "./LinkFormats";
import openLink from "@/lib/client/openLink";
import { Separator } from "@/components/ui/separator";
type Props = {
link: LinkIncludingShortenedCollectionAndTags;
@@ -211,7 +212,7 @@ export default function LinkCard({ link, columns, editMode }: Props) {
</div>
)}
</div>
<hr className="divider my-0 border-t border-neutral-content h-[1px]" />
<Separator />
</div>
)}
@@ -228,7 +229,7 @@ export default function LinkCard({ link, columns, editMode }: Props) {
{(show.collection || show.date) && (
<div>
<hr className="divider mt-0 mb-1 last:hidden border-t border-neutral-content h-[1px]" />
<Separator className="mb-1" />
<div className="flex justify-between items-center text-xs text-neutral px-3 pb-1 gap-2">
{show.collection && !isPublicRoute && (

View File

@@ -31,6 +31,7 @@ import { useRouter } from "next/router";
import LinkFormats from "./LinkFormats";
import openLink from "@/lib/client/openLink";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
type Props = {
link: LinkIncludingShortenedCollectionAndTags;
@@ -200,7 +201,7 @@ export default function LinkMasonry({ link, editMode, columns }: Props) {
)}
</div>
<hr className="divider my-0 border-t border-neutral-content h-[1px]" />
<Separator />
</div>
)}
@@ -247,7 +248,7 @@ export default function LinkMasonry({ link, editMode, columns }: Props) {
{(show.collection || show.date) && (
<div>
<hr className="divider mt-0 mb-1 last:hidden border-t border-neutral-content h-[1px]" />
<Separator className="mb-1" />
<div className="flex flex-wrap justify-between items-center text-xs text-neutral px-3 pb-1 w-full gap-x-2">
{!isPublicRoute && show.collection && (

View File

@@ -5,6 +5,7 @@ import { Button } from "@/components/ui/button";
import { useTranslation } from "next-i18next";
import { useBulkDeleteLinks } from "@linkwarden/router/links";
import toast from "react-hot-toast";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -45,7 +46,7 @@ export default function BulkDeleteLinksModal({ onClose }: Props) {
: t("delete_links", { count: selectedLinks.length })}
</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-3">
<p>

View File

@@ -8,6 +8,7 @@ import Modal from "../Modal";
import { useTranslation } from "next-i18next";
import { useBulkEditLinks } from "@linkwarden/router/links";
import { Button } from "../ui/button";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -70,7 +71,8 @@ export default function BulkEditLinksModal({ onClose }: Props) {
? t("edit_link")
: t("edit_links", { count: selectedLinks.length })}
</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="mt-5">
<div className="grid sm:grid-cols-2 gap-3">
<div>

View File

@@ -8,6 +8,7 @@ import { Button } from "@/components/ui/button";
import { useTranslation } from "next-i18next";
import { useDeleteCollection } from "@linkwarden/router/collections";
import toast from "react-hot-toast";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -63,7 +64,7 @@ export default function DeleteCollectionModal({
{permissions === true ? t("delete_collection") : t("leave_collection")}
</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-3">
{permissions === true ? (

View File

@@ -6,6 +6,7 @@ import { Button } from "@/components/ui/button";
import { useTranslation } from "next-i18next";
import { useDeleteLink } from "@linkwarden/router/links";
import toast from "react-hot-toast";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -51,7 +52,7 @@ export default function DeleteLinkModal({ onClose, activeLink }: Props) {
<Modal toggleModal={onClose}>
<p className="text-xl font-thin text-red-500">{t("delete_link")}</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-3">
<p>{t("link_deletion_confirmation_message")}</p>

View File

@@ -5,6 +5,7 @@ import { useTranslation } from "next-i18next";
import toast from "react-hot-toast";
import { RssSubscription } from "@linkwarden/prisma/client";
import { useDeleteRssSubscription } from "@linkwarden/router/rss";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -45,7 +46,7 @@ export default function DeleteRssSubscriptionModal({
<Modal toggleModal={onClose}>
<p className="text-xl font-thin text-red-500">{t("delete_link")}</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-3">
<p>{t("rss_deletion_confirmation")}</p>

View File

@@ -5,6 +5,7 @@ import { useDeleteUser } from "@linkwarden/router/users";
import { useState } from "react";
import { useSession } from "next-auth/react";
import { useConfig } from "@linkwarden/router/config";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -44,7 +45,7 @@ export default function DeleteUserModal({ onClose, userId }: Props) {
{isAdmin ? t("delete_user") : t("remove_user")}
</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-3">
<p>{t("confirm_user_deletion")}</p>

View File

@@ -9,6 +9,7 @@ import IconPicker from "../IconPicker";
import { IconWeight } from "@phosphor-icons/react";
import oklchVariableToHex from "@/lib/client/oklchVariableToHex";
import { Button } from "../ui/button";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -55,7 +56,7 @@ export default function EditCollectionModal({
<Modal toggleModal={onClose}>
<p className="text-xl font-thin">{t("edit_collection_info")}</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-3">
<div className="flex flex-col gap-3">

View File

@@ -25,6 +25,7 @@ import {
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { User } from "@linkwarden/prisma/client";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -113,7 +114,7 @@ export default function EditCollectionSharingModal({
: t("team")}
</p>
<div className="divider mb-3 mt-1" />
<Separator className="my-3" />
<div className="flex flex-col gap-3">
{permissions === true && !isPublicRoute && (
@@ -154,7 +155,7 @@ export default function EditCollectionSharingModal({
)}
{permissions === true && !isPublicRoute && (
<div className="divider my-3" />
<Separator className="my-3" />
)}
{permissions === true && !isPublicRoute && (
@@ -233,7 +234,7 @@ export default function EditCollectionSharingModal({
</div>
</div>
<div className="divider my-0 last:hidden h-[1px]"></div>
<Separator />
{collection.members
.sort((a, b) => (a.userId as number) - (b.userId as number))
@@ -261,98 +262,103 @@ export default function EditCollectionSharingModal({
};
return (
<div
key={e.userId}
className="relative p-3 bg-base-200 rounded-xl flex gap-2 justify-between border-none"
>
<div className="flex items-center">
<ProfilePhoto
src={e.user.image ? e.user.image : undefined}
name={e.user.name}
/>
<div className="ml-2">
<p className="text-sm font-semibold">{e.user.name}</p>
<p className="text-xs text-neutral">
@{e.user.username}
</p>
<>
<div
key={e.userId}
className="relative p-3 bg-base-200 rounded-xl flex gap-2 justify-between border-none"
>
<div className="flex items-center">
<ProfilePhoto
src={e.user.image ? e.user.image : undefined}
name={e.user.name}
/>
<div className="ml-2">
<p className="text-sm font-semibold">
{e.user.name}
</p>
<p className="text-xs text-neutral">
@{e.user.username}
</p>
</div>
</div>
<div className="flex items-center gap-2">
{permissions === true && !isPublicRoute ? (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8">
{t(roleKey)} <i className="bi-chevron-down" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent sideOffset={4} align="end">
<DropdownMenuRadioGroup
value={roleKey}
onValueChange={handleRoleChange}
>
<DropdownMenuRadioItem value="viewer">
<div>
<p className="font-bold whitespace-nowrap">
{t("viewer")}
</p>
<p className="whitespace-nowrap">
{t("viewer_desc")}
</p>
</div>
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="contributor">
<div>
<p className="font-bold whitespace-nowrap">
{t("contributor")}
</p>
<p className="whitespace-nowrap">
{t("contributor_desc")}
</p>
</div>
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="admin">
<div>
<p className="font-bold whitespace-nowrap">
{t("admin")}
</p>
<p className="whitespace-nowrap">
{t("admin_desc")}
</p>
</div>
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
) : (
<p className="text-sm text-neutral">{t(roleKey)}</p>
)}
{permissions === true && !isPublicRoute && (
<Button
variant="ghost"
size="icon"
className="text-neutral hover:text-red-500"
onClick={() => {
setCollection({
...collection,
members: collection.members.filter(
(member) => member.userId !== e.userId
),
});
}}
>
<i
className="bi-x text-xl"
title={t("remove_member")}
/>
</Button>
)}
</div>
</div>
<div className="flex items-center gap-2">
{permissions === true && !isPublicRoute ? (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8">
{t(roleKey)} <i className="bi-chevron-down" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent sideOffset={4} align="end">
<DropdownMenuRadioGroup
value={roleKey}
onValueChange={handleRoleChange}
>
<DropdownMenuRadioItem value="viewer">
<div>
<p className="font-bold whitespace-nowrap">
{t("viewer")}
</p>
<p className="whitespace-nowrap">
{t("viewer_desc")}
</p>
</div>
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="contributor">
<div>
<p className="font-bold whitespace-nowrap">
{t("contributor")}
</p>
<p className="whitespace-nowrap">
{t("contributor_desc")}
</p>
</div>
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="admin">
<div>
<p className="font-bold whitespace-nowrap">
{t("admin")}
</p>
<p className="whitespace-nowrap">
{t("admin_desc")}
</p>
</div>
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
) : (
<p className="text-sm text-neutral">{t(roleKey)}</p>
)}
{permissions === true && !isPublicRoute && (
<Button
variant="ghost"
size="icon"
className="text-neutral hover:text-red-500"
onClick={() => {
setCollection({
...collection,
members: collection.members.filter(
(member) => member.userId !== e.userId
),
});
}}
>
<i
className="bi-x text-xl"
title={t("remove_member")}
/>
</Button>
)}
</div>
</div>
<Separator className="last:hidden" />
</>
);
})}
</div>

View File

@@ -3,6 +3,7 @@ import TextInput from "@/components/TextInput";
import Modal from "../Modal";
import { useTranslation } from "next-i18next";
import { Button } from "../ui/button";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -24,7 +25,7 @@ export default function EmailChangeVerificationModal({
<Modal toggleModal={onClose}>
<p className="text-xl font-thin">{t("confirm_password")}</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-5">
<p>

View File

@@ -7,6 +7,7 @@ import { useAddUser } from "@linkwarden/router/users";
import Link from "next/link";
import { signIn } from "next-auth/react";
import { Button } from "../ui/button";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -69,7 +70,9 @@ export default function InviteModal({ onClose }: Props) {
return (
<Modal toggleModal={onClose}>
<p className="text-xl font-thin">{t("invite_user")}</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<p className="mb-3">{t("invite_user_desc")}</p>
<form onSubmit={submit}>
{emailEnabled ? (

View File

@@ -10,6 +10,7 @@ import IconPicker from "../IconPicker";
import { IconWeight } from "@phosphor-icons/react";
import oklchVariableToHex from "@/lib/client/oklchVariableToHex";
import { Button } from "../ui/button";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -72,7 +73,7 @@ export default function NewCollectionModal({ onClose, parent }: Props) {
<p className="text-xl font-thin">{t("create_new_collection")}</p>
)}
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-3">
<div className="flex flex-col gap-3">

View File

@@ -11,6 +11,7 @@ import { useAddLink } from "@linkwarden/router/links";
import toast from "react-hot-toast";
import { PostLinkSchemaType } from "@linkwarden/lib/schemaValidation";
import { Button } from "@/components/ui/button";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -95,7 +96,9 @@ export default function NewLinkModal({ onClose }: Props) {
return (
<Modal toggleModal={onClose}>
<p className="text-xl font-thin">{t("create_new_link")}</p>
<div className="divider mb-3 mt-1" />
<Separator className="my-3" />
<div className="grid grid-flow-row-dense sm:grid-cols-5 gap-3">
<div className="sm:col-span-3 col-span-5">
<p className="mb-2">{t("link")}</p>

View File

@@ -6,6 +6,7 @@ import toast from "react-hot-toast";
import TextInput from "../TextInput";
import CollectionSelection from "../InputSelect/CollectionSelection";
import { Button } from "../ui/button";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -57,7 +58,9 @@ export default function NewRssSubscriptionModal({ onClose }: Props) {
<Modal toggleModal={onClose}>
<>
<p className="text-xl font-thin">{t("create_rss_subscription")}</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="flex sm:flex-row flex-col gap-3 items-center">
<div className="w-full">
<label>{t("name")}</label>

View File

@@ -14,6 +14,7 @@ import {
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
} from "@/components/ui/dropdown-menu";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -87,7 +88,7 @@ export default function NewTokenModal({ onClose }: Props) {
<>
<p className="text-xl font-thin">{t("create_access_token")}</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="flex sm:flex-row flex-col gap-2 items-center">
<div className="w-full">

View File

@@ -5,6 +5,7 @@ import { FormEvent, useState } from "react";
import { useTranslation, Trans } from "next-i18next";
import { useAddUser } from "@linkwarden/router/users";
import { Button } from "../ui/button";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -70,7 +71,7 @@ export default function NewUserModal({ onClose }: Props) {
<Modal toggleModal={onClose}>
<p className="text-xl font-thin">{t("create_new_user")}</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<form onSubmit={submit}>
<div className="grid sm:grid-cols-2 gap-3">

View File

@@ -5,6 +5,7 @@ import { useTranslation } from "next-i18next";
import { AccessToken } from "@linkwarden/prisma/client";
import { useRevokeToken } from "@linkwarden/router/tokens";
import toast from "react-hot-toast";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -42,7 +43,7 @@ export default function DeleteTokenModal({ onClose, activeToken }: Props) {
<Modal toggleModal={onClose}>
<p className="text-xl font-thin text-red-500">{t("revoke_token")}</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-3">
<p>{t("revoke_confirmation")}</p>

View File

@@ -2,6 +2,7 @@ import React, { useState } from "react";
import Modal from "../Modal";
import { Button } from "@/components/ui/button";
import { useTranslation } from "next-i18next";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -17,7 +18,7 @@ export default function SurveyModal({ onClose, submit }: Props) {
<Modal toggleModal={onClose}>
<p className="text-xl font-thin">{t("quick_survey")}</p>
<div className="divider mb-3 mt-1"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-4">
<p>{t("how_did_you_discover_linkwarden")}</p>

View File

@@ -12,6 +12,7 @@ import { useUploadFile } from "@linkwarden/router/links";
import { PostLinkSchemaType } from "@linkwarden/lib/schemaValidation";
import { useConfig } from "@linkwarden/router/config";
import { Button } from "@/components/ui/button";
import { Separator } from "../ui/separator";
type Props = {
onClose: Function;
@@ -99,7 +100,8 @@ export default function UploadFileModal({ onClose }: Props) {
<div className="flex gap-2 items-start">
<p className="text-xl font-thin">{t("upload_file")}</p>
</div>
<div className="divider mb-3 mt-1" />
<Separator className="my-3" />
<div className="grid grid-flow-row-dense sm:grid-cols-5 gap-3">
<div className="sm:col-span-3 col-span-5">

View File

@@ -1,17 +0,0 @@
import clsx from "clsx";
import React from "react";
type Props = {
className?: string;
vertical?: boolean;
};
function Divider({ className, vertical = false }: Props) {
return vertical ? (
<hr className={clsx("border-neutral-content border-l h-full", className)} />
) : (
<hr className={clsx("border-neutral-content border-t", className)} />
);
}
export default Divider;

View File

@@ -6,8 +6,8 @@ import { useTranslation } from "next-i18next";
import getServerSideProps from "@/lib/client/getServerSideProps";
import UserListing from "@/components/UserListing";
import { useUsers } from "@linkwarden/router/users";
import Divider from "@/components/ui/Divider";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
interface User extends U {
subscriptions: {
@@ -92,7 +92,7 @@ export default function Admin() {
</div>
</div>
<Divider className="my-3" />
<Separator className="my-3" />
{searchQuery && filteredUsers && filteredUsers.length > 0 ? (
<UserListing

View File

@@ -7,6 +7,7 @@ import { FormEvent, useState } from "react";
import { toast } from "react-hot-toast";
import getServerSideProps from "@/lib/client/getServerSideProps";
import { useTranslation } from "next-i18next";
import { Separator } from "@/components/ui/separator";
interface FormData {
password: string;
@@ -70,7 +71,7 @@ export default function ResetPassword() {
{requestSent ? t("password_updated") : t("reset_password")}
</p>
<div className="divider my-0"></div>
<Separator />
{!requestSent ? (
<>

View File

@@ -34,6 +34,7 @@ import {
DropdownMenuSeparator,
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
export default function Index() {
const { t } = useTranslation();
@@ -273,7 +274,7 @@ export default function Index() {
{activeCollection?.description && <p>{activeCollection.description}</p>}
<div className="divider my-0" />
<Separator />
{collections.some((e) => e.parentId === activeCollection?.id) && (
<>

View File

@@ -6,6 +6,7 @@ import toast from "react-hot-toast";
import { useTranslation } from "next-i18next";
import getServerSideProps from "@/lib/client/getServerSideProps";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
export default function EmailConfirmaion() {
const router = useRouter();
@@ -42,7 +43,7 @@ export default function EmailConfirmaion() {
{t("check_your_email")}
</p>
<div className="divider my-3"></div>
<Separator className="my-3" />
{router.query.email && typeof router.query.email === "string" && (
<p className="text-center font-bold mb-3 break-all">

View File

@@ -6,6 +6,7 @@ import { FormEvent, useState } from "react";
import { toast } from "react-hot-toast";
import getServerSideProps from "@/lib/client/getServerSideProps";
import { useTranslation } from "next-i18next";
import { Separator } from "@/components/ui/separator";
interface FormData {
email: string;
@@ -66,7 +67,7 @@ export default function Forgot() {
{isEmailSent ? t("email_sent") : t("forgot_password")}
</p>
<div className="divider my-0"></div>
<Separator />
{!isEmailSent ? (
<>

View File

@@ -14,6 +14,7 @@ import { getToken } from "next-auth/jwt";
import { prisma } from "@linkwarden/prisma";
import { useTranslation } from "next-i18next";
import { useRouter } from "next/router";
import { Separator } from "@/components/ui/separator";
interface FormData {
username: string;
@@ -91,7 +92,8 @@ export default function Login({
<p className="text-3xl text-black dark:text-white text-center font-extralight">
{t("enter_credentials")}
</p>
<hr className="border-1 border-sky-100 dark:border-neutral-700" />
<Separator />
{process.env.NEXT_PUBLIC_DEMO === "true" &&
process.env.NEXT_PUBLIC_DEMO_USERNAME &&
@@ -205,7 +207,11 @@ export default function Login({
</Button>
{availableLogins.buttonAuths.length > 0 && (
<div className="divider my-1">{t("or_continue_with")}</div>
<div className="flex items-center gap-2">
<Separator className="my-1 flex-1 w-auto" />
<p className="whitespace-nowrap">{t("or_continue_with")}</p>
<Separator className="my-1 flex-1 w-auto" />
</div>
)}
</>
);

View File

@@ -8,6 +8,7 @@ import { toast } from "react-hot-toast";
import getServerSideProps from "@/lib/client/getServerSideProps";
import { Trans, useTranslation } from "next-i18next";
import { useUpdateUser, useUser } from "@linkwarden/router/user";
import { Separator } from "@/components/ui/separator";
interface FormData {
password: string;
@@ -70,7 +71,7 @@ export default function MemberOnboarding() {
{t("invitation_accepted")}
</p>
<div className="divider my-0"></div>
<Separator />
<p
style={{

View File

@@ -30,6 +30,7 @@ import {
TooltipTrigger,
} from "@/components/ui/tooltip";
import { useUser } from "@linkwarden/router/user";
import { Separator } from "@/components/ui/separator";
export default function PublicCollections() {
const { t } = useTranslation();
@@ -228,7 +229,7 @@ export default function PublicCollections() {
</div>
</div>
<div className="divider mt-5 mb-0"></div>
<Separator className="mt-5" />
<div className="flex mb-5 mt-10 flex-col gap-5">
<LinkListOptions

View File

@@ -14,6 +14,7 @@ import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { i18n } from "next-i18next.config";
import { Trans, useTranslation } from "next-i18next";
import { useConfig } from "@linkwarden/router/config";
import { Separator } from "@/components/ui/separator";
type FormData = {
name: string;
@@ -167,7 +168,7 @@ export default function Register({
{t("enter_details")}
</p>
<div className="divider my-0"></div>
<Separator />
<div>
<p className="text-sm w-fit font-semibold mb-1">
@@ -284,7 +285,11 @@ export default function Register({
</Button>
{availableLogins.buttonAuths.length > 0 && (
<div className="divider my-1">{t("or_continue_with")}</div>
<div className="flex items-center gap-2">
<Separator className="my-1 flex-1 w-auto" />
<p className="whitespace-nowrap">{t("or_continue_with")}</p>
<Separator className="my-1 flex-1 w-auto" />
</div>
)}
{displayLoginExternalButton()}

View File

@@ -13,6 +13,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { Separator } from "@/components/ui/separator";
export default function AccessTokens() {
const [newTokenModal, setNewTokenModal] = useState(false);
@@ -33,7 +34,7 @@ export default function AccessTokens() {
{t("access_tokens")}
</p>
<div className="divider my-3"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-3">
<p>{t("access_tokens_description")}</p>

View File

@@ -24,6 +24,7 @@ import {
DropdownMenuItem,
DropdownMenuSeparator,
} from "@/components/ui/dropdown-menu";
import { Separator } from "@/components/ui/separator";
export default function Account() {
const [emailChangeVerificationModal, setEmailChangeVerificationModal] =
@@ -149,7 +150,7 @@ export default function Account() {
{t("accountSettings")}
</p>
<div className="divider my-3"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-5">
<div className="grid sm:grid-cols-2 gap-3 auto-rows-auto">
@@ -308,7 +309,7 @@ export default function Account() {
</p>
</div>
<div className="divider my-3"></div>
<Separator className="my-3" />
<div className="flex gap-3 flex-col">
<div>
@@ -335,7 +336,7 @@ export default function Account() {
</p>
</div>
<div className="divider my-3"></div>
<Separator className="my-3" />
<p>
{t("delete_account_warning")}

View File

@@ -19,6 +19,7 @@ import {
DropdownMenuSeparator,
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
interface User extends U {
subscriptions: {
@@ -65,7 +66,7 @@ export default function Billing() {
{t("billing_settings")}
</p>
<div className="divider my-3"></div>
<Separator className="my-3" />
<div className="w-full mx-auto flex flex-col gap-3 justify-between">
<p className="text-md">
@@ -94,7 +95,7 @@ export default function Billing() {
</p>
</div>
<div className="divider my-3"></div>
<Separator className="my-3" />
<div className="flex items-center justify-between gap-2 mb-3 relative">
<div>

View File

@@ -8,6 +8,7 @@ import { Button } from "@/components/ui/button";
import { useTranslation } from "next-i18next";
import getServerSideProps from "@/lib/client/getServerSideProps";
import { useUser } from "@linkwarden/router/user";
import { Separator } from "@/components/ui/separator";
export default function Delete() {
const [password, setPassword] = useState("");
@@ -74,7 +75,7 @@ export default function Delete() {
</p>
</div>
<div className="divider my-0"></div>
<Separator />
<p>{t("delete_warning")}</p>

View File

@@ -6,6 +6,7 @@ import { useTranslation } from "next-i18next";
import getServerSideProps from "@/lib/client/getServerSideProps";
import { useUpdateUser, useUser } from "@linkwarden/router/user";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
export default function Password() {
const { t } = useTranslation();
@@ -56,7 +57,7 @@ export default function Password() {
{t("change_password")}
</p>
<div className="divider my-3"></div>
<Separator className="my-3" />
<p className="mb-3">{t("password_change_instructions")}</p>
<div className="w-full flex flex-col gap-2 justify-between">

View File

@@ -23,6 +23,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { Separator } from "@/components/ui/separator";
export default function Preference() {
const { t } = useTranslation();
@@ -190,7 +191,7 @@ export default function Preference() {
<SettingsLayout>
<p className="capitalize text-3xl font-thin inline">{t("preference")}</p>
<div className="divider my-3"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-5">
<div>
@@ -214,13 +215,14 @@ export default function Preference() {
<div
key={theme}
className={`w-full text-center outline-solid outline-neutral-content outline h-20 duration-100 rounded-xl flex items-center justify-center cursor-pointer select-none ${bgColor} ${
localStorage.getItem("theme") === theme
account.theme === theme
? `outline-primary ${activeColor}`
: textColor
}`}
onClick={() =>
updateUserPreference.mutate({ theme: theme as any })
}
onClick={() => {
updateUserPreference.mutate({ theme: theme as any });
document.documentElement.setAttribute("data-theme", theme);
}}
>
<i className={`${icon} text-3xl`}></i>
<p className="ml-2 text-xl">{t(theme)}</p>
@@ -260,7 +262,7 @@ export default function Preference() {
{t("ai_settings")}
</p>
<div className="divider my-3"></div>
<Separator className="my-3" />
<p>{t("ai_tagging_method")}</p>
@@ -381,7 +383,9 @@ export default function Preference() {
<p className="capitalize text-3xl font-thin inline">
{t("archive_settings")}
</p>
<div className="divider my-3"></div>
<Separator className="my-3" />
<p>{t("formats_to_archive")}</p>
<div className="p-3">
<Checkbox
@@ -485,7 +489,9 @@ export default function Preference() {
<p className="capitalize text-3xl font-thin inline">
{t("link_settings")}
</p>
<div className="divider my-3"></div>
<Separator className="my-3" />
<div className="mb-3">
<Checkbox
label={t("prevent_duplicate_links")}

View File

@@ -8,6 +8,7 @@ import { RssSubscription } from "@linkwarden/prisma/client";
import NewRssSubscriptionModal from "@/components/ModalContent/NewRssSubscriptionModal";
import { useConfig } from "@linkwarden/router/config";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
export default function RssSubscriptions() {
const { t } = useTranslation();
@@ -31,7 +32,8 @@ export default function RssSubscriptions() {
{t("rss_subscriptions")}
</p>
<div className="divider my-3"></div>
<Separator className="my-3" />
<div className="flex flex-col gap-3">
<p>
{t("rss_subscriptions_desc", {

View File

@@ -7,6 +7,7 @@ import { LinkArchiveActionSchemaType } from "@linkwarden/lib/schemaValidation";
import toast from "react-hot-toast";
import { useArchiveAction } from "@linkwarden/router/links";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
export default function Worker() {
const { t } = useTranslation();
@@ -54,7 +55,7 @@ export default function Worker() {
<SettingsLayout>
<p className="capitalize text-3xl font-thin inline">{t("worker")}</p>
<div className="divider my-3"></div>
<Separator className="my-3" />
<div className="w-full flex flex-col gap-6 justify-between">
<div className="flex flex-col sm:flex-row sm:items-center gap-3">

View File

@@ -8,6 +8,7 @@ import { Button } from "@/components/ui/button";
import getServerSideProps from "@/lib/client/getServerSideProps";
import { Trans, useTranslation } from "next-i18next";
import { useUser } from "@linkwarden/router/user";
import { Separator } from "@/components/ui/separator";
export default function Subscribe() {
const { t } = useTranslation();
@@ -53,7 +54,7 @@ export default function Subscribe() {
{t("subscribe_title")}
</p>
<div className="divider my-0"></div>
<Separator />
<div>
<p>