Cover
Open, close, and position covers: blinds, garage doors, curtains, shades.
Quick Example
// Component approach
<Cover entityId="cover.garage_door">
{({ isOpen, isClosed, open, close }) => (
<div>
<p>Garage: {isOpen ? 'OPEN' : isClosed ? 'CLOSED' : 'PARTIAL'}</p>
<button onClick={isOpen ? close : open}>
{isOpen ? 'Close' : 'Open'}
</button>
</div>
)}
</Cover>
// Hook approach
const garage = useCover('cover.garage_door')
<div>
<p>Garage: {garage.isOpen ? 'OPEN' : garage.isClosed ? 'CLOSED' : 'PARTIAL'}</p>
<button onClick={garage.isOpen ? garage.close : garage.open}>
{garage.isOpen ? 'Close' : 'Open'}
</button>
</div>
Component API
Basic Usage
import { Cover } from 'hass-react'
<Cover entityId="cover.garage_door">
{(coverProps) => (
// Your UI here
)}
</Cover>
Render Props
The Cover component provides these props to your render function:
State Properties
isOpen(boolean) - Whether the cover is fully openisClosed(boolean) - Whether the cover is fully closedisOpening(boolean) - Whether the cover is currently openingisClosing(boolean) - Whether the cover is currently closingposition(number | undefined) - Current position (0-100, where 0 is closed and 100 is open)
Support Properties
supportsSetPosition(boolean) - Cover supports position controlsupportsStop(boolean) - Cover can be stopped mid-travel
Control Methods
open()- Open the cover completelyclose()- Close the cover completelystop()- Stop the cover movement. ThrowsFeatureNotSupportedErrorif the device can't stop, so checksupportsStopfirstsetPosition(position: number)- Move the cover to a specific position (0-100). ThrowsFeatureNotSupportedErrorif the device doesn't support positioning, so checksupportsSetPositionfirst
Entity Properties
entityId(string) - The entity IDstate(string) - Raw state value from Home Assistantattributes(object) - All entity attributeslastChanged(Date) - When the entity last changedlastUpdated(Date) - When the entity was last updated
Hook API
Basic Usage
import { useCover } from 'hass-react'
function MyComponent() {
const cover = useCover('cover.garage_door')
// All the same properties as component render props
return <div>{cover.isOpen ? 'OPEN' : 'CLOSED'}</div>
}
Everything the component passes to its render function is also on the object useCover returns.
List All Covers
To list every cover entity, use the useCovers hook:
import { useCovers } from 'hass-react'
function CoverList() {
const covers = useCovers()
return (
<div>
<h2>Available Covers ({covers.length})</h2>
{covers.map(cover => (
<div key={cover.entity_id}>
{cover.attributes.friendly_name || cover.entity_id}
</div>
))}
</div>
)
}
It returns an array of cover entity objects.
Examples
Simple Cover Control
<Cover entityId="cover.living_room_blinds">
{({ isOpen, isClosed, isOpening, isClosing, open, close, stop, attributes }) => (
<div>
<h3>{attributes.friendly_name}</h3>
<p>
Status: {
isOpening ? 'OPENING' :
isClosing ? 'CLOSING' :
isOpen ? 'OPEN' :
isClosed ? 'CLOSED' : 'PARTIAL'
}
</p>
<button onClick={open} disabled={isOpen || isOpening}>
Open
</button>
<button onClick={close} disabled={isClosed || isClosing}>
Close
</button>
{(isOpening || isClosing) && (
<button onClick={stop}>
Stop
</button>
)}
</div>
)}
</Cover>
Position Control
<Cover entityId="cover.bedroom_shades">
{({ position, setPosition, isOpening, isClosing, attributes }) => (
<div>
<h3>{attributes.friendly_name}</h3>
<p>Position: {position !== undefined ? `${position}%` : 'Unknown'}</p>
{position !== undefined && (
<div>
<input
type="range"
min="0"
max="100"
value={position}
onChange={(e) => setPosition(parseInt(e.target.value))}
disabled={isOpening || isClosing}
/>
<div>
<button onClick={() => setPosition(0)}>
Fully Closed
</button>
<button onClick={() => setPosition(25)}>
25%
</button>
<button onClick={() => setPosition(50)}>
50%
</button>
<button onClick={() => setPosition(75)}>
75%
</button>
<button onClick={() => setPosition(100)}>
Fully Open
</button>
</div>
</div>
)}
</div>
)}
</Cover>
Garage Door Control
<Cover entityId="cover.garage_door">
{({ isOpen, isClosed, isOpening, isClosing, open, close, stop, attributes, lastChanged }) => (
<div>
<h3>{attributes.friendly_name}</h3>
<div>
Status: {
isOpening ? 'OPENING' :
isClosing ? 'CLOSING' :
isOpen ? 'OPEN' :
isClosed ? 'CLOSED' : 'UNKNOWN'
}
</div>
<div>
<button
onClick={isOpen ? close : open}
disabled={isOpening || isClosing}
>
{isOpen ? 'Close Garage' : 'Open Garage'}
</button>
{(isOpening || isClosing) && (
<button onClick={stop}>
Emergency Stop
</button>
)}
</div>
{isOpen && (
<p style={{ color: 'orange' }}>
Warning: Garage door is open
</p>
)}
<p>Last changed: {lastChanged.toLocaleString()}</p>
</div>
)}
</Cover>
Multiple Covers
function CoverPanel() {
const covers = [
'cover.living_room_blinds',
'cover.bedroom_shades',
'cover.kitchen_curtains'
]
return (
<div>
<h2>Window Coverings</h2>
{covers.map(entityId => (
<Cover key={entityId} entityId={entityId}>
{({ isOpen, isClosed, position, open, close, attributes }) => (
<div>
<strong>{attributes.friendly_name}</strong>
<br />
Status: {isOpen ? 'OPEN' : isClosed ? 'CLOSED' : 'PARTIAL'}
{position !== undefined && ` (${position}%)`}
<br />
<button onClick={open} disabled={isOpen}>
Open
</button>
<button onClick={close} disabled={isClosed}>
Close
</button>
</div>
)}
</Cover>
))}
</div>
)
}
Smart Blinds with Scheduling
<Cover entityId="cover.office_blinds">
{({ position, setPosition, attributes }) => {
const [autoMode, setAutoMode] = useState(false)
useEffect(() => {
if (!autoMode) return
const now = new Date()
const hour = now.getHours()
// Auto-adjust based on time of day
if (hour >= 6 && hour < 9) {
// Morning: 25% open
setPosition(25)
} else if (hour >= 9 && hour < 17) {
// Daytime: 75% open
setPosition(75)
} else if (hour >= 17 && hour < 20) {
// Evening: 50% open
setPosition(50)
} else {
// Night: Closed
setPosition(0)
}
}, [autoMode, setPosition])
return (
<div>
<h3>{attributes.friendly_name}</h3>
<p>Position: {position !== undefined ? `${position}%` : 'Unknown'}</p>
<div>
<label>
<input
type="checkbox"
checked={autoMode}
onChange={(e) => setAutoMode(e.target.checked)}
/>
Auto-scheduling
</label>
</div>
{!autoMode && position !== undefined && (
<input
type="range"
min="0"
max="100"
value={position}
onChange={(e) => setPosition(parseInt(e.target.value))}
/>
)}
</div>
)
}}
</Cover>
Cover Status Indicator
<Cover entityId="cover.patio_awning">
{({ isOpen, isClosed, isOpening, isClosing, position, attributes }) => {
const getStatusColor = () => {
if (isOpening || isClosing) return 'blue'
if (isOpen) return 'green'
if (isClosed) return 'gray'
return 'orange'
}
const getStatusText = () => {
if (isOpening) return 'OPENING...'
if (isClosing) return 'CLOSING...'
if (isOpen) return 'OPEN'
if (isClosed) return 'CLOSED'
return 'PARTIAL'
}
return (
<div>
<h3>{attributes.friendly_name}</h3>
<div style={{ color: getStatusColor() }}>
Status: {getStatusText()}
{position !== undefined && ` (${position}%)`}
</div>
{position !== undefined && (
<div>
Progress: {position}%
</div>
)}
</div>
)
}}
</Cover>
Using Hooks
import { useCover } from 'hass-react'
function CoverCard({ entityId }) {
const cover = useCover(entityId)
const getStatusDisplay = () => {
if (cover.isOpening) return { text: 'OPENING', color: 'blue' }
if (cover.isClosing) return { text: 'CLOSING', color: 'blue' }
if (cover.isOpen) return { text: 'OPEN', color: 'green' }
if (cover.isClosed) return { text: 'CLOSED', color: 'gray' }
return { text: 'PARTIAL', color: 'orange' }
}
const status = getStatusDisplay()
return (
<div>
<h3>{cover.attributes.friendly_name}</h3>
<div style={{ color: status.color }}>
Status: {status.text}
{cover.position !== undefined && ` (${cover.position}%)`}
</div>
<div>
<button
onClick={cover.open}
disabled={cover.isOpen || cover.isOpening}
>
Open
</button>
<button
onClick={cover.close}
disabled={cover.isClosed || cover.isClosing}
>
Close
</button>
{(cover.isOpening || cover.isClosing) && (
<button onClick={cover.stop}>
Stop
</button>
)}
</div>
{cover.position !== undefined && (
<div>
<input
type="range"
min="0"
max="100"
value={cover.position}
onChange={(e) => cover.setPosition(parseInt(e.target.value))}
disabled={cover.isOpening || cover.isClosing}
/>
</div>
)}
<p>Last updated: {cover.lastUpdated.toLocaleTimeString()}</p>
</div>
)
}