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 13 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
12 changes: 12 additions & 0 deletions playbook/app/pb_kits/playbook/pb_timeline/date_area.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/date_area.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

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

def classname
generate_classname("pb_timeline_item_left_block")
end
end
end
end
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_area.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

module Playbook
module PbTimeline
class DetailArea < 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.date_area do %>
nidaqg marked this conversation as resolved.
Show resolved Hide resolved
<%= pb_rails("timeline/date_area") do %>
<%= pb_rails("title", props: { text: "Any Kit Here", size: 2 }) %>
<% end %>
<% end %>

<% item.node_area do %>
<%= pb_rails("timeline/node_area", props: { icon: 'check', icon_color: 'teal' }) %>
markdoeswork marked this conversation as resolved.
Show resolved Hide resolved
<% end %>

<% item.detail_area 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.node_area do %>
<%= pb_rails("timeline/node_area") do %>
<%= pb_rails("pill", props: { text: "Any Kit" , variant: "success" }) %>
<% end %>
<% end %>

<% item.detail_area 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,4 @@
You can use whatever kit you want for the date area of the timeline item, the node area, and the content area at the bottom or left.

Checkout the code in this example to see the children kits in action.

markdoeswork marked this conversation as resolved.
Show resolved Hide resolved
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 date_area %>
<%= date_area %>
<% else %>
<%= pb_rails("timeline/date_area", 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 node_area %>
<%= node_area %>
<% else %>
<%= pb_rails("timeline/node_area", props: { icon: icon, icon_color: icon_color }) %>
<% end %>

<div class="pb_timeline_item_right_block">
<%= content.presence %>
</div>
<% if detail_area %>
<%= detail_area %>
<% else %>
<%= pb_rails("timeline/detail_area") 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 :date_area
renders_one :node_area
renders_one :detail_area

def classname
generate_classname("pb_timeline_item_kit", line_style)
end
Expand Down
14 changes: 14 additions & 0 deletions playbook/app/pb_kits/playbook/pb_timeline/node_area.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/node_area.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

module Playbook
module PbTimeline
class NodeArea < 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