Skip to content

Commit

Permalink
feat: [XD-56]: Initial breadcrumb component docs and change from Brea…
Browse files Browse the repository at this point in the history
…dcrumbPART to Breadcrumb.PART
  • Loading branch information
knagurski committed Jan 10, 2025
1 parent d504733 commit b93ff05
Show file tree
Hide file tree
Showing 23 changed files with 365 additions and 132 deletions.
20 changes: 20 additions & 0 deletions apps/design-system/src/components/docs-page/code-block.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { FC } from 'react'

import { MarkdownViewer } from '@harnessio/ui/components'

export interface CodeBlockProps {
code: string
language?: string
}

const CodeBlock: FC<CodeBlockProps> = ({ code, language = 'typescript tsx' }) => (
<MarkdownViewer
source={`
\`\`\`${language}
${code}
\`\`\`
`}
/>
)

export default CodeBlock
8 changes: 7 additions & 1 deletion apps/design-system/src/components/docs-page/docs-page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import CodeBlock from './code-block.tsx'
import ComponentExample from './component-example'
import Example from './example'
import PropsTable from './props-table.tsx'
import Root from './root'
import Section from './section'
import SubSection from './sub-section.tsx'
import Summary from './summary'

export const DocsPage = {
Root,
Summary,
Section,
SubSection,
Example,
ComponentExample
ComponentExample,
CodeBlock,
PropsTable
}
37 changes: 37 additions & 0 deletions apps/design-system/src/components/docs-page/props-table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { FC } from 'react'

import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@harnessio/ui/components'

interface PropDescription {
name: string
required?: boolean
defaultValue?: string
description?: string
}

export interface PropsTableProps {
props: PropDescription[]
}

