ui/select machines/tags: add custom combobox
This just renders machines and tags as chips onclick will open another combobox
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
.dummybg {
|
||||||
|
padding: 1rem;
|
||||||
|
width: 20rem;
|
||||||
|
min-height: 10rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #2e4a4b;
|
||||||
|
background:
|
||||||
|
linear-gradient(0deg, rgba(0, 0, 0, 0.18) 0%, rgba(0, 0, 0, 0.18) 100%),
|
||||||
|
linear-gradient(
|
||||||
|
180deg,
|
||||||
|
var(--clr-bg-inv-3, rgba(46, 74, 75, 0.79)) 0%,
|
||||||
|
var(--clr-bg-inv-4, rgba(32, 54, 55, 0.79)) 100%
|
||||||
|
);
|
||||||
|
box-shadow:
|
||||||
|
0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
||||||
|
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trigger {
|
||||||
|
@apply rounded-md bg-inv-4 w-full min-h-11;
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&:hover {
|
||||||
|
@apply outline outline-def-1 outline-1;
|
||||||
|
background:
|
||||||
|
linear-gradient(
|
||||||
|
90deg,
|
||||||
|
var(--clr-bg-inv-acc-3, #2c4347) 0%,
|
||||||
|
var(--clr-bg-inv-acc-2, #4f747a) 100%
|
||||||
|
),
|
||||||
|
var(--clr-bg-inv-4, #203637);
|
||||||
|
box-shadow: 0 0 0 2px var(--clr-bg-inv-acc-4, #162324) inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
@apply bg-inv-acc-4;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { Meta, StoryObj } from "@kachurun/storybook-solid";
|
||||||
|
|
||||||
|
import { SelectStepper, SelectStepperProps } from "./SelectStepper";
|
||||||
|
import { Tag } from "../Tag/Tag";
|
||||||
|
import Icon from "../Icon/Icon";
|
||||||
|
|
||||||
|
const meta = {
|
||||||
|
title: "Components/Custom/SelectStepper",
|
||||||
|
component: SelectStepper,
|
||||||
|
} satisfies Meta<SelectStepperProps<string>>;
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<SelectStepperProps<string>>;
|
||||||
|
|
||||||
|
const Item = (item: string) => (
|
||||||
|
<Tag
|
||||||
|
inverted
|
||||||
|
icon={(tag) => (
|
||||||
|
<Icon icon={"Machine"} size="0.5rem" inverted={tag.inverted} />
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{item}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
renderItem: Item,
|
||||||
|
values: ["foo", "bar"],
|
||||||
|
options: ["foo", "bar", "baz", "qux", "quux"],
|
||||||
|
onChange: (values: string[]) => {
|
||||||
|
console.log("Selected values:", values);
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
console.log("Combobox clicked");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
71
pkgs/clan-app/ui/src/components/Search/SelectStepper.tsx
Normal file
71
pkgs/clan-app/ui/src/components/Search/SelectStepper.tsx
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import Icon from "../Icon/Icon";
|
||||||
|
import { Typography } from "../Typography/Typography";
|
||||||
|
import { For, JSX, Show } from "solid-js";
|
||||||
|
import styles from "./SelectStepper.module.css";
|
||||||
|
import { Combobox } from "@kobalte/core/combobox";
|
||||||
|
import { Button } from "../Button/Button";
|
||||||
|
|
||||||
|
export interface SelectStepperProps<T> {
|
||||||
|
// Define any props needed for the SelectStepper component
|
||||||
|
values: T[];
|
||||||
|
options: T[];
|
||||||
|
onChange: (values: T[]) => void;
|
||||||
|
onClick: () => void;
|
||||||
|
renderItem: (item: T) => JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SelectStepper<T>(props: SelectStepperProps<T>) {
|
||||||
|
return (
|
||||||
|
<div class={styles.dummybg}>
|
||||||
|
<div class="flex flex-col gap-1.5">
|
||||||
|
<div class="flex w-full items-center gap-2 px-1.5">
|
||||||
|
<Typography
|
||||||
|
hierarchy="body"
|
||||||
|
weight="medium"
|
||||||
|
class="flex gap-2 uppercase"
|
||||||
|
size="s"
|
||||||
|
inverted
|
||||||
|
color="secondary"
|
||||||
|
>
|
||||||
|
Servers
|
||||||
|
</Typography>
|
||||||
|
<Icon icon="Info" color="tertiary" inverted />
|
||||||
|
<Button icon="Settings" hierarchy="primary" ghost class="ml-auto" />
|
||||||
|
</div>
|
||||||
|
<Combobox<T>
|
||||||
|
multiple
|
||||||
|
value={props.values}
|
||||||
|
onChange={props.onChange}
|
||||||
|
options={props.options}
|
||||||
|
allowsEmptyCollection
|
||||||
|
class="w-full"
|
||||||
|
>
|
||||||
|
<Combobox.Control<T> aria-label="Fruits">
|
||||||
|
{(state) => (
|
||||||
|
<Combobox.Trigger
|
||||||
|
tabIndex={1}
|
||||||
|
class={styles.trigger}
|
||||||
|
onClick={props.onClick}
|
||||||
|
>
|
||||||
|
<div class="flex flex-wrap items-center gap-2 px-2 py-3">
|
||||||
|
<Icon icon="Search" color="quaternary" inverted />
|
||||||
|
<Show when={state.selectedOptions().length === 0}>
|
||||||
|
<Typography
|
||||||
|
color="tertiary"
|
||||||
|
inverted
|
||||||
|
hierarchy="body"
|
||||||
|
size="s"
|
||||||
|
>
|
||||||
|
Select
|
||||||
|
</Typography>
|
||||||
|
</Show>
|
||||||
|
<For each={state.selectedOptions()}>{props.renderItem}</For>
|
||||||
|
</div>
|
||||||
|
</Combobox.Trigger>
|
||||||
|
)}
|
||||||
|
</Combobox.Control>
|
||||||
|
</Combobox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user