Skip to content

Commit

Permalink
add component hierarchy to the preview app (#896)
Browse files Browse the repository at this point in the history
* add component hierarchy to the preview app

* fix font issue

* align hover style between tab and vertical tab

* fixes according to review comments

* fix dropdown style (font-sans)

* fix vertical tab padding

* update due to b96ee0f (Button+TextField > shadcn)
  • Loading branch information
Sebastian-ubs authored May 28, 2024
1 parent 5397a9f commit 46b4853
Show file tree
Hide file tree
Showing 13 changed files with 737 additions and 384 deletions.
1 change: 1 addition & 0 deletions lib/platform-bible-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-tabs": "^1.0.4",
"autoprefixer": "^10.4.19",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ const DropdownMenuContent = React.forwardRef<
ref={ref}
sideOffset={sideOffset}
className={cn(
'pr-z-50 pr-min-w-[8rem] pr-overflow-hidden pr-rounded-md pr-border pr-bg-popover pr-p-1 pr-text-popover-foreground pr-shadow-md data-[state=open]:pr-animate-in data-[state=closed]:pr-animate-out data-[state=closed]:pr-fade-out-0 data-[state=open]:pr-fade-in-0 data-[state=closed]:pr-zoom-out-95 data-[state=open]:pr-zoom-in-95 data-[side=bottom]:pr-slide-in-from-top-2 data-[side=left]:pr-slide-in-from-right-2 data-[side=right]:pr-slide-in-from-left-2 data-[side=top]:pr-slide-in-from-bottom-2',
/* pr-font-sans is added to mitigate issue introduced by scopedPreflightStyles */
'pr-z-50 pr-min-w-[8rem] pr-overflow-hidden pr-rounded-md pr-border pr-bg-popover pr-p-1 pr-font-sans pr-text-popover-foreground pr-shadow-md data-[state=open]:pr-animate-in data-[state=closed]:pr-animate-out data-[state=closed]:pr-fade-out-0 data-[state=open]:pr-fade-in-0 data-[state=closed]:pr-zoom-out-95 data-[state=open]:pr-zoom-in-95 data-[side=bottom]:pr-slide-in-from-top-2 data-[side=left]:pr-slide-in-from-right-2 data-[side=right]:pr-slide-in-from-left-2 data-[side=top]:pr-slide-in-from-bottom-2',
className,
)}
{...props}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// adapted from: https://github.com/shadcn-ui/ui/discussions/752
/* eslint-disable react/prop-types */

'use client';

import * as React from 'react';
import * as TabsPrimitive from '@radix-ui/react-tabs';

import { cn } from '@/utils/shadcn-ui.util';

const VerticalTabs = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Root
orientation="vertical"
ref={ref}
className={cn('pr-flex pr-gap-1 pr-rounded-md pr-text-muted-foreground', className)}
{...props}
/>
));

VerticalTabs.displayName = TabsPrimitive.List.displayName;

const VerticalTabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={cn(
'pr-flex-fit pr-mlk-items-center pr-w-[124px] pr-justify-center pr-rounded-md pr-bg-muted pr-p-1 pr-text-muted-foreground',
className,
)}
{...props}
/>
));
VerticalTabsList.displayName = TabsPrimitive.List.displayName;

type LeftTabsTriggerProps = React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger> & {
value: string;
};

const VerticalTabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
LeftTabsTriggerProps
>(({ className, ...props }, ref) => (
<TabsPrimitive.Trigger
ref={ref}
{...props}
className={cn(
'overflow-clip pr-inline-flex pr-w-[116px] pr-cursor-pointer pr-items-center pr-justify-center pr-break-words pr-rounded-sm pr-border-0 pr-bg-muted pr-px-3 pr-py-1.5 pr-text-sm pr-font-medium pr-text-inherit pr-ring-offset-background pr-transition-all hover:pr-text-foreground focus-visible:pr-outline-none focus-visible:pr-ring-2 focus-visible:pr-ring-ring focus-visible:pr-ring-offset-2 disabled:pr-pointer-events-none disabled:pr-opacity-50 data-[state=active]:pr-bg-background data-[state=active]:pr-text-foreground data-[state=active]:pr-shadow-sm',
className,
)}
>
<div className="pr-flex pr-flex-col pr-justify-center">
<div>{props.value}</div>
</div>
</TabsPrimitive.Trigger>
));

const VerticalTabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Content
ref={ref}
className={cn(
'mt-2 pr-ml-5 pr-flex-grow pr-text-foreground pr-ring-offset-background focus-visible:pr-outline-none focus-visible:pr-ring-2 focus-visible:pr-ring-ring focus-visible:pr-ring-offset-2',
className,
)}
{...props}
/>
));
VerticalTabsContent.displayName = TabsPrimitive.Content.displayName;

