Skip to content

Commit

Permalink
dev: Added several components for the Navigation menu
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-crowell committed Jun 16, 2024
1 parent dee4ce4 commit ee5274c
Show file tree
Hide file tree
Showing 38 changed files with 2,757 additions and 1,704 deletions.
11 changes: 0 additions & 11 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
import doob from '@do-ob/eslint-config';
import reactCompiler from 'eslint-plugin-react-compiler';

export default [
...doob.configs.recommended,

{
plugins: {
'react-compiler': reactCompiler,
},
rules: {
...reactCompiler.rules.recommended,
'react-compiler/react-compiler': 'error',
},
},
];
24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,30 @@
"@do-ob/ts-config": "^2.0.0",
"@do-ob/vite-lib-config": "^3.0.1",
"@heroicons/react": "^2.1.3",
"@nextui-org/react": "^2.4.1",
"@storybook/addon-a11y": "^8.1.6",
"@storybook/addon-essentials": "^8.1.6",
"@storybook/addon-interactions": "^8.1.6",
"@storybook/addon-links": "^8.1.6",
"@storybook/addon-themes": "^8.1.6",
"@storybook/blocks": "^8.1.6",
"@storybook/react": "^8.1.6",
"@storybook/react-vite": "^8.1.6",
"@storybook/test": "^8.1.6",
"@nextui-org/react": "^2.4.2",
"@storybook/addon-a11y": "8.2.0-alpha.9",
"@storybook/addon-essentials": "8.2.0-alpha.9",
"@storybook/addon-interactions": "8.2.0-alpha.9",
"@storybook/addon-links": "8.2.0-alpha.9",
"@storybook/addon-themes": "8.2.0-alpha.9",
"@storybook/blocks": "8.2.0-alpha.9",
"@storybook/react": "8.2.0-alpha.9",
"@storybook/react-vite": "8.2.0-alpha.9",
"@storybook/test": "8.2.0-alpha.9",
"@types/node": "^20.12.12",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.0",
"autoprefixer": "^10.4.19",
"cssnano": "^7.0.2",
"eslint": "^9.2.0",
"eslint-plugin-react-compiler": "0.0.0-experimental-51a85ea-20240601",
"framer-motion": "^11.2.10",
"postcss": "^8.4.38",
"react": "18.3.1",
"react-dom": "18.3.1",
"storybook": "8.1.6",
"storybook": "8.2.0-alpha.9",
"tailwindcss": "^3.4.3",
"types-react": "19.0.0-rc.1",
"typescript": "^5.4.5",
"vite": "^5.2.11",
"vitest": "^1.6.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
"@heroicons/react": "^2.1.3",
"@nextui-org/react": "^2.4.1",
"framer-motion": "^11.2.10",
"react": "^18"
"react": "latest"
}
}
1 change: 1 addition & 0 deletions packages/ui/src/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './actions/search';
55 changes: 55 additions & 0 deletions packages/ui/src/actions/search.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Search State type
*/
export type SearchState = Array<{
/**
* The result ID
*/
id: string;

/**
* The result title
*/
title: string;

/**
* The result description
*/
description?: string;

/**
* The result URL
*/
url: string;

/**
* The result thumbnail
*/
thumbnail?: string;
}>;

/**
* Search Payload type
*/
export type SearchPayload = FormData & {
/**
* The search query
*/
query: string;
};

/**
* Search action type.
*/
export type SearchAction = (state: SearchState, payload: FormData) => Promise<SearchState>;

/**
* Search action type
*/
export const search: SearchAction = async (state, payload) => {
const query = payload.get('query');

console.log(`Searching for: ${query}`);

return state;
};
5 changes: 4 additions & 1 deletion packages/ui/src/components.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export { Form } from './components/Form/Form';
export { Navigation } from './components/Navigation/Navigation';
export { NavigationStandard } from './components/Navigation/NavigationStandard';
export { NavigationIsland } from './components/Navigation/NavigationIsland';
export { NavigationStandard } from './components/Navigation/NavigationStandard';
export { SearchButton } from './components/SearchButton/SearchButton';
export { SearchForm } from './components/SearchForm/SearchForm';
export { SearchInput } from './components/SearchInput/SearchInput';
export { ThemeSwitch } from './components/ThemeSwitch/ThemeSwitch';
72 changes: 72 additions & 0 deletions packages/ui/src/components/Form/Form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'use client';

import { nop } from '@do-ob/core';
import { useCallback, useRef, PropsWithChildren } from 'react';

/**
* Form properties
*/
export interface FormProps extends Omit<React.FormHTMLAttributes<HTMLFormElement>, 'action'> {
/**
* The form action.
*/
action?: (formData: FormData) => void;

/**
* If the form should submit on change
*/
changeSubmit?: boolean;

/**
* Change defer time
*/
changeDefer?: number;
}

