mirror of
https://github.com/Xevion/rdap.git
synced 2025-12-05 23:15:58 -06:00
feat: add OverlayScrollbars for improved scrolling UI
Replace native ScrollArea with OverlayScrollbars library in AbstractCard raw view and main page layout. Provides consistent, customizable scrollbars with auto-hide behavior across the application.
This commit is contained in:
@@ -35,6 +35,8 @@
|
||||
"date-fns-tz": "^3.2.0",
|
||||
"next": "^15.5.6",
|
||||
"next-themes": "^0.4.6",
|
||||
"overlayscrollbars": "^2.12.0",
|
||||
"overlayscrollbars-react": "^0.5.6",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0",
|
||||
"react-hook-form": "^7.42.1",
|
||||
|
||||
22
pnpm-lock.yaml
generated
22
pnpm-lock.yaml
generated
@@ -44,6 +44,12 @@ importers:
|
||||
next-themes:
|
||||
specifier: ^0.4.6
|
||||
version: 0.4.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||
overlayscrollbars:
|
||||
specifier: ^2.12.0
|
||||
version: 2.12.0
|
||||
overlayscrollbars-react:
|
||||
specifier: ^0.5.6
|
||||
version: 0.5.6(overlayscrollbars@2.12.0)(react@19.2.0)
|
||||
react:
|
||||
specifier: 19.2.0
|
||||
version: 19.2.0
|
||||
@@ -3328,6 +3334,15 @@ packages:
|
||||
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
overlayscrollbars-react@0.5.6:
|
||||
resolution: {integrity: sha512-E5To04bL5brn9GVCZ36SnfGanxa2I2MDkWoa4Cjo5wol7l+diAgi4DBc983V7l2nOk/OLJ6Feg4kySspQEGDBw==}
|
||||
peerDependencies:
|
||||
overlayscrollbars: ^2.0.0
|
||||
react: '>=16.8.0'
|
||||
|
||||
overlayscrollbars@2.12.0:
|
||||
resolution: {integrity: sha512-mWJ5MOkcZ/ljHwfLw8+bN0V9ziGCoNoqULcp994j5DTGNQvnkWKWkA7rnO29Kyew5AoHxUnJ4Ndqfcl0HSQjXg==}
|
||||
|
||||
own-keys@1.0.1:
|
||||
resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -7363,6 +7378,13 @@ snapshots:
|
||||
type-check: 0.4.0
|
||||
word-wrap: 1.2.5
|
||||
|
||||
overlayscrollbars-react@0.5.6(overlayscrollbars@2.12.0)(react@19.2.0):
|
||||
dependencies:
|
||||
overlayscrollbars: 2.12.0
|
||||
react: 19.2.0
|
||||
|
||||
overlayscrollbars@2.12.0: {}
|
||||
|
||||
own-keys@1.0.1:
|
||||
dependencies:
|
||||
get-intrinsic: 1.3.0
|
||||
|
||||
@@ -2,7 +2,8 @@ import type { FunctionComponent, ReactNode } from "react";
|
||||
import React from "react";
|
||||
import { useBoolean } from "usehooks-ts";
|
||||
import { Link2Icon, CodeIcon, DownloadIcon, ClipboardIcon } from "@radix-ui/react-icons";
|
||||
import { Card, Flex, Box, IconButton, Code, ScrollArea, Tooltip } from "@radix-ui/themes";
|
||||
import { Card, Flex, Box, IconButton, Code, Tooltip } from "@radix-ui/themes";
|
||||
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
|
||||
|
||||
type AbstractCardProps = {
|
||||
children?: ReactNode;
|
||||
@@ -125,7 +126,16 @@ const AbstractCard: FunctionComponent<AbstractCardProps> = ({
|
||||
)}
|
||||
<Box p="4">
|
||||
{showRaw ? (
|
||||
<ScrollArea type="auto" scrollbars="both" style={{ maxHeight: "40rem" }}>
|
||||
<OverlayScrollbarsComponent
|
||||
defer
|
||||
options={{
|
||||
scrollbars: {
|
||||
autoHide: "leave",
|
||||
autoHideDelay: 1300,
|
||||
},
|
||||
}}
|
||||
style={{ maxHeight: "40rem" }}
|
||||
>
|
||||
<Code
|
||||
variant="ghost"
|
||||
size="2"
|
||||
@@ -137,7 +147,7 @@ const AbstractCard: FunctionComponent<AbstractCardProps> = ({
|
||||
>
|
||||
{JSON.stringify(data, null, 4)}
|
||||
</Code>
|
||||
</ScrollArea>
|
||||
</OverlayScrollbarsComponent>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { type AppType } from "next/dist/shared/lib/utils";
|
||||
import "@fontsource-variable/inter";
|
||||
import "@fontsource/ibm-plex-mono/400.css";
|
||||
import "@radix-ui/themes/styles.css";
|
||||
import "overlayscrollbars/overlayscrollbars.css";
|
||||
|
||||
import "@/styles/globals.css";
|
||||
import { DateFormatProvider } from "@/contexts/DateFormatContext";
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ThemeToggle } from "@/components/ThemeToggle";
|
||||
import { Maybe } from "true-myth";
|
||||
import { Flex, Container, Section, Text, Link, IconButton } from "@radix-ui/themes";
|
||||
import { GitHubLogoIcon } from "@radix-ui/react-icons";
|
||||
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
|
||||
|
||||
const Index: NextPage = () => {
|
||||
const { error, setTarget, setTargetType, submit, currentType } = useLookup();
|
||||
@@ -38,78 +39,89 @@ const Index: NextPage = () => {
|
||||
content="xevion, rdap, whois, rdap, domain name, dns, ip address"
|
||||
/>
|
||||
</Head>
|
||||
<Flex
|
||||
asChild
|
||||
justify="between"
|
||||
align="center"
|
||||
px="5"
|
||||
py="4"
|
||||
style={{
|
||||
borderBottom: "1px solid var(--gray-a5)",
|
||||
<OverlayScrollbarsComponent
|
||||
defer
|
||||
options={{
|
||||
scrollbars: {
|
||||
autoHide: "leave",
|
||||
autoHideDelay: 1300,
|
||||
},
|
||||
}}
|
||||
style={{ height: "100vh" }}
|
||||
>
|
||||
<nav>
|
||||
<Text size="5" weight="medium">
|
||||
<Link href="https://github.com/Xevion/rdap" color="gray" highContrast>
|
||||
rdap
|
||||
</Link>
|
||||
<Link href="https://xevion.dev" color="gray">
|
||||
.xevion.dev
|
||||
</Link>
|
||||
</Text>
|
||||
<Flex gap="4" align="center">
|
||||
<IconButton
|
||||
asChild
|
||||
size="3"
|
||||
variant="ghost"
|
||||
aria-label="View on GitHub"
|
||||
title="View on GitHub"
|
||||
>
|
||||
<a
|
||||
href="https://github.com/Xevion/rdap"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
<Flex
|
||||
asChild
|
||||
justify="between"
|
||||
align="center"
|
||||
px="5"
|
||||
py="4"
|
||||
style={{
|
||||
borderBottom: "1px solid var(--gray-a5)",
|
||||
}}
|
||||
>
|
||||
<nav>
|
||||
<Text size="5" weight="medium">
|
||||
<Link href="https://github.com/Xevion/rdap" color="gray" highContrast>
|
||||
rdap
|
||||
</Link>
|
||||
<Link href="https://xevion.dev" color="gray">
|
||||
.xevion.dev
|
||||
</Link>
|
||||
</Text>
|
||||
<Flex gap="4" align="center">
|
||||
<IconButton
|
||||
asChild
|
||||
size="3"
|
||||
variant="ghost"
|
||||
aria-label="View on GitHub"
|
||||
title="View on GitHub"
|
||||
>
|
||||
<GitHubLogoIcon width="22" height="22" />
|
||||
</a>
|
||||
</IconButton>
|
||||
<ThemeToggle />
|
||||
</Flex>
|
||||
</nav>
|
||||
</Flex>
|
||||
<Container size="3" px="5">
|
||||
<Section size="2">
|
||||
<LookupInput
|
||||
isLoading={isLoading}
|
||||
detectedType={currentType}
|
||||
onChange={({ target, targetType }) => {
|
||||
setTarget(target);
|
||||
setTargetType(targetType);
|
||||
}}
|
||||
onSubmit={async function (props) {
|
||||
try {
|
||||
setLoading(true);
|
||||
setResponse(await submit(props));
|
||||
setLoading(false);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
setResponse(Maybe.nothing());
|
||||
setLoading(false);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{error != null ? (
|
||||
<ErrorCard
|
||||
title="An error occurred while performing a lookup."
|
||||
description={error}
|
||||
className="mb-2"
|
||||
<a
|
||||
href="https://github.com/Xevion/rdap"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<GitHubLogoIcon width="22" height="22" />
|
||||
</a>
|
||||
</IconButton>
|
||||
<ThemeToggle />
|
||||
</Flex>
|
||||
</nav>
|
||||
</Flex>
|
||||
<Container size="3" px="5">
|
||||
<Section size="2">
|
||||
<LookupInput
|
||||
isLoading={isLoading}
|
||||
detectedType={currentType}
|
||||
onChange={({ target, targetType }) => {
|
||||
setTarget(target);
|
||||
setTargetType(targetType);
|
||||
}}
|
||||
onSubmit={async function (props) {
|
||||
try {
|
||||
setLoading(true);
|
||||
setResponse(await submit(props));
|
||||
setLoading(false);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
setResponse(Maybe.nothing());
|
||||
setLoading(false);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
{response.isJust ? (
|
||||
<Generic url={response.value.url} data={response.value.data} />
|
||||
) : null}
|
||||
</Section>
|
||||
</Container>
|
||||
{error != null ? (
|
||||
<ErrorCard
|
||||
title="An error occurred while performing a lookup."
|
||||
description={error}
|
||||
className="mb-2"
|
||||
/>
|
||||
) : null}
|
||||
{response.isJust ? (
|
||||
<Generic url={response.value.url} data={response.value.data} />
|
||||
) : null}
|
||||
</Section>
|
||||
</Container>
|
||||
</OverlayScrollbarsComponent>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -157,6 +157,7 @@ const LookupInput: FunctionComponent<LookupInputProps> = ({
|
||||
size="3"
|
||||
placeholder={placeholders[selected]}
|
||||
disabled={isLoading}
|
||||
autoFocus
|
||||
onFocus={() => {
|
||||
isFocusedRef.current = true;
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user