Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PLAY-1586] Timeline Sub Sub Components #3801

Merged
merged 18 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 59 additions & 23 deletions playbook/app/pb_kits/playbook/pb_timeline/_item.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import React from 'react'
import classnames from 'classnames'

import { buildCss, buildHtmlProps } from '../utilities/props'
import { globalProps, GlobalProps } from "../utilities/globalProps";
import { globalProps, GlobalProps } from "../utilities/globalProps"

import DateStacked from '../pb_date_stacked/_date_stacked'
import IconCircle from '../pb_icon_circle/_icon_circle'

import TimelineLabel from './subcomponents/Label'
import TimelineStep from './subcomponents/Step'
import TimelineDetail from './subcomponents/Detail'

type ItemProps = {
className?: string,
children?: React.ReactNode[] | React.ReactNode,
Expand All @@ -17,6 +20,13 @@ type ItemProps = {
lineStyle?: 'solid' | 'dotted',
} & GlobalProps

function isElementOfType<P>(
element: React.ReactNode,
component: React.ComponentType<P>
): element is React.ReactElement<P> {
return React.isValidElement<P>(element) && element.type === component
}

const TimelineItem = ({
className,
children,
Expand All @@ -31,31 +41,57 @@ const TimelineItem = ({

const htmlProps = buildHtmlProps(htmlOptions)

const childrenArray = React.Children.toArray(children)

const labelChild = childrenArray.find(
(child): child is React.ReactElement => isElementOfType(child, TimelineLabel)
)

const stepChild = childrenArray.find(
(child): child is React.ReactElement => isElementOfType(child, TimelineStep)
)

const detailChild = childrenArray.find(
(child): child is React.ReactElement => isElementOfType(child, TimelineDetail)
)

const otherChildren = childrenArray.filter(
(child) =>
!isElementOfType(child, TimelineLabel) &&
!isElementOfType(child, TimelineStep) &&
!isElementOfType(child, TimelineDetail)
)

return (
<div
<div
{...htmlProps}
className={classnames(timelineItemCss, globalProps(props), className)}
>
<div className="pb_timeline_item_left_block">
{date &&
<DateStacked
align="center"
date={date}
size="sm"
/>
}
</div>
<div className="pb_timeline_item_step">
<IconCircle
icon={icon}
size="xs"
variant={iconColor}
/>
<div className="pb_timeline_item_connector" />
</div>
<div className="pb_timeline_item_right_block">
{children}
</div>
{labelChild || (
<div className="pb_timeline_item_left_block">
{date && (
<DateStacked
align="center"
date={date}
size="sm"
/>
)}
</div>
)}
{stepChild || (
<div className="pb_timeline_item_step">
<IconCircle icon={icon}
size="xs"
variant={iconColor}
/>
<div className="pb_timeline_item_connector" />
</div>
)}
{detailChild || (
<div className="pb_timeline_item_right_block">
{ otherChildren }
</div>
)}
</div>
)
}
Expand Down
8 changes: 8 additions & 0 deletions playbook/app/pb_kits/playbook/pb_timeline/_timeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../uti
import { GlobalProps, globalProps } from '../utilities/globalProps'

import TimelineItem from './_item'
import {
TimelineStep,
TimelineLabel,
TimelineDetail,
} from './subcomponents'

type TimelineProps = {
aria?: { [key: string]: string },
Expand Down Expand Up @@ -47,5 +52,8 @@ const Timeline = ({
}

Timeline.Item = TimelineItem
Timeline.Step = TimelineStep
Timeline.Label = TimelineLabel
Timeline.Detail = TimelineDetail

export default Timeline
3 changes: 3 additions & 0 deletions playbook/app/pb_kits/playbook/pb_timeline/detail.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<%= pb_content_tag do %>
<%= content.presence %>
<% end %>
11 changes: 11 additions & 0 deletions playbook/app/pb_kits/playbook/pb_timeline/detail.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

module Playbook
module PbTimeline
class Detail < Playbook::KitBase
def classname
generate_classname("pb_timeline_item_right_block")
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<%= pb_rails("timeline", props: {orientation: "horizontal", show_date: true}) do %>
<%= pb_rails("timeline/item", props: { line_style: "solid"}) do |item| %>

<% item.label do %>
<%= pb_rails("timeline/label") do %>
<%= pb_rails("title", props: { text: "Any Kit Here", size: 2 }) %>
<% end %>
<% end %>

<% item.step do %>
<%= pb_rails("timeline/step", props: { icon: 'check', icon_color: 'teal' }) %>
<% end %>

<% item.detail do %>
<%= pb_rails("title_detail", props: {
title: "Jackson Heights",
detail: "37-27 74th Street"
}) %>
<% end %>
<% end %>
<%= pb_rails("timeline/item", props: { line_style: "dotted"}) do |item| %>

<% item.step do %>
<%= pb_rails("timeline/step") do %>
<%= pb_rails("pill", props: { text: "Any Kit" , variant: "success" }) %>
<% end %>
<% end %>

<% item.detail do %>
<%= pb_rails("title_detail", props: {
title: "Greenpoint",
detail: "81 Gate St Brooklyn"
}) %>
<% end %>
<% end %>

<%= pb_rails("timeline/item", props: {icon: "map-marker-alt", icon_color: "purple", date: Date.today+1 }) do |item| %>
<%= pb_rails("title_detail", props: {
title: "Society Hill",
detail: "72 E St Astoria"
}) %>
<% end %>
<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react'

import Timeline from '../_timeline'
import Title from '../../pb_title/_title'
import Pill from '../../pb_pill/_pill'

import TitleDetail from '../../pb_title_detail/_title_detail'

const TimelineWithChildren = (props) => (
<div>
<Timeline orientation="horizontal"
showDate
{...props}
>
<Timeline.Item lineStyle="solid"
{...props}
>
<Timeline.Label>
<Title size={2}
text='Any Kit Here'
/>
</Timeline.Label>
<Timeline.Step icon="user"
iconColor="royal"
/>
<Timeline.Detail>
<TitleDetail detail="37-27 74th Street"
title="Jackson Heights"
{...props}
/>
</Timeline.Detail>
</Timeline.Item>

<Timeline.Item lineStyle="dotted"
{...props}
>
<Timeline.Step>
<Pill text="Any Kit"
variant="success"
/>
</Timeline.Step>
<Timeline.Detail>
<TitleDetail detail="81 Gate St Brooklyn"
title="Greenpoint"
{...props}
/>
</Timeline.Detail>
</Timeline.Item>

<Timeline.Item lineStyle="solid"
{...props}
>
<Timeline.Label date={new Date(new Date().setDate(new Date().getDate() + 1))} />
<Timeline.Step icon="map-marker-alt"
iconColor="purple"
/>
<Timeline.Detail>
<TitleDetail detail="72 E St Astoria"
title="Society Hill"
{...props}
/>
</Timeline.Detail>
</Timeline.Item>
</Timeline>
</div>
)

export default TimelineWithChildren
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Any kit can be used inside of our compound components of label, step, or detail. Expand the code snippet below to see how to use these children elements.

Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ examples:
- timeline_default: Default
- timeline_vertical: Vertical
- timeline_with_date: With Date
- timeline_with_children: With Children


react:
- timeline_default: Default
- timeline_vertical: Vertical
- timeline_with_date: With Date

- timeline_with_children: With Children
1 change: 1 addition & 0 deletions playbook/app/pb_kits/playbook/pb_timeline/docs/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as TimelineDefault } from './_timeline_default.jsx'
export { default as TimelineVertical } from './_timeline_vertical.jsx'
export { default as TimelineWithDate } from './_timeline_with_date.jsx'
export { default as TimelineWithChildren } from './_timeline_with_children.jsx'
38 changes: 17 additions & 21 deletions playbook/app/pb_kits/playbook/pb_timeline/item.html.erb
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
<%= pb_content_tag do %>
<% if label %>
<%= label %>
<% else %>
<%= pb_rails("timeline/label", props: { date: date }) %>
<% end %>

<div class="pb_timeline_item_left_block">
<% if object.date.present? %>
<%= pb_rails("date_stacked", props: {
date: object.date,
size: "sm",
align: "center"
}) %>
<% end %>
</div>

<div class="pb_timeline_item_step">
<%= pb_rails("icon_circle", props: {
icon: object.icon,
variant: object.icon_color,
size: "xs"
}) %>
<div class="pb_timeline_item_connector"></div>
</div>
<% if step %>
<%= step %>
<% else %>
<%= pb_rails("timeline/step", props: { icon: icon, icon_color: icon_color }) %>
<% end %>

<div class="pb_timeline_item_right_block">
<%= content.presence %>
</div>
<% if detail%>
<%= detail%>
<% else %>
<%= pb_rails("timeline/detail") do %>
<%= content %>
<% end %>
<% end %>
<% end %>
4 changes: 4 additions & 0 deletions playbook/app/pb_kits/playbook/pb_timeline/item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ class Item < Playbook::KitBase
values: %w[solid dotted],
default: "solid"

renders_one :label
renders_one :step
renders_one :detail

def classname
generate_classname("pb_timeline_item_kit", line_style)
end
Expand Down
12 changes: 12 additions & 0 deletions playbook/app/pb_kits/playbook/pb_timeline/label.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<%= pb_content_tag do %>
<% if object.date.present? %>
<%= pb_rails("date_stacked", props: {
date: object.date,
size: "sm",
align: "center"
}) %>
<% else %>
<%= content.presence %>
<% end %>
<% end %>

13 changes: 13 additions & 0 deletions playbook/app/pb_kits/playbook/pb_timeline/label.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module Playbook
module PbTimeline
class Label < Playbook::KitBase
prop :date

def classname
generate_classname("pb_timeline_item_left_block")
end
end
end
end
14 changes: 14 additions & 0 deletions playbook/app/pb_kits/playbook/pb_timeline/step.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<%= pb_content_tag do %>
<% if object.icon.present? %>
<%= pb_rails("icon_circle", props: {
icon: object.icon,
variant: object.icon_color,
size: "xs"
}) %>
<% else %>
<%= content.presence %>
<% end %>
<div class="pb_timeline_item_connector"></div>
<% end %>


16 changes: 16 additions & 0 deletions playbook/app/pb_kits/playbook/pb_timeline/step.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

module Playbook
module PbTimeline
class Step < Playbook::KitBase
prop :icon, type: Playbook::Props::String
prop :icon_color, type: Playbook::Props::Enum,
values: %w[default royal blue purple teal red yellow green],
default: "default"

def classname
generate_classname("pb_timeline_item_step")
end
end
end
end
Loading
Loading