LegacyMenuItem

Draggable

Example

Live demo

Loading...

Code

import { type DragEvent, useCallback, useState } from "react"
import { LegacyMenuItem as MenuItem, type LegacyMenuItemProps } from "blue-react"

export default function MenuItemExample() {
    const bodyMenuItemProps: LegacyMenuItemProps = {
        className: "w-100",
        labelClassName: "d-inline-block",
        caretClassName: "d-inline-block"
    }

    const [itemIDs, setItemIDs] = useState(["1", "2", "3", "4", "5"])

    const dragStart = useCallback((event: DragEvent) => {
        const target = event.target as HTMLElement
        event.dataTransfer.setData("text/plain", target.id)
    }, [])

    const drop = useCallback(
        (event: DragEvent) => {
            event.preventDefault()

            const draggedId = event.dataTransfer.getData("text")
            const dropTargetId = (event.target as HTMLElement).id

            const draggedIndex = itemIDs.indexOf(draggedId)
            const dropTargetIndex = itemIDs.indexOf(dropTargetId)

            const newItemIDs = [...itemIDs]
            newItemIDs.splice(draggedIndex, 1)
            newItemIDs.splice(dropTargetIndex, 0, draggedId)

            setItemIDs(newItemIDs)
        },
        [itemIDs]
    )

    const dragOver = useCallback((event: DragEvent) => {
        event.preventDefault()
    }, [])

    return (
        <>
            <p>
                <strong>Important:</strong> To make draggable menu items work in Firefox, the <code>elementType</code>{" "}
                must not be <code>"button"</code>. Set it to something else, like <code>"div"</code>.
            </p>
            <div onDrop={drop} onDragOver={dragOver}>
                {itemIDs.map((id) => (
                    <MenuItem
                        {...bodyMenuItemProps}
                        elementType={"div"}
                        key={id}
                        id={id}
                        draggable
                        onDragStart={dragStart}
                        onDragOver={dragOver}
                        label={`Item ${id}`}
                    />
                ))}
            </div>
        </>
    )
}

Example

Live demo

Loading...

Code

import { useState } from "react"
import { MenuItem } from "blue-react"
import { SidebarMenu } from "blue-react"

export default function MenuItemExample() {
    const [navigationSource, setNavigationSource] = useState<"user" | "default">("default")

    return (
        <div className="bg-primary position-relative">
            <SidebarMenu sidebarClass="position-static shadow-none overflow-visible" menuClass="overflow-visible">
                <div className="blue-sidebar-visible-on-open blue-sidebar-menu-horizontal-on-open">
                    <MenuItem
                        label="Default"
                        labelClassName="text-center w-100"
                        onClick={() => setNavigationSource("default")}
                        isActive={navigationSource === "default"}
                    />

                    <MenuItem
                        label="User"
                        labelClassName="text-center w-100"
                        onClick={() => setNavigationSource("user")}
                        isActive={navigationSource === "user"}
                    />
                </div>
            </SidebarMenu>
            <p className="p-3 bg-body">Resize the browser to see how the sidebar and its items behave.</p>
        </div>
    )
}

Example

Live demo

Loading...

Code

import { MenuItem } from "blue-react"
import { SidebarMenu } from "blue-react"
import { BoxArrowLeft, House } from "react-bootstrap-icons"
import { IconMenuItem } from "blue-react"
import { useState } from "react"

export default function MenuItemExample() {
    const [showDropdown, setShowDropdown] = useState(false)

    return (
        <div className="bg-primary position-relative">
            <SidebarMenu
                sidebarClass="position-static shadow-none overflow-visible"
                menuClass="overflow-visible"
                topContent={
                    <>
                        <div className="d-flex blue-sidebar-menu-horizontal-on-open">
                            <MenuItem
                                href="#home"
                                label="Home"
                                icon={<House className="bi" />}
                                labelClassName="text-center w-100"
                            />
                            <div className="position-relative">
                                <IconMenuItem
                                    title="More"
                                    supportOutside
                                    showDropdown={showDropdown}
                                    onShowDropdown={setShowDropdown}
                                    labelClassName="text-center w-100"
                                    dropdownClassName="position-absolute z-3 end-0 blue-sidebar-menu-vertical-on-open"
                                >
                                    <div
                                        onClick={() => {
                                            setShowDropdown(false)
                                        }}
                                    >
                                        <MenuItem label="Sign out" icon={<BoxArrowLeft className="bi" />} />
                                    </div>
                                </IconMenuItem>
                            </div>
                        </div>
                    </>
                }
            />
            <p className="p-3 bg-body">Resize the browser to see how the sidebar and its items behave.</p>
        </div>
    )
}

Sidebar

Example

Live demo

Loading...

Code

import { MenuItem } from "blue-react"
import { SidebarMenu } from "blue-react"

export default function MenuItemExample() {
    return (
        <div className="bg-primary position-relative">
            <SidebarMenu sidebarClass="position-static shadow-none overflow-visible" menuClass="overflow-visible">
                <MenuItem icon={<span>😅</span>} label="Hello World" />
                <MenuItem
                    icon={<span style={{ transform: "scale(-1, 1)" }}>👀</span>}
                    label="Click to see sub items"
                    supportOutside
                >
                    <MenuItem label="I am a child, hi" />
                    <MenuItem label="Second child">
                        <MenuItem label="Even more nested" />
                    </MenuItem>
                </MenuItem>
            </SidebarMenu>
            <p className="p-3 bg-body">Resize the browser to see how the sidebar and its items behave.</p>
        </div>
    )
}

Usage in body

Example

Live demo

Loading...

Code

import { LegacyMenuItem as MenuItem, type LegacyMenuItemProps } from "blue-react"
import { EmojiHeartEyesFill } from "react-bootstrap-icons"

export default function MenuItemExample() {
    const bodyMenuItemProps: LegacyMenuItemProps = {
        className: "w-100",
        labelClassName: "d-inline-block",
        caretClassName: "d-inline-block"
    }

    return (
        <>
            <p>Usage in body without sidebar or action bar</p>

            <div className="d-flex flex-column flex-md-row gap-3 w-100">
                <article className="flex-fill">
                    <h4 className="mt-4 mb-3">Single menu item</h4>
                    <MenuItem {...bodyMenuItemProps} icon={<EmojiHeartEyesFill />} label="John Boy" />
                </article>

                <article className="flex-fill">
                    <h4 className="mt-4 mb-3">Dropdown</h4>
                    <MenuItem {...bodyMenuItemProps} icon={<EmojiHeartEyesFill />} label="John Boy">
                        <MenuItem {...bodyMenuItemProps} icon={<EmojiHeartEyesFill />} label="I am a child item" />
                    </MenuItem>
                </article>

                <article className="flex-fill">
                    <h4 className="mt-4 mb-3">Split dropdown</h4>
                    <div
                        className="d-grid w-100"
                        style={{
                            gridTemplateAreas: '"a b" "c c"',
                            gridTemplateColumns: "minmax(auto, calc(100% - 3rem)) 3rem"
                        }}
                    >
                        <MenuItem
                            {...bodyMenuItemProps}
                            style={{ gridArea: "a" }}
                            icon={<EmojiHeartEyesFill />}
                            label="John Boy"
                        />
                        <MenuItem
                            {...bodyMenuItemProps}
                            style={{ gridArea: "b" }}
                            dropdownStyle={{ gridArea: "c" }}
                            supportOutside
                        >
                            <MenuItem {...bodyMenuItemProps} icon={<EmojiHeartEyesFill />} label="I am a child item" />
                        </MenuItem>
                    </div>
                </article>
            </div>
        </>
    )
}
Name Description Type Default