Back
Back
Back
Mobile Rotation Alert
Mobile Rotation Alert
Page Contents
Page Contents
Page Contents
If your site works better in one orientation than another why not let your users know with this little component.
This little component came about when I was building a page that, no matter what I tried, just didn’t look great on mobile landscape.
I thought, why not let users know the site works better in portrait? So I built this component—and here it is.
It offers several customization options, like color, icon, placement, and whether it appears in landscape or portrait mode.
A handy component to have when you need it. And as always, you’re welcome!
If you are not sure how to add code to Framer watch this quick video.
Framer Code Component
Mobile Rotation Alert
1.0
1.0
1.0
1.0
// A custom Framer code override by Chris Kellett - Framerverse
// Get more components at www.framerverse.com
// Mobile Landscape Alert
// Version 1.0
import React, { useState, useEffect } from "react"
import { addPropertyControls, ControlType } from "framer"
function LandscapeToastWarning(props) {
const {
icon,
iconSize,
title,
message,
backgroundColor,
textColor,
previewMode,
fontFamily,
position,
alertMode,
} = props
const [showToast, setShowToast] = useState(false)
useEffect(() => {
const checkOrientation = () => {
const isMobile = window.innerWidth <= 768
const isLandscape = window.innerWidth > window.innerHeight
const shouldShow =
previewMode ||
(isMobile &&
((alertMode === "Landscape" && isLandscape) ||
(alertMode === "Portrait" && !isLandscape)))
setShowToast(shouldShow)
}
if (!previewMode) {
checkOrientation()
window.addEventListener("resize", checkOrientation)
window.addEventListener("orientationchange", checkOrientation)
return () => {
window.removeEventListener("resize", checkOrientation)
window.removeEventListener(
"orientationchange",
checkOrientation
)
}
} else {
setShowToast(true)
}
}, [previewMode, alertMode])
if (!showToast) return null
// Determine position styles based on the selected position prop
const positionStyles = (() => {
switch (position) {
case "Top Left":
return { top: "20px", left: "20px" }
case "Top Center":
return {
top: "20px",
left: "50%",
transform: "translateX(-50%)",
}
case "Top Right":
return { top: "20px", right: "20px" }
case "Bottom Left":
return { bottom: "20px", left: "20px" }
case "Bottom Center":
return {
bottom: "20px",
left: "50%",
transform: "translateX(-50%)",
}
case "Bottom Right":
default:
return { bottom: "20px", right: "20px" }
}
})()
return (
<div
style={{
position: "fixed",
backgroundColor: backgroundColor,
color: textColor,
padding: "20px 20px",
borderRadius: "12px",
display: "flex",
alignItems: "center",
boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.1)",
width: "100%",
maxWidth: "350px",
zIndex: 1000,
fontFamily: fontFamily,
animation: "fadeInUp 0.5s ease-out",
...positionStyles,
}}
>
{icon && (
<span
style={{
marginRight: "20px",
display: "flex",
alignItems: "center",
}}
>
<img
src={icon}
alt="icon"
style={{ width: iconSize, height: iconSize }}
/>
</span>
)}
<div style={{ flex: 1 }}>
<h4
style={{
margin: 0,
fontSize: "16px",
fontWeight: "600",
color: textColor,
maxWidth: "90%",
paddingRight: "20px,",
}}
>
{title}
</h4>
<p
style={{
margin: "4px 0 0",
fontSize: "14px",
color: textColor,
lineHeight: "1.4",
maxWidth: "90%",
paddingRight: "20px,",
}}
>
{message}
</p>
</div>
<button
onClick={() => setShowToast(false)}
style={{
position: "absolute",
top: "12px",
right: "12px",
width: "24px",
height: "24px",
background: "transparent",
border: "none",
color: textColor,
cursor: "pointer",
fontSize: "24px",
lineHeight: "24px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
×
</button>
{/* Keyframe for fade-in and up animation */}
<style>{`
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
`}</style>
</div>
)
}
LandscapeToastWarning.defaultProps = {
icon: "https://example.com/path-to-your-icon.png", // Replace with a valid icon URL
iconSize: 24, // Default icon size
title: "Better on portrait",
message:
"This site is optimized for portrait orientation on mobile devices. Please rotate your device for the best experience.",
backgroundColor: "#34495e",
textColor: "#ffffff",
previewMode: true, // Enabled by default
fontFamily: "Inter, sans-serif", // Default font family
position: "Bottom Right", // Default position
alertMode: "Landscape", // Default to landscape mode
}
addPropertyControls(LandscapeToastWarning, {
icon: {
type: ControlType.Image,
title: "Icon",
},
iconSize: {
type: ControlType.Number,
title: "Icon Size",
defaultValue: 24,
min: 10,
max: 50,
unit: "px",
displayStepper: true,
},
title: {
type: ControlType.String,
title: "Title",
},
message: {
type: ControlType.String,
title: "Message",
displayTextArea: true,
},
backgroundColor: {
type: ControlType.Color,
title: "Background Color",
},
textColor: {
type: ControlType.Color,
title: "Text Color",
},
fontFamily: {
type: ControlType.String,
title: "Font Family",
defaultValue: "Inter, sans-serif",
},
position: {
type: ControlType.Enum,
title: "Position",
options: [
"Top Left",
"Top Center",
"Top Right",
"Bottom Left",
"Bottom Center",
"Bottom Right",
],
optionTitles: [
"Top Left",
"Top Center",
"Top Right",
"Bottom Left",
"Bottom Center",
"Bottom Right",
],
defaultValue: "Bottom Right",
},
alertMode: {
type: ControlType.Enum,
title: "Alert Mode",
options: ["Landscape", "Portrait"],
optionTitles: ["Landscape", "Portrait"],
defaultValue: "Landscape",
},
previewMode: {
type: ControlType.Boolean,
title: "Preview Mode",
defaultValue: true,
enabledTitle: "On",
disabledTitle: "Off",
},
})
export default LandscapeToastWarning
CLICK TO COPY
// A custom Framer code override by Chris Kellett - Framerverse
// Get more components at www.framerverse.com
// Mobile Landscape Alert
// Version 1.0
import React, { useState, useEffect } from "react"
import { addPropertyControls, ControlType } from "framer"
function LandscapeToastWarning(props) {
const {
icon,
iconSize,
title,
message,
backgroundColor,
textColor,
previewMode,
fontFamily,
position,
alertMode,
} = props
const [showToast, setShowToast] = useState(false)
useEffect(() => {
const checkOrientation = () => {
const isMobile = window.innerWidth <= 768
const isLandscape = window.innerWidth > window.innerHeight
const shouldShow =
previewMode ||
(isMobile &&
((alertMode === "Landscape" && isLandscape) ||
(alertMode === "Portrait" && !isLandscape)))
setShowToast(shouldShow)
}
if (!previewMode) {
checkOrientation()
window.addEventListener("resize", checkOrientation)
window.addEventListener("orientationchange", checkOrientation)
return () => {
window.removeEventListener("resize", checkOrientation)
window.removeEventListener(
"orientationchange",
checkOrientation
)
}
} else {
setShowToast(true)
}
}, [previewMode, alertMode])
if (!showToast) return null
// Determine position styles based on the selected position prop
const positionStyles = (() => {
switch (position) {
case "Top Left":
return { top: "20px", left: "20px" }
case "Top Center":
return {
top: "20px",
left: "50%",
transform: "translateX(-50%)",
}
case "Top Right":
return { top: "20px", right: "20px" }
case "Bottom Left":
return { bottom: "20px", left: "20px" }
case "Bottom Center":
return {
bottom: "20px",
left: "50%",
transform: "translateX(-50%)",
}
case "Bottom Right":
default:
return { bottom: "20px", right: "20px" }
}
})()
return (
<div
style={{
position: "fixed",
backgroundColor: backgroundColor,
color: textColor,
padding: "20px 20px",
borderRadius: "12px",
display: "flex",
alignItems: "center",
boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.1)",
width: "100%",
maxWidth: "350px",
zIndex: 1000,
fontFamily: fontFamily,
animation: "fadeInUp 0.5s ease-out",
...positionStyles,
}}
>
{icon && (
<span
style={{
marginRight: "20px",
display: "flex",
alignItems: "center",
}}
>
<img
src={icon}
alt="icon"
style={{ width: iconSize, height: iconSize }}
/>
</span>
)}
<div style={{ flex: 1 }}>
<h4
style={{
margin: 0,
fontSize: "16px",
fontWeight: "600",
color: textColor,
maxWidth: "90%",
paddingRight: "20px,",
}}
>
{title}
</h4>
<p
style={{
margin: "4px 0 0",
fontSize: "14px",
color: textColor,
lineHeight: "1.4",
maxWidth: "90%",
paddingRight: "20px,",
}}
>
{message}
</p>
</div>
<button
onClick={() => setShowToast(false)}
style={{
position: "absolute",
top: "12px",
right: "12px",
width: "24px",
height: "24px",
background: "transparent",
border: "none",
color: textColor,
cursor: "pointer",
fontSize: "24px",
lineHeight: "24px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
×
</button>
{/* Keyframe for fade-in and up animation */}
<style>{`
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
`}</style>
</div>
)
}
LandscapeToastWarning.defaultProps = {
icon: "https://example.com/path-to-your-icon.png", // Replace with a valid icon URL
iconSize: 24, // Default icon size
title: "Better on portrait",
message:
"This site is optimized for portrait orientation on mobile devices. Please rotate your device for the best experience.",
backgroundColor: "#34495e",
textColor: "#ffffff",
previewMode: true, // Enabled by default
fontFamily: "Inter, sans-serif", // Default font family
position: "Bottom Right", // Default position
alertMode: "Landscape", // Default to landscape mode
}
addPropertyControls(LandscapeToastWarning, {
icon: {
type: ControlType.Image,
title: "Icon",
},
iconSize: {
type: ControlType.Number,
title: "Icon Size",
defaultValue: 24,
min: 10,
max: 50,
unit: "px",
displayStepper: true,
},
title: {
type: ControlType.String,
title: "Title",
},
message: {
type: ControlType.String,
title: "Message",
displayTextArea: true,
},
backgroundColor: {
type: ControlType.Color,
title: "Background Color",
},
textColor: {
type: ControlType.Color,
title: "Text Color",
},
fontFamily: {
type: ControlType.String,
title: "Font Family",
defaultValue: "Inter, sans-serif",
},
position: {
type: ControlType.Enum,
title: "Position",
options: [
"Top Left",
"Top Center",
"Top Right",
"Bottom Left",
"Bottom Center",
"Bottom Right",
],
optionTitles: [
"Top Left",
"Top Center",
"Top Right",
"Bottom Left",
"Bottom Center",
"Bottom Right",
],
defaultValue: "Bottom Right",
},
alertMode: {
type: ControlType.Enum,
title: "Alert Mode",
options: ["Landscape", "Portrait"],
optionTitles: ["Landscape", "Portrait"],
defaultValue: "Landscape",
},
previewMode: {
type: ControlType.Boolean,
title: "Preview Mode",
defaultValue: true,
enabledTitle: "On",
disabledTitle: "Off",
},
})
export default LandscapeToastWarning
CLICK TO COPY
// A custom Framer code override by Chris Kellett - Framerverse
// Get more components at www.framerverse.com
// Mobile Landscape Alert
// Version 1.0
import React, { useState, useEffect } from "react"
import { addPropertyControls, ControlType } from "framer"
function LandscapeToastWarning(props) {
const {
icon,
iconSize,
title,
message,
backgroundColor,
textColor,
previewMode,
fontFamily,
position,
alertMode,
} = props
const [showToast, setShowToast] = useState(false)
useEffect(() => {
const checkOrientation = () => {
const isMobile = window.innerWidth <= 768
const isLandscape = window.innerWidth > window.innerHeight
const shouldShow =
previewMode ||
(isMobile &&
((alertMode === "Landscape" && isLandscape) ||
(alertMode === "Portrait" && !isLandscape)))
setShowToast(shouldShow)
}
if (!previewMode) {
checkOrientation()
window.addEventListener("resize", checkOrientation)
window.addEventListener("orientationchange", checkOrientation)
return () => {
window.removeEventListener("resize", checkOrientation)
window.removeEventListener(
"orientationchange",
checkOrientation
)
}
} else {
setShowToast(true)
}
}, [previewMode, alertMode])
if (!showToast) return null
// Determine position styles based on the selected position prop
const positionStyles = (() => {
switch (position) {
case "Top Left":
return { top: "20px", left: "20px" }
case "Top Center":
return {
top: "20px",
left: "50%",
transform: "translateX(-50%)",
}
case "Top Right":
return { top: "20px", right: "20px" }
case "Bottom Left":
return { bottom: "20px", left: "20px" }
case "Bottom Center":
return {
bottom: "20px",
left: "50%",
transform: "translateX(-50%)",
}
case "Bottom Right":
default:
return { bottom: "20px", right: "20px" }
}
})()
return (
<div
style={{
position: "fixed",
backgroundColor: backgroundColor,
color: textColor,
padding: "20px 20px",
borderRadius: "12px",
display: "flex",
alignItems: "center",
boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.1)",
width: "100%",
maxWidth: "350px",
zIndex: 1000,
fontFamily: fontFamily,
animation: "fadeInUp 0.5s ease-out",
...positionStyles,
}}
>
{icon && (
<span
style={{
marginRight: "20px",
display: "flex",
alignItems: "center",
}}
>
<img
src={icon}
alt="icon"
style={{ width: iconSize, height: iconSize }}
/>
</span>
)}
<div style={{ flex: 1 }}>
<h4
style={{
margin: 0,
fontSize: "16px",
fontWeight: "600",
color: textColor,
maxWidth: "90%",
paddingRight: "20px,",
}}
>
{title}
</h4>
<p
style={{
margin: "4px 0 0",
fontSize: "14px",
color: textColor,
lineHeight: "1.4",
maxWidth: "90%",
paddingRight: "20px,",
}}
>
{message}
</p>
</div>
<button
onClick={() => setShowToast(false)}
style={{
position: "absolute",
top: "12px",
right: "12px",
width: "24px",
height: "24px",
background: "transparent",
border: "none",
color: textColor,
cursor: "pointer",
fontSize: "24px",
lineHeight: "24px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
×
</button>
{/* Keyframe for fade-in and up animation */}
<style>{`
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
`}</style>
</div>
)
}
LandscapeToastWarning.defaultProps = {
icon: "https://example.com/path-to-your-icon.png", // Replace with a valid icon URL
iconSize: 24, // Default icon size
title: "Better on portrait",
message:
"This site is optimized for portrait orientation on mobile devices. Please rotate your device for the best experience.",
backgroundColor: "#34495e",
textColor: "#ffffff",
previewMode: true, // Enabled by default
fontFamily: "Inter, sans-serif", // Default font family
position: "Bottom Right", // Default position
alertMode: "Landscape", // Default to landscape mode
}
addPropertyControls(LandscapeToastWarning, {
icon: {
type: ControlType.Image,
title: "Icon",
},
iconSize: {
type: ControlType.Number,
title: "Icon Size",
defaultValue: 24,
min: 10,
max: 50,
unit: "px",
displayStepper: true,
},
title: {
type: ControlType.String,
title: "Title",
},
message: {
type: ControlType.String,
title: "Message",
displayTextArea: true,
},
backgroundColor: {
type: ControlType.Color,
title: "Background Color",
},
textColor: {
type: ControlType.Color,
title: "Text Color",
},
fontFamily: {
type: ControlType.String,
title: "Font Family",
defaultValue: "Inter, sans-serif",
},
position: {
type: ControlType.Enum,
title: "Position",
options: [
"Top Left",
"Top Center",
"Top Right",
"Bottom Left",
"Bottom Center",
"Bottom Right",
],
optionTitles: [
"Top Left",
"Top Center",
"Top Right",
"Bottom Left",
"Bottom Center",
"Bottom Right",
],
defaultValue: "Bottom Right",
},
alertMode: {
type: ControlType.Enum,
title: "Alert Mode",
options: ["Landscape", "Portrait"],
optionTitles: ["Landscape", "Portrait"],
defaultValue: "Landscape",
},
previewMode: {
type: ControlType.Boolean,
title: "Preview Mode",
defaultValue: true,
enabledTitle: "On",
disabledTitle: "Off",
},
})
export default LandscapeToastWarning
CLICK TO COPY
What is it?
If your site works better in one orientation than another why not let your users know with this little component.
What is it?
If your site works better in one orientation than another why not let your users know with this little component.
What is it?
If your site works better in one orientation than another why not let your users know with this little component.
How to use.
Click in the code are below to copy the code to your clipboard. Then click the 'plus' button int the assets panel for 'Code'. Choose if its an overide or Component. Paste the code in and save.
How to use.
Click in the code are below to copy the code to your clipboard. Then click the 'plus' button int the assets panel for 'Code'. Choose if its an overide or Component. Paste the code in and save.
How to use.
Click in the code are below to copy the code to your clipboard. Then click the 'plus' button int the assets panel for 'Code'. Choose if its an overide or Component. Paste the code in and save.
Usage Licence
I'm happy for you to use this code in your projects, even templates. If you use it please keep my accreditation in the code. Please don't sell it as your own. (Hover for full licence).
Usage Licence
I'm happy for you to use this code in your projects, even templates. If you use it please keep my accreditation in the code. Please don't sell it as your own. (Hover for full licence).
Usage Licence
I'm happy for you to use this code in your projects, even templates. If you use it please keep my accreditation in the code. Please don't sell it as your own. (Hover for full licence).
Change Log
// Version 1.0
Figma to Framer
Support
If you need support first watch the help video above. If that does not help reach out to me on one of my social channels or use the contact form. As I am a team of one it may take a short while to get back to you. Please be patient, thanks.
Hope this helps. Good luck with your project.
More Framer resources.
Real Loan Calculator
Add a fully functional, responsive, configurable loan calculator to your project.
Section
Real Loan Calculator
Add a fully functional, responsive, configurable loan calculator to your project.
Section
Real Loan Calculator
Add a fully functional, responsive, configurable loan calculator to your project.
Section
Starfield Generator
A niche component for creating a swirling Starfield, simple but great in the right scenario (like this site).
Code Component
Starfield Generator
A niche component for creating a swirling Starfield, simple but great in the right scenario (like this site).
Code Component
Starfield Generator
A niche component for creating a swirling Starfield, simple but great in the right scenario (like this site).
Code Component
Swipe Variant Changer
Use this component and overide combo to create a swipe toggle that switches component variants.
Code Override
Swipe Variant Changer
Use this component and overide combo to create a swipe toggle that switches component variants.
Code Override
Swipe Variant Changer
Use this component and overide combo to create a swipe toggle that switches component variants.
Code Override
Change Variants with URL Parameters
Use a URL parameter to change the variant on the page you link to.
Code Override
Change Variants with URL Parameters
Use a URL parameter to change the variant on the page you link to.
Code Override
Change Variants with URL Parameters
Use a URL parameter to change the variant on the page you link to.
Code Override
Simple Documentation Maker
Need a simple documentation system? This component adds auto linking contents list to a one page document system.
Code Component
Simple Documentation Maker
Need a simple documentation system? This component adds auto linking contents list to a one page document system.
Code Component
Simple Documentation Maker
Need a simple documentation system? This component adds auto linking contents list to a one page document system.
Code Component
Multi-step Form Experience
Build simple form experiences that look, feel and work like a multi-step form.
Section
Multi-step Form Experience
Build simple form experiences that look, feel and work like a multi-step form.
Section
Multi-step Form Experience
Build simple form experiences that look, feel and work like a multi-step form.
Section