Skip to content

Commit

Permalink
add URL field to library pages
Browse files Browse the repository at this point in the history
  • Loading branch information
Southclaws committed Oct 11, 2024
1 parent da70d2f commit 6471277
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 17 deletions.
4 changes: 4 additions & 0 deletions web/panda.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { map } from "lodash/fp";
import { admonition } from "@/recipes/admonition";
import { button } from "@/recipes/button";
import { headingInput } from "@/recipes/heading-input";
import { input } from "@/recipes/input";
import { popover } from "@/recipes/popover";
import { richCard } from "@/recipes/rich-card";
import { treeView } from "@/recipes/tree-view";
import { typographyHeading } from "@/recipes/typography-heading";
Expand Down Expand Up @@ -228,13 +230,15 @@ export default defineConfig({
theme: {
extend: {
recipes: {
input: input,
admonition: admonition,
button: button,
headingInput: headingInput,
typographyHeading: typographyHeading,
richCard: richCard,
},
slotRecipes: {
popover: popover,
treeView: treeView,
},
semanticTokens,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use client";

import { useState } from "react";
import { Controller, ControllerProps } from "react-hook-form";

import { InfoTip } from "@/components/site/InfoTip";
import { FormErrorText } from "@/components/ui/FormErrorText";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Form } from "@/screens/library/LibraryPageScreen/useLibraryPageScreen";
import { HStack, LStack } from "@/styled-system/jsx";

function useLibraryPageImportFromURL() {
//
}

export function LibraryPageImportFromURL(
props: Omit<ControllerProps<Form>, "render">,
) {
return (
<Controller<Form>
control={props.control}
name={props.name}
render={(form) => {
//

return (
<LStack gap="0">
<HStack w="full" justify="space-between">
<Input
w="full"
size="sm"
variant="ghost"
color="fg.muted"
placeholder="External URL..."
{...form.field}
/>

{/* <HStack>
<InfoTip title="Generating a page from a URL">
Importing a URL will fetch the content and store it in this
page.
</InfoTip>
<Button type="button" size="xs" variant="subtle">
Import
</Button>
</HStack> */}
</HStack>
<FormErrorText>{form.fieldState.error?.message}</FormErrorText>
</LStack>
);
}}
/>
);
}
34 changes: 34 additions & 0 deletions web/src/components/site/InfoTip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { InfoIcon } from "lucide-react";
import { PropsWithChildren } from "react";

import * as Popover from "@/components/ui/popover";
import { LStack } from "@/styled-system/jsx";

import { IconButton } from "../ui/icon-button";

type Props = {
title: string;
};

export function InfoTip({ title, children }: PropsWithChildren<Props>) {
return (
<Popover.Root>
<Popover.Trigger asChild>
<IconButton size="xs" variant="ghost" borderRadius="full">
<InfoIcon />
</IconButton>
</Popover.Trigger>
<Popover.Positioner>
<Popover.Content>
<Popover.Arrow>
<Popover.ArrowTip />
</Popover.Arrow>
<LStack gap="1">
<Popover.Title>{title}</Popover.Title>
<Popover.Description>{children}</Popover.Description>
</LStack>
</Popover.Content>
</Popover.Positioner>
</Popover.Root>
);
}
4 changes: 3 additions & 1 deletion web/src/components/ui/link-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ export function LinkButton({

const isExternal = !href.toString().startsWith("/");

const target = isExternal ? "_blank" : undefined;

return (
<NextLink className={cn} href={href}>
<NextLink className={cn} href={href} target={target}>
<styled.span
display="flex"
// Supports overflowing children and text ellipsis
Expand Down
66 changes: 66 additions & 0 deletions web/src/recipes/input.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { defineRecipe } from "@pandacss/dev";

export const input = defineRecipe({
className: "input",
jsx: ["Input", "Field.Input"],
base: {
appearance: "none",
background: "none",
borderColor: "border.default",
borderRadius: "l2",
borderWidth: "1px",
colorPalette: "accent",
color: "fg.default",
outline: 0,
position: "relative",
transitionDuration: "normal",
transitionProperty: "box-shadow, border-color",
transitionTimingFunction: "default",
width: "full",
_disabled: {
opacity: 0.4,
cursor: "not-allowed",
},
_focus: {
borderColor: "colorPalette.default",
boxShadow: "0 0 0 1px var(--colors-color-palette-default)",
},
_invalid: {
borderColor: "fg.error",
_focus: {
borderColor: "fg.error",
boxShadow: "0 0 0 1px var(--colors-border-error)",
},
},
_placeholder: {
color: "fg.subtle",
opacity: "full",
},
},
defaultVariants: {
size: "md",
variant: "outline",
},
variants: {
size: {
"2xs": { px: "1.5", h: "7", minW: "7", fontSize: "xs" },
xs: { px: "2", h: "8", minW: "8", fontSize: "xs" },
sm: { px: "2.5", h: "9", minW: "9", fontSize: "sm" },
md: { px: "3", h: "10", minW: "10", fontSize: "md" },
lg: { px: "3.5", h: "11", minW: "11", fontSize: "md" },
xl: { px: "4", h: "12", minW: "12", fontSize: "lg" },
"2xl": { px: "4.5", h: "16", minW: "16", textStyle: "3xl" },
},
variant: {
outline: {},
ghost: {
borderColor: "transparent",
px: "0",
_focus: {
borderColor: "transparent",
boxShadow: "0 0 0 0px var(--colors-color-palette-default)",
},
},
},
},
});
50 changes: 50 additions & 0 deletions web/src/recipes/popover.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { popoverAnatomy } from "@ark-ui/anatomy";
import { defineSlotRecipe } from "@pandacss/dev";

export const popover = defineSlotRecipe({
className: "popover",
slots: popoverAnatomy.keys(),
base: {
positioner: {
position: "relative",
},
content: {
background: "bg.default",
borderRadius: "l3",
boxShadow: "lg",
display: "flex",
flexDirection: "column",
maxWidth: "sm",
zIndex: "popover",
p: "4",
_open: {
animation: "fadeIn 0.25s ease-out",
},
_closed: {
animation: "fadeOut 0.2s ease-out",
},
_hidden: {
display: "none",
},
},
title: {
fontWeight: "medium",
textStyle: "sm",
},
description: {
color: "fg.muted",
textStyle: "sm",
},
closeTrigger: {
color: "fg.muted",
},
arrow: {
"--arrow-size": "var(--sizes-3)",
"--arrow-background": "var(--colors-bg-default)",
},
arrowTip: {
borderTopWidth: "1px",
borderLeftWidth: "1px",
},
},
});
30 changes: 23 additions & 7 deletions web/src/screens/library/LibraryPageScreen/LibraryPageScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
"use client";

import { isEmpty } from "lodash";
import Link from "next/link";
import { FormProvider } from "react-hook-form";

import { CancelAction } from "src/components/site/Action/Cancel";
import { EditAction } from "src/components/site/Action/Edit";
import { SaveAction } from "src/components/site/Action/Save";

import { Breadcrumbs } from "@/components/library/Breadcrumbs";
import { LibraryPageImportFromURL } from "@/components/library/LibraryPageImportFromURL/LibraryPageImportFromURL";
import { LibraryPageMenu } from "@/components/library/LibraryPageMenu/LibraryPageMenu";
import { NodeCardRows } from "@/components/library/NodeCardList";
import { Admonition } from "@/components/ui/admonition";
import { Anchor } from "@/components/site/Anchor";
import { Heading } from "@/components/ui/heading";
import { LinkButton } from "@/components/ui/link-button";
import * as Popover from "@/components/ui/popover";
import { HStack, LStack, VStack, styled } from "@/styled-system/jsx";
import { HStack, LStack, styled } from "@/styled-system/jsx";

import { ContentInput } from "./ContentInput";
import { TitleInput } from "./TitleInput";
Expand Down Expand Up @@ -87,8 +89,8 @@ export function LibraryPageScreen(props: Props) {
)}
</HStack>

<VStack w="full" alignItems="start" gap="2">
<VStack alignItems="start" w="full" minW="0">
<LStack gap="2">
<LStack minW="0">
<HStack w="full" justify="space-between" alignItems="end">
{editing ? (
<TitleInput />
Expand All @@ -98,8 +100,22 @@ export function LibraryPageScreen(props: Props) {
</Heading>
)}
</HStack>
</VStack>
</VStack>
</LStack>
</LStack>

<LStack gap="2">
<HStack w="full">
{editing ? (
<LibraryPageImportFromURL control={form.control} name="link" />
) : (
node.link?.url && (
<LinkButton href={node.link?.url} size="xs" variant="subtle">
{node.link?.domain}
</LinkButton>
)
)}
</HStack>
</LStack>

<ContentInput
disabled={!editing}
Expand Down
28 changes: 25 additions & 3 deletions web/src/screens/library/LibraryPageScreen/useLibraryPageScreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ import { useLibraryPath } from "../useLibraryPath";
export const FormSchema = z.object({
name: z.string().min(1, "Please enter a name."),
slug: z.string().optional(),
link: z.preprocess((v) => {
if (typeof v === "string" && v === "") {
return undefined;
}

return v;
}, z.string().url("Invalid URL").optional()),

content: z.string().optional(),
});
export type Form = z.infer<typeof FormSchema>;
Expand Down Expand Up @@ -64,6 +72,7 @@ export function useLibraryPageScreen({
() => ({
name: node.name,
slug: node.slug,
link: node.link?.url,
description: node.description,
content: node.content,
}),
Expand All @@ -87,7 +96,12 @@ export function useLibraryPageScreen({
function handleEditMode() {
if (editing) {
setEditing(false);
form.reset(node);
form.reset({
name: node.name,
slug: node.slug,
link: node.link?.url,
content: node.content,
});

if (isNew) {
router.back();
Expand All @@ -96,7 +110,12 @@ export function useLibraryPageScreen({
if (!isAllowedToEdit) return;

setEditing(true);
form.reset(node);
form.reset({
name: node.name,
slug: node.slug,
link: node.link?.url,
content: node.content,
});
}
}

Expand All @@ -105,7 +124,10 @@ export function useLibraryPageScreen({

handle(
async () => {
await onSave(payload);
await onSave({
...payload,
url: payload.link,
});
setEditing(false);
},
{
Expand Down
4 changes: 2 additions & 2 deletions web/styled-system/recipes/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ export * from './badge';
export * from './code';
export * from './form-label';
export * from './icon';
export * from './input';
export * from './kbd';
export * from './link';
export * from './skeleton';
export * from './spinner';
export * from './textarea';
export * from './text';
export * from './input';
export * from './admonition';
export * from './button';
export * from './heading-input';
Expand Down Expand Up @@ -53,6 +53,6 @@ export * from './tabs';
export * from './tags-input';
export * from './toast';
export * from './toggle-group';
export * from './tooltip';
export * from './qr-code';
export * from './tooltip';
export * from './tree-view';
Loading

0 comments on commit 6471277

Please sign in to comment.