import { useState } from "react"; import { HvInput, HvOption, HvSelect } from "@hitachivantara/uikit-react-core"; export default function Demo() { const [selectedCountry, setSelectedCountry] = useState("Portugal"); const [formattedPhoneNumber, setFormattedPhoneNumber] = useState(""); return ( <HvInput label="Dropdown prefix" className="w-300px" onChange={(_, value) => { setFormattedPhoneNumber( countries.find((c) => c.label === selectedCountry)?.format(value) || "", ); }} value={formattedPhoneNumber} startAdornment={ <HvSelect value={selectedCountry} variant="secondaryGhost" classes={{ root: "w-100px! border-r-1! border-r-border! rounded-none!", select: "font-normal border-none! rounded-none!", }} onChange={(evt, val) => { setSelectedCountry(val || ""); }} enablePortal > {countries.map((country) => ( <HvOption key={country.label} value={country.label}> {country.flag} {country.code} </HvOption> ))} </HvSelect> } /> ); } function format(value: string) { // Apply formatting pattern: "XX XXX XX XX" return value .replace(/\D/g, "") .slice(0, 9) .replace(/(\d{2})(\d{3})?(\d{2})?(\d{2})?/, (match, p1, p2, p3, p4) => { return [p1, p2, p3, p4].filter(Boolean).join(" "); }); } const countries = [ { flag: "🇮🇳", format, code: "+91", label: "India" }, { flag: "🇵🇹", format, code: "+351", label: "Portugal" }, { flag: "🇬🇧", format, code: "+44", label: "United Kingdom" }, { flag: "🇺🇸", format, code: "+1", label: "United States" }, ];
import { useRef, useState } from "react"; import { HvAdornment, HvInput } from "@hitachivantara/uikit-react-core"; import { Copy, Success } from "@hitachivantara/uikit-react-icons"; export default function Demo() { const [copied, setCopied] = useState(false); const inputRef = useRef<HTMLInputElement>(null); const handleCopy = () => { navigator.clipboard.writeText(inputRef.current?.value || ""); setCopied(true); setTimeout(() => { setCopied(false); }, 1000); }; return ( <HvInput label="Copy to clipboard" ref={inputRef} className="w-300px" defaultValue={"Copy this text"} endAdornment={ <HvAdornment icon={ <> <Success color="positive" className={`transition-all ${copied ? "scale-100 opacity-100" : "scale-0 opacity-0"}`} /> <Copy className={`absolute transition-all ${copied ? "scale-0 opacity-0" : "scale-100 opacity-100"}`} /> </> } onClick={handleCopy} /> } /> ); }
Select colors
import { useRef, useState } from "react"; import { flushSync } from "react-dom"; import { HvBaseDropdown, HvLabel, HvPanel, HvTag, } from "@hitachivantara/uikit-react-core"; const colors = [ "Blue", "Red", "Green", "Yellow", "Purple", "White", "Black", "Orange", "Pink", "Brown", "Gray", "Cyan", "Magenta", "Lime", "Teal", "Lavender", ]; export default function Demo() { const containerRef = useRef<HTMLDivElement>(null); const focusTarget = useRef<HTMLDivElement>(null); const [selectedColors, setSelectedColors] = useState<string[]>([]); const scrollToEnd = () => { containerRef.current?.scrollTo({ left: containerRef.current.scrollWidth, behavior: "smooth", }); }; const handleAddColor = (color: string) => { flushSync(() => { setSelectedColors((prev) => [...prev.filter((c) => c !== color), color]); }); scrollToEnd(); }; const handleRemoveColor = (color: string) => { flushSync(() => { setSelectedColors((prev) => prev.filter((c) => c !== color)); }); scrollToEnd(); }; return ( <div className="w-300px"> <HvLabel label="Tags dropdown input" id="tags-dropdown-input" showGutter /> <HvBaseDropdown aria-labelledby="tags-dropdown-input" onContainerCreation={() => focusTarget.current?.focus()} placeholder={ selectedColors.length ? ( <div className="flex gap-xs overflow-scroll px-1px h-full items-center" ref={containerRef} > {selectedColors.map((color) => ( <HvTag key={color} label={color} onDelete={() => handleRemoveColor(color)} /> ))} </div> ) : ( "Select colors" ) } > <div ref={focusTarget} tabIndex={-1} /> <HvPanel className="flex gap-xs flex-wrap"> {colors .filter((color) => !selectedColors.includes(color)) .map((color) => ( <HvTag key={color} label={color} onClick={() => handleAddColor(color)} /> ))} </HvPanel> </HvBaseDropdown> </div> ); }
import { useEffect, useRef, useState } from "react"; import { ClickAwayListener, Popper } from "@mui/material"; import { HvAdornment, HvPanel, HvTag, HvTagsInput, HvTypography, } from "@hitachivantara/uikit-react-core"; import { DropDownXS } from "@hitachivantara/uikit-react-icons"; const colors = [ "Blue", "Red", "Green", "Yellow", "Purple", "White", "Black", "Orange", "Pink", "Brown", "Gray", "Cyan", "Magenta", "Lime", "Teal", "Lavender", ]; const lastUsed = ["Blue", "Red", "Green"]; export default function Demo() { const containerRef = useRef<HTMLDivElement>(null); const [selectedColors, setSelectedColors] = useState<string[]>([]); const [open, setOpen] = useState(false); useEffect(() => { if (containerRef.current) { containerRef.current.scrollLeft = containerRef.current.scrollWidth; } }, [selectedColors]); const handleAddColor = (color: string) => { setSelectedColors((prev) => { const newColors = prev.filter((c) => c !== color); return newColors.length ? [...newColors, color] : [color]; }); }; const handleRemoveColor = (color: string) => { setSelectedColors((prev) => prev.filter((c) => c !== color)); }; return ( <div className="w-300px"> <HvTagsInput label="Tags with suggestions" ref={containerRef} onChange={(event, value) => { setSelectedColors( value.map((v) => (typeof v === "string" ? v : (v.label as string))), ); }} onDelete={(_, value) => { handleRemoveColor(value as string); }} value={selectedColors} commitTagOn={["Comma", "Enter"]} endAdornment={ <HvAdornment tabIndex={0} icon={<DropDownXS rotate={open} size="xs" />} onClick={() => setOpen((o) => !o)} /> } classes={{ tagsList: "h-32px pr-0! overflow-hidden", }} /> <Popper anchorEl={containerRef.current} open={open} placement="bottom-start" > <ClickAwayListener onClickAway={() => setOpen(false)}> <HvPanel className="grid gap-xs w-300px my-2px border rounded-large"> <HvTypography variant="caption1">Last Used:</HvTypography> <div className="flex gap-xs"> {lastUsed.map((color, idx) => ( <HvTag autoFocus={idx === 0} key={color} label={color} onClick={() => handleAddColor(color)} /> ))} </div> <HvTypography variant="caption1">More colors:</HvTypography> <div className="flex flex-wrap gap-xs"> {colors .filter( (color) => !selectedColors.includes(color) && !lastUsed.includes(color), ) .map((color) => ( <HvTag key={color} label={color} onClick={() => handleAddColor(color)} /> ))} </div> </HvPanel> </ClickAwayListener> </Popper> </div> ); }
import { useState } from "react"; import { ClickAwayListener, Popper } from "@mui/material"; import { HvAdornment, HvInput, HvPanel, HvTag, HvTypography, } from "@hitachivantara/uikit-react-core"; import { Add } from "@hitachivantara/uikit-react-icons"; const colors = [ "Blue", "Red", "Green", "Yellow", "Purple", "White", "Black", "Orange", "Pink", "Brown", "Gray", "Cyan", "Magenta", "Lime", "Teal", "Lavender", ]; export default function Demo() { const [anchorEl, setAnchorEl] = useState<HTMLElement>(); const [selectedColors, setSelectedColors] = useState<string[]>([]); const open = Boolean(anchorEl); const handleAddColor = (color: string) => { setSelectedColors((prev) => [...new Set([...prev, color])]); }; const handleRemoveColor = (color: string) => { setSelectedColors((prev) => prev.filter((c) => c !== color)); }; return ( <> <div className="w-300px"> <HvInput label="Tags with suggestions and empty input" onEnter={(event, value) => { handleAddColor(value); }} startAdornment={ <HvAdornment tabIndex={0} icon={<Add rotate={open} size="xs" />} onClick={(evt) => setAnchorEl(evt.currentTarget)} /> } className="mb-sm" /> <Popper anchorEl={anchorEl} open={open} placement="bottom-start"> <ClickAwayListener onClickAway={() => setAnchorEl(undefined)}> <HvPanel className="grid gap-xs w-300px my-2px border rounded-large"> <HvTypography variant="caption1">More colors:</HvTypography> <div className="flex flex-wrap gap-xs"> {colors .filter((color) => !selectedColors.includes(color)) .map((color) => ( <HvTag key={color} label={color} onClick={() => handleAddColor(color)} /> ))} </div> </HvPanel> </ClickAwayListener> </Popper> </div> <div className="flex flex-wrap gap-xs"> {selectedColors.map((color) => ( <HvTag key={color} label={color} onDelete={() => handleRemoveColor(color)} /> ))} </div> </> ); }
Name:John Doe
import { useRef, useState } from "react"; import { HvBaseInput, HvButton, HvIconButton, HvTypography, } from "@hitachivantara/uikit-react-core"; import { Check, Close, Edit } from "@hitachivantara/uikit-react-icons"; export default function Demo() { const [editing, setEditing] = useState(false); const inputRef = useRef<HTMLInputElement>(null); const [cachedValue, setCachedValue] = useState("John Doe"); return editing ? ( <form className="flex items-center gap-xs w-260px" onSubmit={(evt) => { evt.preventDefault(); setCachedValue(inputRef.current?.value || ""); setEditing(false); }} onReset={() => setEditing(false)} > <HvBaseInput ref={inputRef} autoFocus defaultValue={cachedValue} /> <HvIconButton type="reset" size="xs" variant="negative" title="Cancel"> <Close /> </HvIconButton> <HvIconButton type="submit" size="xs" variant="positive" title="Save"> <Check /> </HvIconButton> </form> ) : ( <div className="flex items-center gap-xs w-260px"> <span className="capitalize">Name:</span> <HvTypography variant="label">{cachedValue}</HvTypography> <HvButton icon title="Edit" onClick={() => setEditing(true)}> <Edit /> </HvButton> </div> ); }
import { HvFormElement, HvInput, HvLabel, } from "@hitachivantara/uikit-react-core"; export default function Demo() { return ( <HvFormElement required className="flex gap-xs"> <HvLabel label="Name" htmlFor="username-input" className="h-fit mt-5px" /> <HvInput id="username" className="w-300px" required /> </HvFormElement> ); }