Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(select): add select/dropdown component #35

Merged
merged 9 commits into from
Oct 14, 2024
2 changes: 2 additions & 0 deletions src/primevue/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import radioButton from "./radioButton/radioButton";
import autocomplete from "./autocomplete/autocomplete";
import textarea from "./textarea/textarea";
import toast from "./toast/toast";
import select from "./select/select";

import { deDE } from "@/config/locale";

Expand All @@ -34,6 +35,7 @@ export const RisUiTheme = {
textarea,
toast,
autocomplete,
select,
};

export const RisUiLocale = {
Expand Down
7 changes: 7 additions & 0 deletions src/primevue/select/select.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[aria-invalid="true"] {
@apply border-red-800 bg-red-100 outline-red-800;
}

[aria-invalid="true"] + small {
@apply ris-label3-regular mt-2 flex items-center gap-4 text-red-900;
}
133 changes: 133 additions & 0 deletions src/primevue/select/select.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { html } from "@/lib/tags";
import { Meta, StoryObj } from "@storybook/vue3";
import Select from "primevue/select";
hamo225 marked this conversation as resolved.
Show resolved Hide resolved
import { ref } from "vue";
import ErrorOutline from "~icons/material-symbols/error-outline";

const meta: Meta<typeof Select> = {
component: Select,

tags: ["autodocs"],

args: {
placeholder: "Dropdown",
disabled: false,
invalid: false,
},
};

export default meta;

export const Default: StoryObj<typeof meta> = {
render: (args) => ({
components: { Select },
setup() {
const selectedOption = ref();
const options = ref([
{ name: "Text 1", code: "AB" },
{ name: "Text 2", code: "CD" },
{ name: "Text 3", code: "EF" },
{ name: "Text 4", code: "GH" },
{ name: "Text 5", code: "IJ" },
]);
return { args, selectedOption, options };
},
template: html` <select
id="with-top-label"
v-bind="args"
v-model="selectedOption"
optionLabel="name"
:options="options"
/>`,
}),
};

export const WithLabel: StoryObj<typeof meta> = {
args: {
disabled: false,
},
render: (args) => ({
components: { Select },
setup() {
const selectedOption = ref();
const options = ref([
{ name: "Text 1", code: "AB" },
{ name: "Text 2", code: "CD" },
{ name: "Text 3", code: "EF" },
{ name: "Text 4", code: "GH" },
{ name: "Text 5", code: "IJ" },
]);
return { args, selectedOption, options };
},
template: html` <label class="ris-label2-regular" for="with-top-label"
>Label</label
>
<select
id="with-top-label"
v-bind="args"
v-model="selectedOption"
optionLabel="name"
:options="options"
/>`,
}),
};

export const WithHorizontalLabel: StoryObj<typeof meta> = {
render: (args) => ({
components: { Select },
setup() {
const selectedOption = ref();
const options = ref([
{ name: "Text 1", code: "AB" },
{ name: "Text 2", code: "CD" },
{ name: "Text 3", code: "EF" },
{ name: "Text 4", code: "GH" },
{ name: "Text 5", code: "IJ" },
]);
return { args, selectedOption, options };
},
template: html`<div class="flex w-1/2 items-center gap-16">
<label class="ris-label2-regular" for="with-left-label">Label</label>
<select
id="with-left-label"
v-bind="args"
v-model="selectedOption"
optionLabel="name"
:options="options"
/>
</div>`,
}),
};

export const InvalidWithHint: StoryObj<typeof meta> = {
args: {
invalid: true,
"aria-invalid": "true",
},
render: (args) => ({
components: { Select, ErrorOutline },
setup() {
const selectedOption = ref();
const options = ref([
{ name: "Text 1", code: "AB" },
{ name: "Text 2", code: "CD" },
{ name: "Text 3", code: "EF" },
{ name: "Text 4", code: "GH" },
{ name: "Text 5", code: "IJ" },
]);
return { args, selectedOption, options };
},
template: html`
<label class="ris-label2-regular" for="invalid">Dropdown</label>
<select
id="invalid"
aria-describedby="invalid-hint"
v-bind="args"
v-model="selectedOption"
optionLabel="name"
:options="options"
/>
<small id="invalid-hint"> <ErrorOutline /> Invalid date </small>
`,
}),
};
48 changes: 48 additions & 0 deletions src/primevue/select/select.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { SelectPassThroughOptions } from "primevue/select";
hamo225 marked this conversation as resolved.
Show resolved Hide resolved
import { tw } from "@/lib/tags.ts";
import "./select.css";

export const base = tw`ris-body2-regular h-full min-h-48 w-full border-2 border-blue-800 bg-white px-16 py-4 outline-4 -outline-offset-4 outline-blue-800 placeholder:text-gray-600 hover:outline focus:outline disabled:border-blue-500 disabled:bg-white disabled:text-blue-500 disabled:outline-none [&+label]:my-4`;
hamo225 marked this conversation as resolved.
Show resolved Hide resolved

const select: SelectPassThroughOptions = {
root: ({}) => {
hamo225 marked this conversation as resolved.
Show resolved Hide resolved
return {
class: {
[base]: true,
"flex items-center justify-between": true,
},
tabindex: 0,
hamo225 marked this conversation as resolved.
Show resolved Hide resolved
onKeydown: (event: KeyboardEvent) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
const dropdown = event.currentTarget as HTMLElement;
dropdown.click();
}
},
};
},
label: () => {
return {
tabindex: -1,
};
},
list: () => {
const listStyle = tw`shadow-md`;
return {
class: {
hamo225 marked this conversation as resolved.
Show resolved Hide resolved
[listStyle]: true,
},
};
},
option: ({}) => {
const optionStyle = tw`ris-body2-regular relative h-full min-h-48 w-full bg-white px-24 py-16 after:absolute after:bottom-0 after:left-8 after:right-8 after:border-b after:border-gray-300 after:content-[''] last:after:border-b-0 hover:bg-gray-100`;
return {
class: {
[optionStyle]: true,
hamo225 marked this conversation as resolved.
Show resolved Hide resolved
},
tabindex: 0,
};
},
};

export default select;
Loading