Skip to content

Commit

Permalink
Merge #442
Browse files Browse the repository at this point in the history
442: Add a call to action banner for the cloud r=bidoubiwa a=bidoubiwa

Fixes: #441 

A banner now automatically appears at the top of the page with a call to action to the Meilisearch cloud.

To deactivate the banner, you can add `cloud_banner=false` to the query parameters.

## TODO: 
- [x] Implement banner
- [x] Implement query param
- [x] Implement caching of banner visibility 

Co-authored-by: Charlotte Vermandel <charlottevermandel@gmail.com>
Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com>
  • Loading branch information
3 people committed Jul 10, 2023
2 parents d36abd9 + a93d6c3 commit 298daff
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 2 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
],
"react/no-arrow-function-lifecycle": 0,
"react/no-invalid-html-attribute": 0,
"react/jsx-no-useless-fragment": "off",
"react/no-unused-class-component-methods": 0
}
}
10 changes: 9 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import ApiKeyModalContent from 'components/ApiKeyModalContent'
import Box from 'components/Box'
import EmptyView from 'components/EmptyView'
import Header from 'components/Header/index'
// import Sidebar from 'components/Sidebar'
import CloudBanner from 'components/CloudBanner'
import Modal from 'components/Modal'
import OnBoarding from 'components/OnBoarding'
import Results from 'components/Results'
Expand Down Expand Up @@ -93,6 +93,8 @@ const App = () => {
const [isMeilisearchRunning, setIsMeilisearchRunning] = React.useState(true)
const [requireApiKeyToWork, setRequireApiKeyToWork] = React.useState(false)
const [currentIndex, setCurrentIndex] = useLocalStorage('currentIndex')
const [showCloudBanner, setShowCloudBanner] = React.useState(true)

const [ISClient, setISClient] = React.useState(
instantMeilisearch(baseUrl, apiKey, {
primaryKey: 'id',
Expand Down Expand Up @@ -147,6 +149,11 @@ const App = () => {
// Check if the API key is present on the url then put it in the local storage
const urlParams = new URLSearchParams(window.location.search)
const apiKeyParam = urlParams.get('api_key')
const cloudBannerQueryParam = urlParams.get('cloud_banner')

if (cloudBannerQueryParam === 'false') {
setShowCloudBanner(false)
}
if (apiKeyParam) {
setApiKey(apiKeyParam)
}
Expand Down Expand Up @@ -214,6 +221,7 @@ const App = () => {
indexName={currentIndex ? currentIndex.uid : ''}
searchClient={ISClient}
>
{showCloudBanner && <CloudBanner />}
<Header
indexes={indexes}
currentIndex={currentIndex}
Expand Down
91 changes: 91 additions & 0 deletions src/components/CloudBanner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React from 'react'
import styled from 'styled-components'
import Color from 'color'
import Typography from 'components/Typography'
import Link from 'components/Link'

import IconButton from 'components/IconButton'
import { Cross } from 'components/icons'
import Container from './Container'

const Button = styled(IconButton)`
position: absolute;
top: 27px;
right: 16px;
&:hover {
pointer-events: initial;
}
`

const CloudBannerWrapper = styled.div`
background: linear-gradient(269.85deg, #ff1786 0%, #8e33de 100%);
display: flex;
position: sticky;
top: 0;
height: 74px;
box-shadow: 0px 0px 30px ${(p) => Color(p.theme.colors.gray[0]).alpha(0.15)};
z-index: 3;
padding: 4px;
`

const CloudBanner = () => {
const [isBannerVisible, setIsBannerVisible] = React.useState(true)

const handleBannerClose = () => {
setIsBannerVisible(false)
localStorage.setItem('bannerVisibility', JSON.stringify(false))
}

// Retrieve the banner visibility state from local storage on component mount
React.useEffect(() => {
const storedVisibility = localStorage.getItem('bannerVisibility')
if (storedVisibility) {
setIsBannerVisible(JSON.parse(storedVisibility))
}

return () => {}
}, [])

return (
<>
{isBannerVisible && (
<CloudBannerWrapper>
<Container
display="flex"
flexDirection="column"
alignContent="center"
>
<Typography variant="typo14" color="white">
Supercharge your Meilisearch experience
</Typography>

<Typography variant="typo15" color="white">
Say goodbye to server management, and manual updates with{' '}
<Link
href="https://www.meilisearch.com/pricing?utm_campaign=oss&utm_source=integration&utm_medium=minidashboard"
color="white"
>
<Typography variant="typo14" color="white">
Meilisearch Cloud
</Typography>
</Link>
.&nbsp;
<Typography variant="typo14" color="white">
Get started with a 14-day free trial! No credit card required.
</Typography>
</Typography>
<Button
color="gray.9"
aria-label="close"
onClick={handleBannerClose}
>
<Cross style={{ width: 10 }} />
</Button>
</Container>
</CloudBannerWrapper>
)}
</>
)
}

export default CloudBanner
2 changes: 1 addition & 1 deletion src/components/Link.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import styled from 'styled-components'
import PropTypes from 'prop-types'

const A = styled.a`
color: ${(p) => p.theme.colors.main.default};
color: ${(p) => p.color || p.theme.colors.main.default};
text-decoration: underline;
transition: color 300ms;
outline: none;
Expand Down
21 changes: 21 additions & 0 deletions src/components/Typography.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,25 @@ const variants = {
font-weight: 500;
`,
},
// Used in CloudBanner
typo14: {
tag: 'span',
style: css`
font-size: 15px;
line-height: 25px;
font-weight: 500;
`,
},
// Used in CloudBanner
typo15: {
tag: 'span',
style: css`
font-size: 15px;
font-weight: 300;
line-height: 25px;
display: inline-block;
`,
},
}

const StyledTypography = styled.span`
Expand Down Expand Up @@ -155,6 +174,8 @@ Typography.propTypes = {
'typo11',
'typo12',
'typo13',
'typo14',
'typo15',
]),
/**
* Text to be displayed
Expand Down

0 comments on commit 298daff

Please sign in to comment.