Käyttötarkoitus
Käytä valintalassoa, kun haluat mahdollistaa esimerkiksi useamman valintaruudun valinnan yhdellä kertaa.
Valintalasso on tarkoitettu käytettäväksi asiantuntijoiden käyttöliittymissä apuvälineenä valintojen teon nopeuttamiseen.
Rajoitukset
- Valintalasso ei toimi pelkällä näppäimistöllä, eikä kosketuslaitteissa.
- Valintalasso estää oletuksena tekstin valitsemisen.
- Jos tekstin valinta on tärkeää, voi valintalasson rajoittaa tietyn elementin sisään tai laittaa sen aktivoitumaan ainoastaan jonkin näppäimen kanssa.
- Interaktiot voi myös palauttaa
preventInteraction
-parametrilla. Tällöin lasso ja tekstin valinta toimivat yhtäaikaa.
Konfigurointi
Valintalassotyökalu koostuu SelectionLasso-komponentista ja useammasta React-hookista:
useSelectionLasso
: Määrittää valintalasson näyttämisen, koon ja sijainnin ruudulla.
useSelectionLassoSelect
: Mahdollistaa kohteiden valinnan valmiiden sääntöjen pohjalta (vapaaehtoinen).
useSelectionLassoScroll
: Mahdollistaa sivun vierittämisen valinnan mukana, kun hiiri siirtyy näytön ylä- tai alareunaan (vapaaehtoinen).
Valintalasson voi siirtää Portal-komponentilla sivun loppuun, jos ympäröivien elementtien tyylimääritykset häiritsevät sen toimintaa.
const { onMouseMove, onMouseUp } = useSelectionLassoScroll({ scrollSpeed: 20, scrollThreshold: 50 });
useSelectionLassoSelect
const { select, onChange } = useSelectionLassoSelect({
selectItem(item) {
item.checked = true;
},
deselectItem(item) {
item.checked = false;
},
multiSelectKey: "Control",
selectableItems,
});
useSelectionLasso
const ref = useRef<HTMLDivElement>(null);
const { props } = useSelectionLasso(ref, {
container: document.documentElement,
enabled: true,
onMouseDown: undefined,
onMouseMove: (e, insideItems, outsideItems) => {
onMouseMove(e);
select(insideItems, outsideItems);
},
onMouseUp,
preventInteraction: true,
root: document.documentElement,
selectableItems,
selectionThreshold: 3,
});
Esimerkit
Valintaruutujen valinta
Useamman erillisen valintaruudun valitseminen onnistuu pitämällä ctrl
-painiketta pohjassa.
function UseSelectionLassoExample() {
const [isLassoEnabled, setIsLassoEnabled] = useState(false);
const selectableItems = useRef<HTMLInputElement[]>([]);
const ref = useRef<HTMLDivElement>(null);
const { onMouseMove, onMouseUp } = useSelectionLassoScroll();
const { select, onChange } = useSelectionLassoSelect({
selectItem(item) {
item.checked = true;
},
deselectItem(item) {
item.checked = false;
},
selectableItems: selectableItems.current,
});
const { props } = useSelectionLasso(ref, {
onMouseUp,
onMouseMove: (e, insideItems, outsideItems) => {
onMouseMove(e);
select(insideItems, outsideItems);
},
selectableItems: selectableItems.current,
enabled: isLassoEnabled,
});
return (
<>
<Button onClick={() => setIsLassoEnabled(!isLassoEnabled)} className="kds-mb-6">
{isLassoEnabled ? "Poista lasso käytöstä" : "Ota lasso käyttöön"}
</Button>
<div>
{[...Array(20)].map((x, i) => (
<Checkbox
key={`checkbox-${i}`}
ref={(el) => (selectableItems.current[i] = el)}
labelText={`Valinta ${i + 1}`}
onChange={() => onChange(selectableItems.current[i], selectableItems.current[i].checked)}
/>
))}
</div>
<Portal>
<SelectionLasso ref={ref} {...props} />
</Portal>
</>
);
}
Taulukon rivien valinta
Esimerkki taulukon rivien valinnasta. Useamman erillisen valintaruudun valitseminen onnistuu pitämällä ctrl
-painiketta pohjassa.
function UseSelectionLassoExample() {
const [rowAmount, setRowAmount] = useState(20);
const [isLassoEnabled, setIsLassoEnabled] = useState(false);
const selectableItems = useRef<HTMLInputElement[]>([]);
const ref = useRef<HTMLDivElement>(null);
const {
isToggleOn: isSelected,
flipToggle: toggleSelect,
flipAll: toggleAllSelected,
setToggleOn,
setToggleOff,
} = useToggle();
const { onMouseMove, onMouseUp } = useSelectionLassoScroll();
const { select, onChange } = useSelectionLassoSelect({
selectItem(item) {
setToggleOn(`row-${selectableItems.current.indexOf(item)}`);
},
deselectItem(item) {
setToggleOff(`row-${selectableItems.current.indexOf(item)}`);
},
selectableItems: selectableItems.current,
});
const { props } = useSelectionLasso(ref, {
onMouseUp,
onMouseMove: (e, insideItems, outsideItems) => {
onMouseMove(e);
select(insideItems, outsideItems);
},
selectableItems: selectableItems.current,
enabled: isLassoEnabled,
});
const rows = [...Array(rowAmount)].map((x, i) => `row-${i}`);
const allRows = ["row-select-all", ...rows];
const handleToggle = (index, key, isSelected) => {
toggleSelect(key);
onChange(selectableItems.current[index], isSelected);
};
const handleToggleAll = () => {
toggleAllSelected(allRows);
selectableItems.current.forEach((row) => {
onChange(row, !row.checked);
});
};
return (
<>
<ButtonGroup className="kds-mb-6" horizontal>
<Button onClick={() => setIsLassoEnabled(!isLassoEnabled)}>
{isLassoEnabled ? "Poista lasso käytöstä" : "Ota lasso käyttöön"}
</Button>
<Button onClick={() => setRowAmount(rowAmount + 10)} appearance="outline">
Lisää rivejä
</Button>
</ButtonGroup>
<Table>
<TableHead>
<TableHeadRow
isSelected={isSelected("row-select-all")}
selectLabel="Valitse kaikki rivit"
selectOnChange={handleToggleAll}
>
<TableHeader scope="col">Lorem</TableHeader>
<TableHeader scope="col">Ipsum</TableHeader>
<TableHeader scope="col">Dolor</TableHeader>
</TableHeadRow>
</TableHead>
<TableBody>
{rows.map((key, i) => (
<TableRow
checkbox
isSelected={isSelected(key)}
key={key}
selectLabel="Valitse rivi"
selectOnChange={() => handleToggle(i, key, !isSelected(key))}
ref={(el) => (selectableItems.current[i] = el)}
>
<TableCell>Rivi {i + 1}</TableCell>
<TableCell>Ipsum</TableCell>
<TableCell>Dolor</TableCell>
</TableRow>
))}
</TableBody>
</Table>
<Portal>
<SelectionLasso ref={ref} {...props} />
</Portal>
</>
);
}
Valintalasson rajoittaminen tietyn elementin sisään
Esimerkissä valintalasso aktivoituu pitämällä ctrl
-painiketta pohjassa. Useampien valintojen tekeminen tapahtuu ctrl
- ja alt
-painikkeilla.
Valintalasso on myös asetettu valitsemaan ainoastaan valintaruutuja ympäröivän elementin sisällä root
- ja container
-parametrien avulla.
root
-parametri asettaa elementin, jonka sisällä muiden elementtien interaktiot estetään lasson ollessa aktiivisena (esimerkiksi tekstin valinta, hover-efektit).
container
-parametri asettaa valintalasson aktivoitumaan ja valitsemaan vain annetun HTML-elementin sisällä.
function UseSelectionLassoExample() {
const [isLassoEnabled, setIsLassoEnabled] = useState(false);
const selectableItems = useRef<HTMLInputElement[]>([]);
const containerRef = useRef<HTMLDivElement>(null);
const ref = useRef<HTMLDivElement>(null);
const { select, onChange } = useSelectionLassoSelect({
selectItem(item) {
item.checked = true;
},
deselectItem(item) {
item.checked = false;
},
multiSelectKey: ["Control", "Alt"],
selectableItems: selectableItems.current,
});
const { props } = useSelectionLasso(ref, {
root: containerRef.current,
container: containerRef.current,
onMouseMove: (e, insideItems, outsideItems) => {
select(insideItems, outsideItems);
},
selectableItems: selectableItems.current,
enabled: isLassoEnabled,
});
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === "Control" && !isLassoEnabled) {
setIsLassoEnabled(true);
}
};
const handleKeyUp = (e: KeyboardEvent) => {
if (e.key === "Control" && isLassoEnabled) {
setIsLassoEnabled(false);
}
};
window.addEventListener("keydown", handleKeyDown);
window.addEventListener("keyup", handleKeyUp);
return () => {
window.removeEventListener("keydown", handleKeyDown);
window.removeEventListener("keyup", handleKeyUp);
};
}, [isLassoEnabled]);
return (
<>
<div ref={containerRef} className="kds--m-4 sm:kds--m-6 kds-p-4 sm:kds-p-6">
{[...Array(20)].map((x, i) => (
<Checkbox
key={`checkbox-${i}`}
ref={(el) => (selectableItems.current[i] = el)}
labelText={`Valinta ${i + 1}`}
onChange={() => onChange(selectableItems.current[i], selectableItems.current[i].checked)}
/>
))}
</div>
<SelectionLasso ref={ref} {...props} />
</>
);
}
Huomioitavaa selaintuessa