const PropsTable: FC<PropsTableProps> = ({ props }) => (
<Table>
<TableHeader>
<TableRow>
<TableHead>Prop</TableHead>
<TableHead>Required</TableHead>
<TableHead>Default</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{props.map(({ name, required, defaultValue, description }) => (
<TableRow key={name}>
<TableCell title={description}>{name}</TableCell>
<TableCell>{required ? 'yup' : 'nope'}</TableCell>
<TableCell>{defaultValue}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)

export default PropsTable
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.section {
display: flex;
flex-direction: column;
gap: 1rem;
}
4 changes: 3 additions & 1 deletion apps/design-system/src/components/docs-page/section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { FC, PropsWithChildren, ReactNode } from 'react'

import { Text } from '@harnessio/ui/components'

import css from './section.module.css'

export interface SectionProps extends PropsWithChildren {
title: string
description?: ReactNode
}

const Section: FC<SectionProps> = ({ title, description, children }) => (
<section>
<section className={css.section}>
<Text as="h3" size={5}>
{title}
</Text>
Expand Down
22 changes: 22 additions & 0 deletions apps/design-system/src/components/docs-page/sub-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { FC, PropsWithChildren, ReactNode } from 'react'

import { Text } from '@harnessio/ui/components'

import css from './section.module.css'

export interface SubSectionProps extends PropsWithChildren {
title: string
description?: ReactNode
}

const SubSection: FC<SubSectionProps> = ({ title, description, children }) => (
<section className={css.section}>
<Text as="h4" size={4}>
{title}
</Text>
{description}
{children}
</section>
)

export default SubSection
37 changes: 14 additions & 23 deletions apps/design-system/src/pages/view-preview/root-view-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,7 @@ import { Outlet, Route, Routes } from 'react-router-dom'

import { noop, useThemeStore, useTranslationsStore } from '@utils/viewUtils'

import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbSeparator,
Navbar,
NavbarItemType,
Topbar
} from '@harnessio/ui/components'
import { Breadcrumb, Navbar, NavbarItemType, Topbar } from '@harnessio/ui/components'
import { SandboxLayout } from '@harnessio/ui/views'

const RootViewWrapper: FC<PropsWithChildren<{ asChild?: boolean }>> = ({ children, asChild = false }) => {
Expand Down Expand Up @@ -62,19 +53,19 @@ const RootViewWrapper: FC<PropsWithChildren<{ asChild?: boolean }>> = ({ childre
<div className="bg-background-1 sticky top-0 z-40">
<Topbar.Root>
<Topbar.Left>
<Breadcrumb className="select-none">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="#">Lorem</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="#">Ipsum</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>Dolor</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
<Breadcrumb.Root className="select-none">
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Lorem</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Ipsum</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>Dolor</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb.Root>
</Topbar.Left>
</Topbar.Root>
</div>
Expand Down
170 changes: 170 additions & 0 deletions apps/design-system/src/subjects/components/breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import { DocsPage } from '@components/docs-page/docs-page'

const BreadcrumbComponent = () => (
<DocsPage.Root>
<DocsPage.Summary title="Breadcrumb">
<p>
A breadcrumbs is a list of links that help visualize the location of a page within the hierarchical structure of
a site, it allows navigation up to any of the ancestors.
</p>
</DocsPage.Summary>

<DocsPage.ComponentExample
code={`
<Breadcrumb.Root className="select-none">
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Lorem</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Ellipsis />
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Ipsum</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Page>Dolor</Breadcrumb.Page>
</Breadcrumb.List>
</Breadcrumb.Root>
`}
/>

<DocsPage.Section title="Anatomy">
<p>All parts of the breadcrumb can be imported and composed as required.</p>

<DocsPage.CodeBlock
code={`<Breadcrumb.Root className="select-none">
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Lorem</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Ellipsis />
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Ipsum</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Page>Dolor</Breadcrumb.Page>
</Breadcrumb.List>
</Breadcrumb.Root>`}
/>
</DocsPage.Section>

<DocsPage.Section title="API Reference">
<DocsPage.SubSection title="Root">
<p>The `Root` component wraps the breadcrumb with a `nav` tag for use as page navigation.</p>
<DocsPage.PropsTable
props={[
{ name: 'children', description: 'You can pass in your `Breadcrumb.List` as a child', required: true },
{ name: 'className', required: false }
]}
/>
</DocsPage.SubSection>

<DocsPage.SubSection title="List">
<p>The `List` component adds styling to ensure the breadcrumb is displayed inline as a list.</p>
<DocsPage.CodeBlock
code={`<Breadcrumb.List>
{/* Pass Breadcrumb.Item, Breadcrumb.Separator and Breadcrumb.Page elements as children */}
</Breadcrumb.List>`}
/>
<DocsPage.PropsTable
props={[
{ name: 'children', description: 'You can pass in your `Breadcrumb.Item`s as children', required: true },
{ name: 'className', required: false }
]}
/>
</DocsPage.SubSection>

<DocsPage.SubSection title="Item">
<p>The `Item` component displays its contents as a node within the breadcrumb.</p>
<DocsPage.CodeBlock
code={`<Breadcrumb.Item>
{/* Pass text, JSX elements or Breadcrumb.Link elements as children */}
</Breadcrumb.Item>`}
/>
<DocsPage.PropsTable
props={[
{ name: 'children', description: 'Content to display', required: true },
{ name: 'className', required: false }
]}
/>
</DocsPage.SubSection>

<DocsPage.SubSection title="Link">
<p>
The `Link` component can be passed as a child to an `Item` component to display a clickable breadcrumb item.
</p>
<DocsPage.CodeBlock
code={`<Breadcrumb.Item>
<Breadcrumb.Link href="#">
Lorem
</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Item>
<Breadcrumb.Link asChild>
<button onClick={handleLinkClick}>Click me</button>
</Breadcrumb.Link>
</Breadcrumb.Item>`}
/>
<DocsPage.PropsTable
props={[
{ name: 'href', description: 'Where to link to' },
{ name: 'children', description: 'Content to display in the link', required: true },
{
name: 'asChild',
description: 'Render using the passed child element instead of as an anchor element',
defaultValue: 'false'
},
{ name: 'className' }
]}
/>
</DocsPage.SubSection>

<DocsPage.SubSection title="Page">
<p>
The `Page` component displays its contents as a node within the breadcrumb with styling to denote that it is
the current page.
</p>
<DocsPage.CodeBlock code={`<Breadcrumb.Page>Lorem ipsum</Breadcrumb.Page>`} />
<DocsPage.PropsTable
props={[
{ name: 'children', description: 'Content to display', required: true },
{ name: 'className', required: false }
]}
/>
</DocsPage.SubSection>

<DocsPage.SubSection title="Separator">
<p>The `Separator` component displays a separator between the items of the breadcrumb.</p>
<DocsPage.CodeBlock
code={`<Breadcrumb.Separator />
<Breadcrumb.Item>
Lorem ipsum
</Breadcrumb.Item>
<Breadcrumb.Separator>
&gt;
</Breadcrumb.Separator>`}
/>
<DocsPage.PropsTable
props={[
{ name: 'children', description: 'Content to display', defaultValue: '/' },
{ name: 'className', required: false }
]}
/>
</DocsPage.SubSection>

<DocsPage.SubSection title="Ellipsis">
<p>The `Ellipsis` component displays an ellipsis for use when there are too many items to display.</p>
<DocsPage.CodeBlock code={`<Breadcrumb.Ellipsis />`} />
<DocsPage.PropsTable props={[{ name: 'className', required: false }]} />
</DocsPage.SubSection>
</DocsPage.Section>
</DocsPage.Root>
)

export default BreadcrumbComponent
8 changes: 5 additions & 3 deletions apps/design-system/src/subjects/components/componentPages.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { RouteProps } from 'react-router-dom'

import AlertComponent from '@subjects/components/alert'
import BadgeComponent from '@subjects/components/badge'
import ButtonComponent from '@subjects/components/button'
import AlertComponent from './alert'
import BadgeComponent from './badge'
import BreadcrumbComponent from './breadcrumb'
import ButtonComponent from './button'

interface ComponentPage {
name: string
Expand All @@ -13,5 +14,6 @@ interface ComponentPage {
export const componentPages: ComponentPage[] = [
{ name: 'Alert', path: 'alert', Component: AlertComponent },
{ name: 'Badge', path: 'badge', Component: BadgeComponent },
{ name: 'Breadcrumb', path: 'breadcrumb', Component: BreadcrumbComponent },
{ name: 'Button', path: 'button', Component: ButtonComponent }
]
Loading

0 comments on commit b93ff05

Please sign in to comment.