/**
* A form that mimics React 19 form behavior.
*/
export function Form({
action = nop,
changeSubmit = false,
changeDefer = 250,
onChange = nop,
onSubmit = nop,
children,
}: PropsWithChildren<FormProps>) {

const debounceTimeout = useRef<NodeJS.Timeout | null>(null);

const handleChange = useCallback((e: React.ChangeEvent<HTMLFormElement>) => {
onChange(e);

if (!changeSubmit) {
return;
}
if (debounceTimeout.current) {
clearTimeout(debounceTimeout.current);
}

const currentTarget = e.currentTarget;
debounceTimeout.current = setTimeout(() => {
currentTarget.requestSubmit();
}, changeDefer);
}, [ changeDefer, onChange ]);

return (
<form
className="flex w-full flex-col gap-2"
onChange={changeSubmit ? handleChange : onChange}
onSubmit={(e) => {
e.preventDefault();
if (debounceTimeout.current) {
clearTimeout(debounceTimeout.current);
}
const formData = new FormData(e.currentTarget);
action(formData);
onSubmit(e);
}}
>
{children}
</form>);
}
31 changes: 30 additions & 1 deletion packages/ui/src/components/Navigation/Navigation.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react';

import { Navigation } from './Navigation';
import { Link } from '@do-ob/ui/types';
import { Link, SocialLinks } from '@do-ob/ui/types';

const meta = {
component: Navigation,
Expand Down Expand Up @@ -73,11 +73,36 @@ const links: Link[] = [
},
];

const socials: SocialLinks = [
{
type: 'facebook',
url: 'https://facebook.com',
},
{
type: 'instagram',
url: 'https://instagram.com',
},
{
type: 'linkedin',
url: 'https://linkedin.com',
},
{
type: 'x',
url: 'https://x.com',
},
{
type: 'youtube',
url: 'https://youtube.com',
},
];

export const Standard: Story = {
args: {
title: 'Navigation',
links,
search: '#search',
modeToggle: true,
socials,
},
};

Expand All @@ -87,6 +112,8 @@ export const Island: Story = {
variant: 'island',
links,
search: '#search',
modeToggle: true,
socials,
},
};

Expand All @@ -96,6 +123,8 @@ export const Extended: Story = {
variant: 'extended',
links,
search: '#search',
modeToggle: true,
socials,
},
};

Expand Down
24 changes: 22 additions & 2 deletions packages/ui/src/components/Navigation/Navigation.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Link, ThemeColor } from '@do-ob/ui/types';
import type { Link, ThemeColor, SocialLinks } from '@do-ob/ui/types';

import { NavigationStandard } from './NavigationStandard';
import { NavigationIsland } from './NavigationIsland';
Expand All @@ -13,7 +13,7 @@ export interface NavigationProps {
/**
* The brand image to display
*/
image?: string;
logo?: string;

/**
* The theme color of the navigation
Expand All @@ -34,6 +34,26 @@ export interface NavigationProps {
* The search form action URL
*/
search?: string;

/**
* Enable the dark mode toggle
*/
modeToggle?: boolean;

/**
* The social links of the navigation
*/
socials?: SocialLinks;

/**
* Class names to modify.
*/
classNames?: {
/**
* The logo image class name
*/
logo?: string;
}
}

export interface NavigationVariantProps extends NavigationProps {
Expand Down
12 changes: 6 additions & 6 deletions packages/ui/src/components/Navigation/NavigationExtended.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,29 @@ export function NavigationExtended({
color,
links,
className,
search
search,
modeToggle,
socials,
}: NavigationProps) {

const [ colors ] = twColors(color);

return (
<Navbar
className={clmg(clsx(color && colors, 'border-b-1 border-b-foreground-200/50', className))}
className={clmg(clsx(color && colors, 'relative border-b-1 border-b-foreground-200/50', className))}
height="4rem"
>
<NavbarContent justify="start">
<NavigationPart_Brand title={title} />
</NavbarContent>

<NavbarContent justify="center">
<NavbarContent justify="start">
<NavigationPart_Links links={links} colors={colors} />
</NavbarContent>

<NavbarContent justify="end">
<div className="max-w-64">
{search ? (
<NavigationPart_Actions search={search} />
) : null}
<NavigationPart_Actions search={search} modeToggle={modeToggle} socials={socials} />
</div>
</NavbarContent>

Expand Down
13 changes: 7 additions & 6 deletions packages/ui/src/components/Navigation/NavigationIsland.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,30 @@ import { NavigationPart_Actions } from './parts/NavigationPart_Actions';

export function NavigationIsland({
title,
image,
logo,
color,
links,
className,
search,
modeToggle,
socials,
classNames = {}
}: NavigationProps) {

const [ colors ] = twColors(color);

return (
<Navbar className="items-center justify-center" height="5rem">
<Navbar className="items-center justify-center bg-transparent backdrop-blur-none backdrop-filter-none" height="5rem">
<NavbarContent justify="start" className="flex items-center">
<NavigationPart_Brand title={title} image={image} />
<NavigationPart_Brand title={title} logo={logo} logoClassName={classNames.logo} />
</NavbarContent>
<NavbarContent justify="center">
<div className={clmg(clsx(color && colors, 'flex rounded-full border-1 border-foreground-200/50 px-4', className))}>
<NavigationPart_Links links={links} colors={colors} />
</div>
</NavbarContent>
<NavbarContent justify="end">
{search ? (
<NavigationPart_Actions search={search} />
) : null}
<NavigationPart_Actions search={search} modeToggle={modeToggle} socials={socials} />
</NavbarContent>
</Navbar>
);
Expand Down
Loading

0 comments on commit ee5274c

Please sign in to comment.