Skip to content
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React, { HTMLAttributes } from 'react'
import styled from 'styled-components'
import { useTheme } from '@redis-ui/styles'
import { Spacer } from '../spacer'

interface RiEmptyPromptProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
body?: React.ReactNode
title?: React.ReactNode
icon?: React.ReactNode
}

const StyledEmptyPrompt = styled.div`
max-width: 36em;
text-align: center;
padding: 24px;
margin: auto;
`

const RiEmptyPrompt = ({ body, title, icon, ...rest }: RiEmptyPromptProps) => {
const theme = useTheme()

return (<StyledEmptyPrompt {...rest}>
{icon}
{title && (
<>
<Spacer size={theme.core.space.space100} />
{title}
</>
)}
{body && (
<>
<Spacer size={theme.core.space.space100} />
{body}
</>
)}
</StyledEmptyPrompt>
)
}


export default RiEmptyPrompt
3 changes: 2 additions & 1 deletion redisinsight/ui/src/components/base/layout/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import LoadingContent from './loading-content/LoadingContent'
import ResizableContainer from './resize/container/ResizableContainer'
import ResizablePanel from './resize/panel/ResizablePanel'
import ResizablePanelHandle from './resize/handle/ResizablePanelHandle'

import RiEmptyPrompt from './empty-prompt/RiEmptyPrompt'

export * from './card'
export * from './horizontal-spacer'
Expand All @@ -14,4 +14,5 @@ export {
ResizablePanel,
ResizableContainer,
ResizablePanelHandle,
RiEmptyPrompt,
}
30 changes: 28 additions & 2 deletions redisinsight/ui/src/components/base/layout/spacer/spacer.styles.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { HTMLAttributes, ReactNode } from 'react'
import styled from 'styled-components'
import { CommonProps } from 'uiSrc/components/base/theme/types'
import { theme } from 'uiSrc/components/base/theme'

export const SpacerSizes = ['xs', 's', 'm', 'l', 'xl', 'xxl'] as const
export type SpacerSize = (typeof SpacerSizes)[number]

// Extract only the spaceXXX keys from the theme
export type ThemeSpacingKey = Extract<keyof typeof theme.semantic.core.space, `space${string}`>
// Allow direct theme spacing values
export type ThemeSpacingValue = typeof theme.semantic.core.space[ThemeSpacingKey]

export type SpacerProps = CommonProps &
HTMLAttributes<HTMLDivElement> & {
children?: ReactNode
size?: SpacerSize
size?: SpacerSize | ThemeSpacingKey | ThemeSpacingValue
}

export const spacerStyles = {
Expand All @@ -20,7 +27,26 @@
xxl: 'var(--size-xxl)',
}

const isThemeSpacingKey = (
size: SpacerSize | ThemeSpacingKey | ThemeSpacingValue
): size is ThemeSpacingKey => typeof size === 'string' && size in theme.semantic.core.space

const getSpacingValue = (
size: SpacerSize | ThemeSpacingKey | ThemeSpacingValue,
): string => {
const themeSpacingValues = Object.values(theme.semantic.core.space)
if (typeof size === 'string' && themeSpacingValues.includes(size)) {
return size
}

if (isThemeSpacingKey(size)) {
return theme?.semantic?.core?.space?.[size] || '0'

Check warning on line 43 in redisinsight/ui/src/components/base/layout/spacer/spacer.styles.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
}

return spacerStyles[size as SpacerSize]

Check warning on line 46 in redisinsight/ui/src/components/base/layout/spacer/spacer.styles.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
}

export const StyledSpacer = styled.div<SpacerProps>`
flex-shrink: 0;
height: ${({ size = 'l' }) => spacerStyles[size]};
height: ${({ size = 'l' }) => getSpacingValue(size)};
`
21 changes: 13 additions & 8 deletions redisinsight/ui/src/components/base/layout/spacer/spacer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react'
import cx from 'classnames'
import { useTheme } from '@redis-ui/styles'
import {
SpacerProps,
StyledSpacer,
Expand All @@ -9,17 +10,21 @@ import {
* A simple spacer component that can be used to add vertical spacing between
* other components. The size of the spacer can be specified using the `size`
* prop, which can be one of the following values:
* - 'xs' = 4px
* - 's' = 8px
* - 'm' = 12px
* - 'l' = 16px
* - 'xl' = 24px
* - 'xxl' = 32px.
* - Legacy sizes: 'xs' = 4px, 's' = 8px, 'm' = 12px, 'l' = 16px, 'xl' = 24px, 'xxl' = 32px
* - Theme spacing sizes: Any key from theme.semantic.core.space (e.g., 'space000', 'space010',
* 'space025', 'space050', 'space100', 'space150', 'space200', 'space250', 'space300',
* 'space400', 'space500', 'space550', 'space600', 'space800', etc.)
*
* The theme spacing tokens are dynamically extracted from the theme, ensuring consistency
* and automatic updates when the theme changes.
*
* The default value for `size` is 'l'.
*/
export const Spacer = ({ className, children, ...rest }: SpacerProps) => (
<StyledSpacer {...rest} className={cx('RI-spacer', className)}>
export const Spacer = ({ className, children, ...rest }: SpacerProps) => {
const theme = useTheme()
return (
<StyledSpacer {...rest} className={cx('RI-spacer', className)} theme={theme}>
{children}
</StyledSpacer>
)
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import React from 'react'
import { EuiEmptyPrompt } from '@elastic/eui'

import LogoIcon from 'uiSrc/assets/img/logo_small.svg'
import { getConfig } from 'uiSrc/config'
import { RiLoadingLogo } from 'uiSrc/components/base/display'
import { RiEmptyPrompt } from 'uiSrc/components/base/layout'

const riConfig = getConfig()

const PagePlaceholder = () => (
<>
{riConfig.app.env !== 'development' && (
<EuiEmptyPrompt
<RiEmptyPrompt
data-testid="page-placeholder"
icon={<RiLoadingLogo src={LogoIcon} $size="XXL" />}
titleSize="s"
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from 'react'
import { EuiEmptyPrompt } from '@elastic/eui'

import { EXTERNAL_LINKS } from 'uiSrc/constants/links'
import { RiIcon } from 'uiSrc/components/base/icons/RiIcon'
import { Link } from 'uiSrc/components/base/link/Link'
import { RiEmptyPrompt } from 'uiSrc/components/base/layout'
import styles from './styles.module.scss'

const EmptyPrompt = () => (
<div className={styles.container}>
<EuiEmptyPrompt
<RiEmptyPrompt
data-testid="enablement-area__empty-prompt"
icon={<RiIcon type="ToastDangerIcon" color="danger600" size="l" />}
title={<h2>No information to display</h2>}
Expand Down
Loading