export { VerticalTabs, VerticalTabsList, VerticalTabsTrigger, VerticalTabsContent };
54 changes: 54 additions & 0 deletions lib/platform-bible-react/src/components/shadcn-ui/tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* eslint-disable react/prop-types */
import * as React from 'react';
import * as TabsPrimitive from '@radix-ui/react-tabs';

import { cn } from '@/utils/shadcn-ui.util';

const Tabs = TabsPrimitive.Root;

const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={cn(
'pr-inline-flex pr-h-10 pr-items-center pr-justify-center pr-rounded-md pr-bg-muted pr-p-1 pr-text-muted-foreground',
className,
)}
{...props}
/>
));
TabsList.displayName = TabsPrimitive.List.displayName;

const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Trigger
ref={ref}
className={cn(
'pr-inline-flex pr-items-center pr-justify-center pr-whitespace-nowrap pr-rounded-sm pr-px-3 pr-py-1.5 pr-text-sm pr-font-medium pr-ring-offset-background pr-transition-all hover:pr-text-foreground focus-visible:pr-outline-none focus-visible:pr-ring-2 focus-visible:pr-ring-ring focus-visible:pr-ring-offset-2 disabled:pr-pointer-events-none disabled:pr-opacity-50 data-[state=active]:pr-bg-background data-[state=active]:pr-text-foreground data-[state=active]:pr-shadow-sm',
className,
)}
{...props}
/>
));
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;

const TabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Content
ref={ref}
className={cn(
'pr-mt-2 pr-ring-offset-background focus-visible:pr-outline-none focus-visible:pr-ring-2 focus-visible:pr-ring-ring focus-visible:pr-ring-offset-2',
className,
)}
{...props}
/>
));
TabsContent.displayName = TabsPrimitive.Content.displayName;

export { Tabs, TabsList, TabsTrigger, TabsContent };
9 changes: 9 additions & 0 deletions lib/platform-bible-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,12 @@ export { default as useEvent } from './hooks/use-event.hook';
export { default as useEventAsync } from './hooks/use-event-async.hook';
export { default as usePromise } from './hooks/use-promise.hook';
export type { UsePromiseOptions } from './hooks/use-promise.hook';
export { Input } from '@/components/shadcn-ui/input';
export * from '@/components/shadcn-ui/dropdown-menu';
export { Tabs, TabsList, TabsContent, TabsTrigger } from '@/components/shadcn-ui/tabs';
export {
VerticalTabs,
VerticalTabsList,
VerticalTabsContent,
VerticalTabsTrigger,
} from '@/components/shadcn-ui/tabs-vertical';
59 changes: 38 additions & 21 deletions lib/platform-bible-react/src/preview/app.component.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,46 @@
import { useState } from 'react';
import { ScriptureReference } from 'platform-bible-utils';
import { BookChapterControl, RefSelector } from '..';
import './app.component.css';

const defaultScrRef: ScriptureReference = {
bookNum: 1,
chapterNum: 1,
verseNum: 1,
};
import { Tabs, TabsContent, TabsList, TabsTrigger } from '..';
import { ThemeProvider } from './theme-provider.component';
import ThemeToggle from './theme-toggle.component';
import Basics from './components/basics.component';
import Compositions from './components/compositions.component';
import Examples from './components/examples.component';
import Playground from './components/playground.component';

function App() {
const [scrRef, setScrRef] = useState(defaultScrRef);

return (
<>
<h1>platform-bible-react Preview</h1>
<p>
Edit <code>lib\platform-bible-react\src\preview\app.component.tsx</code> and save to see
updates
</p>
<RefSelector scrRef={scrRef} handleSubmit={setScrRef} />
<div className="bcv-control-div">
<BookChapterControl scrRef={scrRef} handleSubmit={setScrRef} />
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
{/* pr-font-sans is added to mitigate issue introduced by scopedPreflightStyles */}
<div className="pr-twp pr-p-2 pr-font-sans">
<ThemeToggle className="pr-fixed pr-right-4 pr-top-4" />
<h1 className="pr-pb-4 pr-uppercase">platform-bible-react Preview</h1>
<p>
Edit <code>lib/platform-bible-react/src/preview/components/...</code> and save to see
updates
</p>
<Tabs defaultValue="Playground" className="pr-pt-4">
<TabsList>
<TabsTrigger value="Basics">Basic Components</TabsTrigger>
<TabsTrigger value="Compositions">Composition Components</TabsTrigger>
<TabsTrigger value="Examples">Example Layouts</TabsTrigger>
<TabsTrigger value="Playground">Playground</TabsTrigger>
</TabsList>

<TabsContent value="Basics">
<Basics />
</TabsContent>
<TabsContent value="Compositions">
<Compositions />
</TabsContent>
<TabsContent value="Examples">
<Examples />
</TabsContent>
<TabsContent value="Playground">
<Playground />
</TabsContent>
</Tabs>
</div>
</>
</ThemeProvider>
);
}

