feat: switch to mist color from tailwind

This commit is contained in:
Aarnav Tale
2026-03-08 23:48:03 -04:00
parent df5e04f239
commit 0ce411e92b
49 changed files with 2738 additions and 2991 deletions
+163 -186
View File
@@ -1,205 +1,182 @@
import { closestCorners, DndContext, DragOverlay } from '@dnd-kit/core';
import { closestCorners, DndContext, DragOverlay } from "@dnd-kit/core";
import { restrictToParentElement, restrictToVerticalAxis } from "@dnd-kit/modifiers";
import {
restrictToParentElement,
restrictToVerticalAxis,
} from '@dnd-kit/modifiers';
import {
arrayMove,
SortableContext,
useSortable,
verticalListSortingStrategy,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { GripVertical, Lock } from 'lucide-react';
import { useEffect, useState } from 'react';
import { Form } from 'react-router';
import Button from '~/components/Button';
import Input from '~/components/Input';
import TableList from '~/components/TableList';
import cn from '~/utils/cn';
arrayMove,
SortableContext,
useSortable,
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { GripVertical, Lock } from "lucide-react";
import { useEffect, useState } from "react";
import { Form } from "react-router";
import Button from "~/components/Button";
import Input from "~/components/Input";
import TableList from "~/components/TableList";
import cn from "~/utils/cn";
interface Props {
searchDomains: string[];
isDisabled: boolean;
magic?: string;
searchDomains: string[];
isDisabled: boolean;
magic?: string;
}
export default function ManageDomains({
searchDomains,
isDisabled,
magic,
}: Props) {
const [activeId, setActiveId] = useState<number | string | null>(null);
const [localDomains, setLocalDomains] = useState(searchDomains);
export default function ManageDomains({ searchDomains, isDisabled, magic }: Props) {
const [activeId, setActiveId] = useState<number | string | null>(null);
const [localDomains, setLocalDomains] = useState(searchDomains);
useEffect(() => {
setLocalDomains(searchDomains);
}, [searchDomains]);
useEffect(() => {
setLocalDomains(searchDomains);
}, [searchDomains]);
return (
<div className="flex flex-col w-full sm:w-2/3">
<h1 className="text-2xl font-medium mb-4">Search Domains</h1>
<p className="mb-4">
Set custom DNS search domains for your Tailnet. When using Magic DNS,
your tailnet domain is used as the first search domain.
</p>
<DndContext
collisionDetection={closestCorners}
modifiers={[restrictToVerticalAxis, restrictToParentElement]}
onDragEnd={(event) => {
setActiveId(null);
const { active, over } = event;
if (!over) {
return;
}
return (
<div className="flex w-full flex-col sm:w-2/3">
<h1 className="mb-4 text-2xl font-medium">Search Domains</h1>
<p className="mb-4">
Set custom DNS search domains for your Tailnet. When using Magic DNS, your tailnet domain is
used as the first search domain.
</p>
<DndContext
collisionDetection={closestCorners}
modifiers={[restrictToVerticalAxis, restrictToParentElement]}
onDragEnd={(event) => {
setActiveId(null);
const { active, over } = event;
if (!over) {
return;
}
const activeItem = localDomains[(active.id as number) - 1];
const overItem = localDomains[(over.id as number) - 1];
const activeItem = localDomains[(active.id as number) - 1];
const overItem = localDomains[(over.id as number) - 1];
if (!activeItem || !overItem) {
return;
}
if (!activeItem || !overItem) {
return;
}
const oldIndex = localDomains.indexOf(activeItem);
const newIndex = localDomains.indexOf(overItem);
const oldIndex = localDomains.indexOf(activeItem);
const newIndex = localDomains.indexOf(overItem);
if (oldIndex !== newIndex) {
setLocalDomains(arrayMove(localDomains, oldIndex, newIndex));
}
}}
onDragStart={(event) => {
setActiveId(event.active.id);
}}
>
<TableList>
{magic ? (
<TableList.Item key="magic-dns-sd">
<div
className={cn(
'flex items-center gap-4',
isDisabled ? 'flex-row-reverse justify-between w-full' : '',
)}
>
<Lock className="p-0.5" />
<p className="font-mono text-sm py-0.5">{magic}</p>
</div>
</TableList.Item>
) : undefined}
<SortableContext
items={localDomains}
strategy={verticalListSortingStrategy}
>
{localDomains.map((sd, index) => (
<Domain
domain={sd}
id={index + 1}
isDisabled={isDisabled}
key={sd}
/>
))}
<DragOverlay adjustScale>
{activeId ? (
<Domain
domain={localDomains[(activeId as number) - 1]}
id={(activeId as number) - 1}
isDisabled={isDisabled}
isDragging
/>
) : undefined}
</DragOverlay>
</SortableContext>
{isDisabled ? undefined : (
<TableList.Item key="add-sd">
<Form
className="flex items-center justify-between w-full"
method="POST"
>
<input name="action_id" type="hidden" value="add_domain" />
<Input
className={cn(
'border-none font-mono p-0 text-sm',
'rounded-none focus:ring-0 w-full ml-1',
)}
isRequired
label="Search Domain"
labelHidden
name="domain"
placeholder="Search Domain"
type="text"
/>
<Button
className={cn(
'px-2 py-1 rounded-md',
'text-blue-500 dark:text-blue-400',
)}
type="submit"
>
Add
</Button>
</Form>
</TableList.Item>
)}
</TableList>
</DndContext>
</div>
);
if (oldIndex !== newIndex) {
setLocalDomains(arrayMove(localDomains, oldIndex, newIndex));
}
}}
onDragStart={(event) => {
setActiveId(event.active.id);
}}
>
<TableList>
{magic ? (
<TableList.Item key="magic-dns-sd">
<div
className={cn(
"flex items-center gap-4",
isDisabled ? "flex-row-reverse justify-between w-full" : "",
)}
>
<Lock className="p-0.5" />
<p className="py-0.5 font-mono text-sm">{magic}</p>
</div>
</TableList.Item>
) : undefined}
<SortableContext items={localDomains} strategy={verticalListSortingStrategy}>
{localDomains.map((sd, index) => (
<Domain domain={sd} id={index + 1} isDisabled={isDisabled} key={sd} />
))}
<DragOverlay adjustScale>
{activeId ? (
<Domain
domain={localDomains[(activeId as number) - 1]}
id={(activeId as number) - 1}
isDisabled={isDisabled}
isDragging
/>
) : undefined}
</DragOverlay>
</SortableContext>
{isDisabled ? undefined : (
<TableList.Item key="add-sd">
<Form className="flex w-full items-center justify-between" method="POST">
<input name="action_id" type="hidden" value="add_domain" />
<Input
className={cn(
"border-none font-mono p-0 text-sm",
"rounded-none focus:ring-0 w-full ml-1",
)}
isRequired
label="Search Domain"
labelHidden
name="domain"
placeholder="Search Domain"
type="text"
/>
<Button
className={cn("px-2 py-1 rounded-md", "text-blue-500 dark:text-blue-400")}
type="submit"
>
Add
</Button>
</Form>
</TableList.Item>
)}
</TableList>
</DndContext>
</div>
);
}
interface DomainProps {
domain: string;
id: number;
isDragging?: boolean;
isDisabled: boolean;
domain: string;
id: number;
isDragging?: boolean;
isDisabled: boolean;
}
function Domain({ domain, id, isDragging, isDisabled }: DomainProps) {
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
isDragging: isSortableDragging,
} = useSortable({ id });
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
isDragging: isSortableDragging,
} = useSortable({ id });
return (
<TableList.Item
className={cn(
isSortableDragging ? 'opacity-50' : '',
isDragging ? 'ring-3 bg-white dark:bg-headplane-900' : '',
)}
ref={setNodeRef}
style={{
transform: CSS.Transform.toString(transform),
transition,
}}
>
<p className="font-mono text-sm flex items-center gap-4">
{isDisabled ? undefined : (
<GripVertical
{...attributes}
{...listeners}
className="p-0.5 focus:ring-3 outline-hidden rounded-md"
/>
)}
{domain}
</p>
{isDragging ? undefined : (
<Form method="POST">
<input name="action_id" type="hidden" value="remove_domain" />
<input name="domain" type="hidden" value={domain} />
<Button
className={cn(
'px-2 py-1 rounded-md',
'text-red-500 dark:text-red-400',
)}
isDisabled={isDisabled}
type="submit"
>
Remove
</Button>
</Form>
)}
</TableList.Item>
);
return (
<TableList.Item
className={cn(
isSortableDragging ? "opacity-50" : "",
isDragging ? "ring-3 bg-white dark:bg-mist-900" : "",
)}
ref={setNodeRef}
style={{
transform: CSS.Transform.toString(transform),
transition,
}}
>
<p className="flex items-center gap-4 font-mono text-sm">
{isDisabled ? undefined : (
<GripVertical
{...attributes}
{...listeners}
className="rounded-md p-0.5 outline-hidden focus:ring-3"
/>
)}
{domain}
</p>
{isDragging ? undefined : (
<Form method="POST">
<input name="action_id" type="hidden" value="remove_domain" />
<input name="domain" type="hidden" value={domain} />
<Button
className={cn("px-2 py-1 rounded-md", "text-red-500 dark:text-red-400")}
isDisabled={isDisabled}
type="submit"
>
Remove
</Button>
</Form>
)}
</TableList.Item>
);
}
+66 -70
View File
@@ -1,77 +1,73 @@
import { Form } from 'react-router';
import Button from '~/components/Button';
import Code from '~/components/Code';
import Link from '~/components/Link';
import TableList from '~/components/TableList';
import cn from '~/utils/cn';
import AddRecord from '../dialogs/add-record';
import { Form } from "react-router";
import Button from "~/components/Button";
import Code from "~/components/Code";
import Link from "~/components/Link";
import TableList from "~/components/TableList";
import cn from "~/utils/cn";
import AddRecord from "../dialogs/add-record";
interface Props {
records: { name: string; type: 'A' | string; value: string }[];
isDisabled: boolean;
records: { name: string; type: "A" | string; value: string }[];
isDisabled: boolean;
}
export default function ManageRecords({ records, isDisabled }: Props) {
return (
<div className="flex flex-col w-full sm:w-2/3">
<h1 className="text-2xl font-medium mb-4">DNS Records</h1>
<p>
Headscale supports adding custom DNS records to your Tailnet. As of now,
only <Code>A</Code> and <Code>AAAA</Code> records are supported.{' '}
<Link
name="Headscale DNS Records documentation"
to="https://headscale.net/stable/ref/dns"
>
Learn More
</Link>
</p>
<div className="mt-4">
<TableList className="mb-8">
{records.length === 0 ? (
<TableList.Item>
<p className="opacity-50 mx-auto">No DNS records found</p>
</TableList.Item>
) : (
records.map((record) => (
<TableList.Item key={`${record.name}-${record.value}`}>
<div className="flex gap-2 items-center w-full">
<p
className={cn(
'font-mono text-sm font-bold py-1 px-2 rounded-md text-center',
'bg-headplane-100 dark:bg-headplane-700/30 min-w-12',
)}
>
{record.type}
</p>
<div className="flex flex-col sm:flex-row sm:gap-2 flex-1 min-w-0">
<p className="font-mono text-sm truncate">{record.name}</p>
<p className="font-mono text-sm truncate opacity-70 sm:opacity-100">
{record.value}
</p>
</div>
</div>
<Form method="POST">
<input name="action_id" type="hidden" value="remove_record" />
<input name="record_name" type="hidden" value={record.name} />
<input name="record_type" type="hidden" value={record.type} />
<Button
className={cn(
'px-2 py-1 rounded-md',
'text-red-500 dark:text-red-400',
)}
isDisabled={isDisabled}
type="submit"
>
Remove
</Button>
</Form>
</TableList.Item>
))
)}
</TableList>
return (
<div className="flex w-full flex-col sm:w-2/3">
<h1 className="mb-4 text-2xl font-medium">DNS Records</h1>
<p>
Headscale supports adding custom DNS records to your Tailnet. As of now, only <Code>A</Code>{" "}
and <Code>AAAA</Code> records are supported.{" "}
<Link name="Headscale DNS Records documentation" to="https://headscale.net/stable/ref/dns">
Learn More
</Link>
</p>
<div className="mt-4">
<TableList className="mb-8">
{records.length === 0 ? (
<TableList.Item>
<p className="mx-auto opacity-50">No DNS records found</p>
</TableList.Item>
) : (
records.map((record) => (
<TableList.Item key={`${record.name}-${record.value}`}>
<div className="flex w-full items-center gap-2">
<p
className={cn(
"font-mono text-sm font-bold py-1 px-2 rounded-md text-center",
"bg-mist-100 dark:bg-mist-700/30 min-w-12",
)}
>
{record.type}
</p>
<div className="flex min-w-0 flex-1 flex-col sm:flex-row sm:gap-2">
<p className="truncate font-mono text-sm">{record.name}</p>
<p className="truncate font-mono text-sm opacity-70 sm:opacity-100">
{record.value}
</p>
</div>
</div>
<Form method="POST">
<input name="action_id" type="hidden" value="remove_record" />
<input name="record_name" type="hidden" value={record.name} />
<input name="record_type" type="hidden" value={record.type} />
<Button
className={cn("px-2 py-1 rounded-md", "text-red-500 dark:text-red-400")}
isDisabled={isDisabled}
type="submit"
>
Remove
</Button>
</Form>
</TableList.Item>
))
)}
</TableList>
{isDisabled ? undefined : <AddRecord records={records} />}
</div>
</div>
);
{isDisabled ? undefined : <AddRecord records={records} />}
</div>
</div>
);
}