Skip to main content

Cover

Control covers, blinds, garage doors, curtains, and 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 open
  • isClosed (boolean) - Whether the cover is fully closed
  • isOpening (boolean) - Whether the cover is currently opening
  • isClosing (boolean) - Whether the cover is currently closing
  • position (number | undefined) - Current position (0-100, where 0 is closed and 100 is open)

Control Methods

  • open() - Open the cover completely
  • close() - Close the cover completely
  • stop() - Stop the cover movement
  • setPosition(position: number) - Set cover to specific position (0-100)

Entity Properties

  • entityId (string) - The entity ID
  • state (string) - Raw state value from Home Assistant
  • attributes (object) - All entity attributes
  • lastChanged (Date) - When the entity last changed
  • lastUpdated (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>
}

The useCover hook returns an object with all the same properties and methods as the component's render props.

List All Covers

Use the useCovers hook to retrieve all available cover entities:

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>
)
}

The useCovers hook fetches all cover entities from Home Assistant and returns an array of cover 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>
)
}