Expand Down
137 changes: 137 additions & 0 deletions lib/platform-bible-react/src/preview/components/basics.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { Button as ShadcnButton } from '@/components/shadcn-ui/button';
import {
Button,
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuTrigger,
Input,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
TextField,
VerticalTabs,
VerticalTabsContent,
VerticalTabsList,
VerticalTabsTrigger,
} from '../..';

function Basics() {
return (
<div>
<VerticalTabs>
<VerticalTabsList>
<VerticalTabsTrigger value="Button">Button</VerticalTabsTrigger>
<VerticalTabsTrigger value="Input">Input</VerticalTabsTrigger>
<VerticalTabsTrigger value="Dropdown Menu">Dropdown Menu</VerticalTabsTrigger>
<VerticalTabsTrigger value="Tabs">Tabs</VerticalTabsTrigger>
</VerticalTabsList>

<VerticalTabsContent value="Button">
<div>
{/* eslint-disable-next-line no-alert */}
<Button onClick={() => alert('Hello World')}>Wrapped Button</Button>
</div>
<div>
{/* eslint-disable-next-line no-alert */}
<ShadcnButton onClick={() => alert('Hello World')}>Plain Shadcn Button</ShadcnButton>
</div>
</VerticalTabsContent>

<VerticalTabsContent value="Input">
<table>
<tr>
<td>
Text Field <div className="pr-text-xs">(wrapped)</div>
</td>
{/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}
<td>
<TextField />
</td>
</tr>
<tr>
<td>
Shadcn Default Input
<div className="pr-text-xs">(shadcn-ui/input)</div>
</td>
{/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}
<td>
<Input />
</td>
</tr>
<tr>
<td>
Small Input
<div className="pr-text-xs">(from https://ui.jln.dev/ &rarr; popover)</div>
</td>
{/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}
<td>
<Input className="pr-full pr-file:border-0 pr-col-span-2 pr-flex pr-h-8 pr-rounded-md pr-border pr-border-input pr-bg-background pr-px-3 pr-py-2 pr-text-sm pr-ring-offset-background file:pr-bg-transparent file:pr-text-sm file:pr-font-medium placeholder:pr-text-muted-foreground focus-visible:pr-outline-none focus-visible:pr-ring-2 focus-visible:pr-ring-ring focus-visible:pr-ring-offset-2 disabled:pr-cursor-not-allowed disabled:pr-opacity-50" />
</td>
</tr>
<tr>
<td>
Small Input <div className="pr-text-xs">(from BCV control)</div>
</td>
{/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}
<td>
<Input className="pr-box-border pr-gap-2.5 pr-rounded-lg pr-border pr-border-solid pr-border-black pr-bg-white pr-py-2 pr-pl-4 pr-pr-3 pr-font-medium pr-text-slate-900 pr-shadow-none pr-outline-none" />
</td>
</tr>
</table>
</VerticalTabsContent>

<VerticalTabsContent value="Dropdown Menu">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<ShadcnButton>Open</ShadcnButton>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>DropdownMenuLabel</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>
<span>DropdownMenuItem</span>
<DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</VerticalTabsContent>

<VerticalTabsContent value="Tabs">
<Tabs>
<TabsList>
<TabsTrigger value="1">Tab 1</TabsTrigger>
<TabsTrigger value="2">Tab 2</TabsTrigger>
<TabsTrigger value="3">Tab 3 - no linked content</TabsTrigger>
</TabsList>
<TabsContent value="1">Tab 1 Content</TabsContent>
<TabsContent value="2">Tab 2 Content</TabsContent>
{/* intentionally left out 3 to see the effect */}
</Tabs>
<hr className="pr-my-4" />
<VerticalTabs defaultValue="2">
<VerticalTabsList>
<VerticalTabsTrigger value="1">Tab 1</VerticalTabsTrigger>
<VerticalTabsTrigger value="2">Tab 2</VerticalTabsTrigger>
<VerticalTabsTrigger value="3">Tab 3</VerticalTabsTrigger>
<VerticalTabsTrigger value="4">Tab 4</VerticalTabsTrigger>
</VerticalTabsList>
<VerticalTabsContent value="1">Tab 1 Content</VerticalTabsContent>
<VerticalTabsContent value="2">Tab 2 Content</VerticalTabsContent>
<VerticalTabsContent value="3">Tab 3 Content</VerticalTabsContent>
<VerticalTabsContent value="4">Tab 4 Content</VerticalTabsContent>
</VerticalTabs>
</VerticalTabsContent>
</VerticalTabs>
</div>
);
}

export default Basics;
Loading

0 comments on commit 46b4853

Please sign in to comment.