Hoppa till huvudinnehåll
Sidopanel, Detaljpanel

Panel

Komponent som används för att kunna visa fördjupande information eller ge plats för sekundära verktyg som till exempel filter, utan att behöva navigera bort från huvudinnehållet. Panelen används som en sekundär yta, inte som en tillfällig dialog, och visas till höger om huvudinnehållet.

import { Layout, LayoutContent, Main, Panel } from '@midas-ds/layout'
import { useState } from 'react'
import { Button } from '@midas-ds/components'

function App() {
const [isOpen, setIsOpen] = useState(false)

return (
<Layout>
<LayoutContent>
<Main>
<Button onPress={() => setIsOpen(true)}>Öppna panel</Button>
</Main>

<Panel
id='detaljer'
title='Detaljer'
isOpen={isOpen}
onOpenChange={setIsOpen}
>
{/* Panelinnehåll */}
</Panel>
</LayoutContent>
</Layout>
)
}

Användning

  • Standardbeteendet för panelBehavior är replace och detta rekommenderas för de flesta fall. Vi vill undvika att en ny panel läggs ovanpå en tidigare panel, eftersom det gör att användaren måste stänga flera paneler efter varandra för att komma till ursprungsläget.

Använd Panel för:

  • Situationer användaren behöver stödjande information eller verktyg utan att lämna huvudinnehållet.

Använd inte Panel för:

  • Navigering eller för innehåll som kräver en egen sida.

Varianter

Komponenten finns i två olika varianter. overlay där panelen lägger sig ovanför huvudinnehållet och push som ligger i samma nivå som huvudinnehållet och trycker ihop innehållet. Välj variant, overaly eller push baserat på vad som fungerar bäst utifrån användningssituationen, innehållshierarkin och användningsflödet.

  • overlay passar bäst när panelens innehåll behöver få tillfälligt fokus jämfört med huvudinnehållet.
  • push passar bäst när panelens innehåll behöver vara tillgängligt under längre tid, i mer ihållande flöden. Det kan dock vara lämpligt att växla till overlay vid smalare brytpunkter som en del i en responsiv design.

Implementation

Panel med egna åtgärder

Använd actions-propen för att lägga till egna knappar i panelens header, till höger om titeln och till vänster om stängknappen.

import { Layout, LayoutContent, Main, Panel } from '@midas-ds/layout'
import { Button } from '@midas-ds/components'
import { Ellipsis } from 'lucide-react'
import { useState } from 'react'

function App() {
const [isOpen, setIsOpen] = useState(false)

return (
<Layout>
<LayoutContent>
<Main>
<Button onPress={() => setIsOpen(true)}>Öppna panel</Button>
</Main>

<Panel
id='detaljer'
title='Detaljer'
isOpen={isOpen}
onOpenChange={setIsOpen}
actions={
<Button
variant='icon'
size='medium'
aria-label='Fler alternativ'
>
<Ellipsis size={20} />
</Button>
}
>
{/* Panelinnehåll */}
</Panel>
</LayoutContent>
</Layout>
)
}

Flera paneler med PanelProvider

När du har flera paneler som kan öppnas och stängas oberoende av varandra, använd PanelProvider och usePanels-hooken.

import { Layout, LayoutContent, Main, PanelProvider, PanelRegion, usePanels } from '@midas-ds/layout'
import { Button } from '@midas-ds/components'

function PanelControls() {
const { addPanel, closePanel } = usePanels()

return (
<>
<Button onPress={() => addPanel({ id: 'panel-a', title: 'Panel A' })}>Öppna Panel A</Button>
<Button onPress={() => addPanel({ id: 'panel-b', title: 'Panel B' })}>Öppna Panel B</Button>
</>
)
}

function App() {
return (
<PanelProvider>
<Layout>
<LayoutContent>
<Main>
<PanelControls />
</Main>
<PanelRegion />
</LayoutContent>
</Layout>
</PanelProvider>
)
}
<PanelProvider panelBehavior='replace'> {/* replace | bring-to-front | pop-to */}

Byt innehåll utan animation

Använd ett stabilt id när du anropar addPanel för att uppdatera panelinnehållet på plats utan att animera om. React känner igen id:t och uppdaterar titel och innehåll direkt.

import { Layout, LayoutContent, Main, PanelProvider, PanelRegion, usePanels } from '@midas-ds/layout'

const items = [
{ id: '1', name: 'Ansökan #1042', status: 'Inlämnad' },
{ id: '2', name: 'Ansökan #1043', status: 'Under granskning' },
{ id: '3', name: 'Ansökan #1044', status: 'Beviljad' },
]

function ItemList() {
const { addPanel } = usePanels()

return (
<ul>
{items.map(item => (
<li key={item.id}>
<button
onClick={() =>
addPanel({
id: 'detail', // same id every time → no re-animation
title: item.name,
children: <p>Status: {item.status}</p>,
})
}
>
{item.name}
</button>
</li>
))}
</ul>
)
}

function App() {
return (
<PanelProvider panelBehavior='replace'>
<Layout>
<LayoutContent>
<Main>
<ItemList />
</Main>
<PanelRegion />
</LayoutContent>
</Layout>
</PanelProvider>
)
}

API

Panel

NameTypeDefaultDescription
id *string-

Required unique id used to manage panel state.

title *string-

Panel title displayed in the header.

isOpen-

Controlled open state.

defaultOpen-

Uncontrolled initial open state.

promoting-
actions-

Custom actions rendered in the panel header, to the right of the title.

PanelProvider

NameTypeDefaultDescription
defaultPanels[]

Panels to open on mount.

panelBehaviorreplace

Behaviour when opening a panel that is already open.

  • replace — Replaces all existing panels. Recommended for most use cases.
  • bring-to-front — Panels stack; opening an existing panel moves it to the front.
  • pop-to — Opening an existing panel closes all panels above it.

Showing one panel at a time is recommended. replace reflects this as the default. Use bring-to-front or pop-to only when multiple simultaneous panels are justified.

panelVariantoverlay

How the panel is displayed relative to the main content.

  • overlay — Panel overlays the main content without affecting its width.
  • push — Panel pushes the main content aside, reducing its available width.

usePanels

Hook för att komma åt PanelContext och hantera panelernas tillstånd programmatiskt.

const { panels, addPanel, closePanel, removePanel } = usePanels()
NameTypeDefaultDescription
panels *PanelItem[]-

The current list of panels.

panelVariant *-

The active panel variant inherited from PanelProvider.

addPanel *(panel: Omit<PanelItem, "isOpen" | "defaultOpen">) => void-

Opens or activates a panel. If a panel with the same id exists, it is updated in place.

closePanel *(id: string) => void-

Closes a panel, triggering the exit animation.

removePanel *(id: string) => void-

Permanently removes a panel from state.

resetPromoting *(id: string) => void-