-
Notifications
You must be signed in to change notification settings - Fork 8
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
Feature/info message component #644
Changes from 2 commits
02463ad
2ec37da
16ee5b7
41c1307
04596ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
node_modules/ | ||
dist/ | ||
coverage/ | ||
|
||
# Logs | ||
logs | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import styled from 'styled-components'; | ||
import { Link, Text } from '../text/Text.component'; | ||
import { Icon } from '../icon/Icon.component'; | ||
import { defaultTheme } from '../../style/theme'; | ||
import { useComputeBackgroundColor } from './InfoMessageUtils'; | ||
|
||
type Props = { | ||
title: string; | ||
content: React.ReactNode; | ||
link?: string; | ||
}; | ||
|
||
const InfoMessageContainer = styled.div` | ||
background-color: ${defaultTheme.darkRebrand.backgroundLevel2}; | ||
border-radius: 3px; | ||
padding: 0.5rem; | ||
display: flex; | ||
flex-direction: column; | ||
gap: 0.5rem; | ||
color: white; | ||
`; | ||
const TitleContainer = styled.div` | ||
align-items: center; | ||
display: flex; | ||
gap: 0.5rem; | ||
`; | ||
|
||
function InfoMessage({ title, content, link }: Props) { | ||
const { containerRef, backgroundColor } = useComputeBackgroundColor(); | ||
|
||
return ( | ||
<InfoMessageContainer | ||
ref={containerRef} | ||
style={{ backgroundColor: backgroundColor }} | ||
> | ||
<TitleContainer> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This component can likely be replaced by a Stack |
||
<Icon | ||
name="Info-circle" | ||
color={defaultTheme.darkRebrand.infoPrimary} | ||
size="lg" | ||
/> | ||
<Text isEmphazed>{title}</Text> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would check the typeOf title if it is a string then I would render it within the Text isEmphazed component, If it is a react node (else) I would render it directly |
||
</TitleContainer> | ||
<Text color="textSecondary">{content}</Text> | ||
{link && ( | ||
<Link href={link} target="_blank" style={{ alignSelf: 'flex-end' }}> | ||
More infos <Icon name="External-link"></Icon> | ||
</Link> | ||
)} | ||
</InfoMessageContainer> | ||
); | ||
} | ||
|
||
export default InfoMessage; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import { defaultTheme } from '../../style/theme'; | ||
import React from 'react'; | ||
import { useComputeBackgroundColor } from './InfoMessageUtils'; | ||
import { render } from '@testing-library/react'; | ||
import '@testing-library/jest-dom'; | ||
import { CoreUiThemeProvider } from '../coreuithemeprovider/CoreUiThemeProvider'; | ||
|
||
describe('useComputeBackgroundColor', () => { | ||
it('should return backgroundlevel2 by default', () => { | ||
//S | ||
const SUT = jest.fn(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could be declared once and be more explicit |
||
const Component = () => { | ||
const { containerRef, backgroundColor } = useComputeBackgroundColor(); | ||
SUT(backgroundColor); | ||
return <div ref={containerRef}>{backgroundColor}</div>; | ||
}; | ||
render( | ||
<CoreUiThemeProvider theme={defaultTheme.darkRebrand}> | ||
<Component /> | ||
</CoreUiThemeProvider>, | ||
); | ||
//V | ||
expect(SUT).toHaveBeenCalledWith(defaultTheme.darkRebrand.backgroundLevel2); | ||
}); | ||
|
||
it('should return backgroundlevel3 if parent element backgroundColor is level 2', () => { | ||
//S | ||
const SUT = jest.fn(); | ||
const Component = () => { | ||
const { containerRef, backgroundColor } = useComputeBackgroundColor(); | ||
SUT(backgroundColor); | ||
return ( | ||
<div | ||
style={{ backgroundColor: defaultTheme.darkRebrand.backgroundLevel2 }} | ||
> | ||
<div ref={containerRef}>{backgroundColor}</div> | ||
</div> | ||
); | ||
}; | ||
render( | ||
<CoreUiThemeProvider theme={defaultTheme.darkRebrand}> | ||
<Component /> | ||
</CoreUiThemeProvider>, | ||
); | ||
//V | ||
expect(SUT).toHaveBeenCalledWith(defaultTheme.darkRebrand.backgroundLevel3); | ||
}); | ||
it('should return backgroundlevel3 if parent of parent element backgroundColor is level 2', () => { | ||
//S | ||
const SUT = jest.fn(); | ||
const Component = () => { | ||
const { containerRef, backgroundColor } = useComputeBackgroundColor(); | ||
SUT(backgroundColor); | ||
return ( | ||
<div | ||
style={{ backgroundColor: defaultTheme.darkRebrand.backgroundLevel2 }} | ||
> | ||
<div> | ||
<div ref={containerRef}>{backgroundColor}</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
render( | ||
<CoreUiThemeProvider theme={defaultTheme.darkRebrand}> | ||
<Component /> | ||
</CoreUiThemeProvider>, | ||
); | ||
//V | ||
expect(SUT).toHaveBeenCalledWith(defaultTheme.darkRebrand.backgroundLevel3); | ||
}); | ||
it('should return backgroundlevel2 if parent of parent element backgroundColor is level 3', () => { | ||
//S | ||
const SUT = jest.fn(); | ||
const Component = () => { | ||
const { containerRef, backgroundColor } = useComputeBackgroundColor(); | ||
SUT(backgroundColor); | ||
return ( | ||
<div | ||
style={{ backgroundColor: defaultTheme.darkRebrand.backgroundLevel3 }} | ||
> | ||
<div> | ||
<div ref={containerRef}>{backgroundColor}</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
render( | ||
<CoreUiThemeProvider theme={defaultTheme.darkRebrand}> | ||
<Component /> | ||
</CoreUiThemeProvider>, | ||
); | ||
//V | ||
expect(SUT).toHaveBeenCalledWith(defaultTheme.darkRebrand.backgroundLevel2); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { DefaultTheme, useTheme } from "styled-components"; | ||
import { hex2RGB } from "../../utils"; | ||
import { useEffect, useRef, useState } from "react"; | ||
|
||
export const useComputeBackgroundColor = () => { | ||
const theme = useTheme(); | ||
const containerRef = useRef<HTMLDivElement | null>(null); | ||
const [backgroundColor, setBackgroundColor] = useState(''); | ||
|
||
useEffect(() => { | ||
containerRef.current && | ||
setBackgroundColor(getBackgroundColor(containerRef.current, theme)); | ||
}, [containerRef,theme]); | ||
|
||
return { | ||
containerRef, | ||
backgroundColor, | ||
}; | ||
}; | ||
|
||
export const getBackgroundColor = (element: HTMLElement, theme: DefaultTheme) => { | ||
if (element.parentElement) { | ||
const parentElementBackgroundColor = window.getComputedStyle( | ||
element.parentElement, | ||
)['background-color']; | ||
if (/rgba\([0-9]+, [0-9]+, [0-9]+, 0\)/.test(parentElementBackgroundColor) || !window.getComputedStyle(element.parentElement,)['background-color']) { | ||
return getBackgroundColor(element.parentElement, theme); | ||
} else { | ||
const rgbArray = hex2RGB(theme.backgroundLevel2); | ||
if ( | ||
`rgb(${rgbArray[0]}, ${rgbArray[1]}, ${rgbArray[2]})` === | ||
parentElementBackgroundColor | ||
) { | ||
return theme.backgroundLevel3; | ||
} | ||
} | ||
} | ||
return theme.backgroundLevel2; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import React from 'react'; | ||
import InfoMessage from '../src/lib/components/infomessage/InfoMessage.component'; | ||
import { Wrapper } from './common'; | ||
import { defaultTheme } from '../src/lib/style/theme'; | ||
import { Meta, StoryObj } from '@storybook/react'; | ||
|
||
type Story = StoryObj<typeof InfoMessage>; | ||
|
||
const meta: Meta<typeof InfoMessage> = { | ||
title: 'Components/InfoMessage', | ||
component: InfoMessage, | ||
decorators: [(story) => <Wrapper>{story()}</Wrapper>], | ||
}; | ||
|
||
export default meta; | ||
|
||
export const Playground: StoryObj< | ||
React.ComponentProps<typeof InfoMessage> & { backgroundColor?: string } | ||
> = { | ||
render: ({ backgroundColor, ...args }) => ( | ||
<div | ||
style={{ | ||
backgroundColor, | ||
padding: '1rem', | ||
}} | ||
> | ||
<div | ||
style={{ | ||
padding: '1rem', | ||
}} | ||
> | ||
<InfoMessage | ||
title="What to do with this key?" | ||
content="This key is needed by the Veeam repository to access ARTESCA for data backup." | ||
link="test" | ||
/> | ||
</div> | ||
</div> | ||
), | ||
argTypes: { | ||
backgroundColor: { | ||
description: 'Background color of the parent element', | ||
options: ['Level1', 'Level2', 'Level3', 'Level4'], | ||
mapping: { | ||
Level1: defaultTheme.darkRebrand.backgroundLevel1, | ||
Level2: defaultTheme.darkRebrand.backgroundLevel2, | ||
Level3: defaultTheme.darkRebrand.backgroundLevel3, | ||
Level4: defaultTheme.darkRebrand.backgroundLevel4, | ||
}, | ||
control: { | ||
type: 'radio', | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
export const Default: Story = { | ||
args: { | ||
title: 'Title for the provided info', | ||
content: 'Some text that will help the user to understand what to do', | ||
}, | ||
}; | ||
|
||
export const WithLink: Story = { | ||
args: { | ||
...Default.args, | ||
link: 'toDocs', | ||
}, | ||
}; | ||
|
||
export const WithDifferentBackground: Story = { | ||
render: (args) => { | ||
return ( | ||
<div | ||
style={{ | ||
padding: '1rem', | ||
display: 'flex', | ||
flexDirection: 'column', | ||
justifyContent: 'space-around', | ||
height: '30rem', | ||
}} | ||
> | ||
<div | ||
style={{ | ||
height: '10rem', | ||
backgroundColor: defaultTheme.darkRebrand.backgroundLevel3, | ||
padding: '1rem', | ||
}} | ||
> | ||
<InfoMessage {...args} /> | ||
</div> | ||
<div | ||
style={{ | ||
height: '10rem', | ||
backgroundColor: defaultTheme.darkRebrand.backgroundLevel2, | ||
padding: '1rem', | ||
}} | ||
> | ||
<InfoMessage {...args} /> | ||
</div> | ||
</div> | ||
); | ||
}, | ||
args: { | ||
...Default.args, | ||
}, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would make it possible to provide a ReactNode or a string here. It would allow use cases where we want to add icons or actions button towards the end of the title line.