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-1581] Height, minHeight, maxHeight for Card, Flex, FlexItem, & Dialog #3749

Merged
merged 12 commits into from
Oct 22, 2024
6 changes: 5 additions & 1 deletion playbook/app/pb_kits/playbook/pb_card/_card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { get } from 'lodash'
import classnames from 'classnames'

import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
import { GlobalProps, globalProps } from '../utilities/globalProps'
import { GlobalProps, globalProps, globalInlineProps } from '../utilities/globalProps'
import type { ProductColors, CategoryColors, BackgroundColors } from '../types/colors'

import Icon from '../pb_icon/_icon'
Expand Down Expand Up @@ -49,6 +49,7 @@ type CardBodyProps = {
padding?: string,
} & GlobalProps


// Header component
const Header = (props: CardHeaderProps) => {
const { children, className, headerColor = 'category_1', headerColorStriped = false } = props
Expand Down Expand Up @@ -107,6 +108,7 @@ const Card = (props: CardPropTypes): React.ReactElement => {

// coerce to array
const cardChildren = React.Children.toArray(children)
const inlineStyles = globalInlineProps(props);

const subComponentTags = (tagName: string) => {
return cardChildren.filter((c: string) => (
Expand Down Expand Up @@ -135,6 +137,7 @@ const Card = (props: CardPropTypes): React.ReactElement => {
{...dataProps}
{...htmlProps}
className={classnames(cardCss, globalProps(props), className)}
style={inlineStyles}
>
{subComponentTags('Header')}
{
Expand Down Expand Up @@ -163,6 +166,7 @@ const Card = (props: CardPropTypes): React.ReactElement => {
{...dataProps}
{...htmlProps}
className={classnames(cardCss, globalProps(props), className)}
style={inlineStyles}
>
{subComponentTags('Header')}
{nonHeaderChildren}
Expand Down
6 changes: 5 additions & 1 deletion playbook/app/pb_kits/playbook/pb_dialog/_dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import classnames from "classnames";
import Modal from "react-modal";

import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from "../utilities/props";
import { globalProps } from "../utilities/globalProps";
import { globalProps, globalInlineProps } from "../utilities/globalProps";

import Body from "../pb_body/_body";
import Button from "../pb_button/_button";
Expand Down Expand Up @@ -91,6 +91,8 @@ const Dialog = (props: DialogProps): React.ReactElement => {
beforeClose: "pb_dialog_overlay_before_close",
};

const inlineStyles = globalInlineProps(props);

const classes = classnames(
buildCss("pb_dialog_wrapper"),
globalProps(props),
Expand Down Expand Up @@ -184,6 +186,7 @@ const Dialog = (props: DialogProps): React.ReactElement => {
overlayClassName={overlayClassNames}
portalClassName={portalClassName}
shouldCloseOnOverlayClick={shouldCloseOnOverlayClick && !loading}
style={{ content: inlineStyles }}
>
<>
{title && !status ? <Dialog.Header>{title}</Dialog.Header> : null}
Expand All @@ -192,6 +195,7 @@ const Dialog = (props: DialogProps): React.ReactElement => {
<Dialog.Body
className="dialog_status_text_align"
padding="md"

>
<Flex align="center"
orientation="column"
Expand Down
4 changes: 3 additions & 1 deletion playbook/app/pb_kits/playbook/pb_flex/_flex.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import classnames from 'classnames'
import { buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
import { GlobalProps, globalProps } from '../utilities/globalProps'
import { GlobalProps, globalProps, globalInlineProps } from '../utilities/globalProps'
import { GenericObject, Sizes } from '../types'

type FlexProps = {
Expand Down Expand Up @@ -61,6 +61,7 @@ const Flex = (props: FlexProps): React.ReactElement => {
const alignSelfClass = alignSelf !== 'none' ? `align_self_${alignSelf}` : ''
const dataProps = buildDataProps(data)
const htmlProps = buildHtmlProps(htmlOptions)
const inlineStyles = globalInlineProps(props)


return (
Expand All @@ -83,6 +84,7 @@ const Flex = (props: FlexProps): React.ReactElement => {
globalProps(props),
className
)}
style={inlineStyles}
{...dataProps}
{...htmlProps}
>
Expand Down
10 changes: 8 additions & 2 deletions playbook/app/pb_kits/playbook/pb_flex/_flex_item.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import classnames from 'classnames'
import { buildCss, buildHtmlProps } from '../utilities/props'
import { globalProps, GlobalProps } from '../utilities/globalProps'
import { globalProps, GlobalProps, globalInlineProps} from '../utilities/globalProps'
type FlexItemPropTypes = {
children: React.ReactNode[] | React.ReactNode,
fixedSize?: string,
Expand Down Expand Up @@ -35,14 +35,20 @@ const FlexItem = (props: FlexItemPropTypes): React.ReactElement => {
const fixedStyle =
fixedSize !== undefined ? { flexBasis: `${fixedSize}` } : null
const orderClass = order !== 'none' ? `order_${order}` : null
const inlineStyles = globalInlineProps(props)
const combinedStyles = {
...fixedStyle,
...inlineStyles
}

const htmlProps = buildHtmlProps(htmlOptions)


return (
<div
{...htmlProps}
className={classnames(buildCss('pb_flex_item_kit', growClass, shrinkClass, flexClass, displayFlexClass), orderClass, alignSelfClass, globalProps(props), className)}
style={fixedStyle}
style={combinedStyles}
>
{children}
</div>
Expand Down
9 changes: 3 additions & 6 deletions playbook/app/pb_kits/playbook/pb_flex/flex_item.html.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
<%= content_tag(:div,
id: object.id,
data: object.data,
class: object.classname,
style: object.style_value,
jasperfurniss marked this conversation as resolved.
Show resolved Hide resolved
**combined_html_options) do %>
<%= pb_content_tag(:div,
style: object.inline_styles
) do %>
<%= content.presence %>
<% end %>
9 changes: 7 additions & 2 deletions playbook/app/pb_kits/playbook/pb_flex/flex_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@ def classname
generate_classname("pb_flex_item_kit", fixed_size_class, grow_class, shrink_class, display_flex_class) + align_self_class
end

def style_value
"flex-basis: #{fixed_size};" if fixed_size.present?
def inline_styles
styles = []
styles << "flex-basis: #{fixed_size};" if fixed_size.present?
styles << "height: #{height};" if height.present?
jasperfurniss marked this conversation as resolved.
Show resolved Hide resolved
jasperfurniss marked this conversation as resolved.
Show resolved Hide resolved
styles << "min-height: #{min_height};" if min_height.present?
styles << "max-height: #{max_height};" if max_height.present?
styles.join(" ")
end

private
Expand Down
2 changes: 1 addition & 1 deletion playbook/app/pb_kits/playbook/pb_popover/_popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import classnames from "classnames";
import { globalProps, GlobalProps } from "../utilities/globalProps";
import { uniqueId } from 'lodash';

type ModifiedGlobalProps = Omit<GlobalProps, 'minWidth'>
type ModifiedGlobalProps = Omit<GlobalProps, 'minWidth' | 'maxHeight' | 'minHeight'>

type PbPopoverProps = {
aria?: { [key: string]: string };
Expand Down
3 changes: 3 additions & 0 deletions playbook/app/pb_kits/playbook/utilities/globalPropNames.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export default [
"minHeight",
"maxHeight",
"height",
"left",
"bottom",
"right",
Expand Down
41 changes: 39 additions & 2 deletions playbook/app/pb_kits/playbook/utilities/globalProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,24 @@ type ZIndex = {
zIndex?: ZIndexType,
} | ZIndexResponsiveType

type Height = {
height?: string
}

type MaxHeight = {
maxHeight?: string
}

type MinHeight = {
minHeight?: string
}

// keep this as the last type definition
export type GlobalProps = AlignContent & AlignItems & AlignSelf &
BorderRadius & Cursor & Dark & Display & DisplaySizes & Flex & FlexDirection &
FlexGrow & FlexShrink & FlexWrap & JustifyContent & JustifySelf &
LineHeight & Margin & MinWidth & MaxWidth & NumberSpacing & Order & Overflow & Padding &
Position & Shadow & TextAlign & Truncate & VerticalAlign & ZIndex & { hover?: string } & Top & Right & Bottom & Left;
Position & Shadow & TextAlign & Truncate & VerticalAlign & ZIndex & { hover?: string } & Top & Right & Bottom & Left & Height & MaxHeight & MinHeight;

const getResponsivePropClasses = (prop: {[key: string]: string}, classPrefix: string) => {
const keys: string[] = Object.keys(prop)
Expand Down Expand Up @@ -498,7 +510,22 @@ const PROP_CATEGORIES: {[key:string]: (props: {[key: string]: any}) => string} =
} else {
return verticalAlign ? `vertical_align_${verticalAlign} ` : ''
}
}
},

}

const PROP_INLINE_CATEGORIES: {[key:string]: (props: {[key: string]: any}) => {[key: string]: any}} = {
heightProps: ({ height }: Height) => {
return height ? { height } : {};
},

maxHeightProps: ({ maxHeight }: MaxHeight) => {
return maxHeight ? { maxHeight } : {};
},

minHeightProps: ({ minHeight }: MinHeight) => {
return minHeight ? { minHeight } : {};
},
}

type DefaultProps = {[key: string]: string} | Record<string, unknown>
Expand All @@ -510,6 +537,16 @@ export const globalProps = (props: GlobalProps, defaultProps: DefaultProps = {})
}).filter((value) => value?.length > 0).join(" ")
}

// New function for inline styles
export const globalInlineProps = (props: GlobalProps): React.CSSProperties => {
const styles = Object.keys(PROP_INLINE_CATEGORIES).reduce((acc, key) => {
const result = PROP_INLINE_CATEGORIES[key](props);
return { ...acc, ...(typeof result === 'object' ? result : {}) }; // Ensure result is an object before spreading
}, {});

return styles; // Return the styles object directly
}


export const deprecatedProps = (): void => {
// if (process.env.NODE_ENV === 'development') {
Expand Down
17 changes: 17 additions & 0 deletions playbook/lib/playbook/kit_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ class KitBase < ViewComponent::Base
prop :aria, type: Playbook::Props::HashProp, default: {}
prop :html_options, type: Playbook::Props::HashProp, default: {}
prop :children, type: Playbook::Props::Proc
prop :style, type: Playbook::Props::HashProp, default: {}
prop :height
prop :min_height
prop :max_height

def object
self
Expand All @@ -82,6 +86,14 @@ def combined_html_options
default_html_options.merge(html_options.deep_merge(data_attributes))
end

def global_inline_props
{
height: height,
min_height: min_height,
max_height: max_height,
}.compact
end

# rubocop:disable Layout/CommentIndentation
# pb_content_tag information (potentially to be abstracted into its own dev doc in the future)
# The pb_content_tag generates HTML content tags for rails kits with flexible options.
Expand Down Expand Up @@ -118,6 +130,7 @@ def default_options
data: data,
class: classname,
aria: aria,
style: inline_styles,
}
end

Expand All @@ -131,5 +144,9 @@ def data_attributes
aria: aria,
}.transform_keys { |key| key.to_s.tr("_", "-").to_sym }
end

def inline_styles
global_inline_props.map { |key, value| "#{key.to_s.gsub('_', '-')}: #{value};" }.join(" ")
end
end
end
Loading