Skip to content

Commit

Permalink
feat: add primary and secondary button (#4)
Browse files Browse the repository at this point in the history
* feat: add primary and secondary button

* feat: refactor and prettier run

* chore: fix prettier + tailwind plugin setup

Signed-off-by: Raphael Arce <[email protected]>

* feat: add icons and chat box button

* feat: add disabled state to secondary and chatbox button

* fix: prettier error

* feat: add icon button and cleanup

* feat: added sidebard and new chat icon

* feat: change file names to component names

* feat: update imports

---------

Signed-off-by: Raphael Arce <[email protected]>
Co-authored-by: Raphael Arce <[email protected]>
  • Loading branch information
aeschi and raphael-arce authored Jul 23, 2024
1 parent 0ac892e commit f2fbfb1
Show file tree
Hide file tree
Showing 15 changed files with 310 additions and 2 deletions.
5 changes: 5 additions & 0 deletions prettier.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import technologiestiftung from "@technologiestiftung/prettier-config";
import { fileURLToPath } from "node:url";
import { dirname, resolve } from "node:path";

const __dirname = dirname(fileURLToPath(import.meta.url));

// eslint-disable-next-line @technologiestiftung/no-default-export
export default {
...technologiestiftung,
plugins: ["prettier-plugin-tailwindcss"],
tailwindConfig: resolve(__dirname, "./tailwind.config.js"),
};
46 changes: 45 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
import { SendIcon } from "./components/icons/send-icon";
import { PrimaryButton } from "./components/buttons/primary-button";
import { SecondaryButton } from "./components/buttons/secondary-button";
import { ChatBoxButton } from "./components/buttons/chat-box-button";
import { ChatIcon } from "./components/icons/chat-icon";
import { IconButton } from "./components/buttons/icon-button";
import { SidebarIcon } from "./components/icons/sidebar-icon";
import { NewChatIcon } from "./components/icons/new-chat-icon";

export function App() {
return <h1>BärGPT - KI Testumgebung</h1>;
return (
<div className="p-4 font-arial">
<h1 aria-label="button">BärGPT - KI Testumgebung</h1>
<PrimaryButton
label={
<div className="flex flex-row items-center gap-2">
<SendIcon />
Senden
</div>
}
ariaLabel="Nachricht abschicken"
/>
<SecondaryButton label="E–Mail Hilfe" ariaLabel="E–Mail Hilfe" />
<ChatBoxButton
icon={<ChatIcon />}
label={
<div>
Erkläre mir was ich mit <b>BärGPT</b> machen kann.
</div>
}
ariaLabel="Erkläre mir was ich mit BärGPT machen kann."
/>
<IconButton
isOutlineVisible={true}
icon={<SidebarIcon />}
ariaLabel="Seitenleiste anzeigen"
title="Seitenleiste anzeigen"
/>
<IconButton
isOutlineVisible={false}
icon={<NewChatIcon />}
ariaLabel="Neuen Chat starten"
title="Neuen Chat starten"
/>
</div>
);
}
13 changes: 13 additions & 0 deletions src/components/buttons/button-types.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";

export interface ButtonProps {
label?: string | React.ReactNode;
onClick?: () => void;
disabled?: boolean;
type?: "button" | "submit";
ariaLabel?: string;
title?: string;
isLoading?: boolean;
icon?: React.ReactNode;
isOutlineVisible?: boolean;
}
28 changes: 28 additions & 0 deletions src/components/buttons/chat-box-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from "react";
import { ButtonProps } from "./button-types";

export const ChatBoxButton: React.FC<ButtonProps> = ({
label,
onClick,
disabled,
type = "button",
ariaLabel,
title,
icon,
}) => {
return (
<button
className={`text-md my-2 flex h-fit w-fit items-center justify-center rounded bg-white px-4 py-6 font-normal text-dark-blue outline outline-1 outline-mid-grey hover:bg-light-grey active:bg-white disabled:bg-white disabled:font-normal disabled:text-mid-grey`}
disabled={disabled}
onClick={onClick}
type={type}
aria-label={ariaLabel}
title={title}
>
<div className="flex w-[180px] flex-col items-start gap-3 pb-2">
<div> {icon} </div>
<div className="text-md text-start">{label}</div>
</div>
</button>
);
};
25 changes: 25 additions & 0 deletions src/components/buttons/icon-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from "react";
import { ButtonProps } from "./button-types";

export const IconButton: React.FC<ButtonProps> = ({
onClick,
disabled,
type = "button",
ariaLabel,
title,
icon,
isOutlineVisible = true,
}) => {
return (
<button
className={`${isOutlineVisible ? "outline-mid-grey" : "outline-white"} my-2 flex h-[34px] w-[34px] items-center justify-center rounded bg-white p-4 text-dark-blue outline outline-1 outline-mid-grey hover:bg-light-grey hover:outline-mid-grey active:bg-white disabled:bg-white disabled:text-mid-grey`}
disabled={disabled}
onClick={onClick}
type={type}
aria-label={ariaLabel}
title={title}
>
<div> {icon} </div>
</button>
);
};
24 changes: 24 additions & 0 deletions src/components/buttons/primary-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from "react";
import { ButtonProps } from "./button-types";

export const PrimaryButton: React.FC<ButtonProps> = ({
label,
onClick,
disabled,
type = "button",
ariaLabel,
title,
}) => {
return (
<button
className={`my-2 flex min-h-[35px] w-fit items-center justify-center rounded bg-dark-blue px-3 text-sm font-semibold text-white outline-mid-grey hover:bg-light-blue hover:text-dark-blue active:bg-white active:font-normal active:text-dark-blue active:outline active:outline-1 disabled:bg-light-grey disabled:font-normal disabled:text-dark-grey disabled:active:outline-none`}
disabled={disabled}
onClick={onClick}
type={type}
aria-label={ariaLabel}
title={title}
>
<span>{label}</span>
</button>
);
};
24 changes: 24 additions & 0 deletions src/components/buttons/secondary-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from "react";
import { ButtonProps } from "./button-types";

export const SecondaryButton: React.FC<ButtonProps> = ({
label,
onClick,
disabled,
type = "button",
ariaLabel,
title,
}) => {
return (
<button
className={`my-2 flex min-h-[35px] w-fit items-center justify-center rounded bg-white px-3 text-sm font-normal text-dark-blue outline outline-1 outline-mid-grey hover:bg-light-grey active:bg-white active:font-semibold disabled:bg-white disabled:font-normal disabled:text-mid-grey`}
disabled={disabled}
onClick={onClick}
type={type}
aria-label={ariaLabel}
title={title}
>
<span>{label}</span>
</button>
);
};
23 changes: 23 additions & 0 deletions src/components/icons/chat-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";

export const ChatIcon: React.FC = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="23"
height="23"
viewBox="0 0 23 23"
fill="none"
>
<g clipPath="url(#clip0_92_916)">
<path
d="M2.875 0C1.28926 0 0 1.28926 0 2.875V15.8125C0 17.3982 1.28926 18.6875 2.875 18.6875H7.1875V22.2813C7.1875 22.5553 7.34023 22.8023 7.58281 22.9236C7.82539 23.0449 8.11738 23.018 8.3375 22.8563L13.8943 18.6875H20.125C21.7107 18.6875 23 17.3982 23 15.8125V2.875C23 1.28926 21.7107 0 20.125 0H2.875Z"
fill="#9185BE"
/>
</g>
<defs>
<clipPath id="clip0_92_916">
<rect width="23" height="23" fill="white" />
</clipPath>
</defs>
</svg>
);
23 changes: 23 additions & 0 deletions src/components/icons/mail-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";

export const MailIcon: React.FC = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="23"
height="23"
viewBox="0 0 23 23"
fill="none"
>
<g clipPath="url(#clip0_92_963)">
<path
d="M2.875 9.34824L11.5 2.96035L20.125 9.34824V11.4775L13.0049 16.7559C12.5691 17.0793 12.0436 17.25 11.5 17.25C10.9564 17.25 10.4309 17.0748 9.99512 16.7559L2.875 11.4775V9.34824ZM11.5 0C10.9564 0 10.4309 0.175195 9.99512 0.494141L1.16348 7.03926C0.43125 7.58281 0 8.43633 0 9.34824V20.125C0 21.7107 1.28926 23 2.875 23H20.125C21.7107 23 23 21.7107 23 20.125V9.34824C23 8.43633 22.5688 7.57832 21.8365 7.03926L13.0049 0.494141C12.5691 0.175195 12.0436 0 11.5 0Z"
fill="#024F9E"
/>
</g>
<defs>
<clipPath id="clip0_92_963">
<rect width="23" height="23" fill="white" />
</clipPath>
</defs>
</svg>
);
16 changes: 16 additions & 0 deletions src/components/icons/new-chat-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react";

export const NewChatIcon: React.FC = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="19"
height="20"
viewBox="0 0 19 20"
fill="none"
>
<path
d="M17.683 1.37852C16.8618 0.567836 15.5345 0.567836 14.7133 1.37852L13.5847 2.48905L17.2555 6.11309L18.3841 4.99885C19.2053 4.18817 19.2053 2.87774 18.3841 2.06705L17.683 1.37852ZM6.46426 9.52242C6.23553 9.74822 6.0593 10.0259 5.95806 10.3331L4.84819 13.6203C4.73945 13.9386 4.82569 14.2903 5.06567 14.5309C5.30564 14.7715 5.66185 14.853 5.98806 14.7456L9.31768 13.6499C9.62514 13.5499 9.90636 13.376 10.1388 13.1502L16.4119 6.95339L12.7373 3.32565L6.46426 9.52242ZM3.59959 2.94437C1.61231 2.94437 0 4.53613 0 6.49807V15.9746C0 17.9365 1.61231 19.5283 3.59959 19.5283H13.1985C15.1858 19.5283 16.7981 17.9365 16.7981 15.9746V12.4209C16.7981 11.7657 16.2619 11.2363 15.5982 11.2363C14.9345 11.2363 14.3983 11.7657 14.3983 12.4209V15.9746C14.3983 16.6298 13.8622 17.1592 13.1985 17.1592H3.59959C2.93591 17.1592 2.39972 16.6298 2.39972 15.9746V6.49807C2.39972 5.84286 2.93591 5.3135 3.59959 5.3135H7.19917C7.86284 5.3135 8.39903 4.78415 8.39903 4.12894C8.39903 3.47372 7.86284 2.94437 7.19917 2.94437H3.59959Z"
fill="currentColor"
/>
</svg>
);
23 changes: 23 additions & 0 deletions src/components/icons/pdf-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";

export const PDFIcon: React.FC = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="23"
viewBox="0 0 18 23"
fill="none"
>
<g clipPath="url(#clip0_92_1607)">
<path
d="M3 0C1.34531 0 0 1.28926 0 2.875V20.125C0 21.7107 1.34531 23 3 23H15C16.6547 23 18 21.7107 18 20.125V7.1875H12C11.1703 7.1875 10.5 6.54512 10.5 5.75V0H3ZM12 0V5.75H18L12 0ZM5.25 11.5H12.75C13.1625 11.5 13.5 11.8234 13.5 12.2188C13.5 12.6141 13.1625 12.9375 12.75 12.9375H5.25C4.8375 12.9375 4.5 12.6141 4.5 12.2188C4.5 11.8234 4.8375 11.5 5.25 11.5ZM5.25 14.375H12.75C13.1625 14.375 13.5 14.6984 13.5 15.0938C13.5 15.4891 13.1625 15.8125 12.75 15.8125H5.25C4.8375 15.8125 4.5 15.4891 4.5 15.0938C4.5 14.6984 4.8375 14.375 5.25 14.375ZM5.25 17.25H12.75C13.1625 17.25 13.5 17.5734 13.5 17.9688C13.5 18.3641 13.1625 18.6875 12.75 18.6875H5.25C4.8375 18.6875 4.5 18.3641 4.5 17.9688C4.5 17.5734 4.8375 17.25 5.25 17.25Z"
fill="#04AA84"
/>
</g>
<defs>
<clipPath id="clip0_92_1607">
<rect width="18" height="23" fill="white" />
</clipPath>
</defs>
</svg>
);
16 changes: 16 additions & 0 deletions src/components/icons/send-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react";

export const SendIcon: React.FC = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="19"
height="19"
viewBox="0 0 19 19"
fill="none"
>
<path
d="M18.4846 0.207954C18.8594 0.46772 19.0561 0.916743 18.9855 1.36577L16.6105 16.8033C16.5549 17.1632 16.3359 17.4787 16.0168 17.6568C15.6977 17.8349 15.3154 17.8572 14.9777 17.7162L10.5394 15.8718L7.99746 18.6216C7.66718 18.9816 7.14765 19.1003 6.69121 18.9222C6.23476 18.7441 5.93789 18.3025 5.93789 17.8126V14.7103C5.93789 14.5619 5.99355 14.4208 6.09375 14.3095L12.3133 7.52592C12.5285 7.29213 12.5211 6.93217 12.2984 6.70952C12.0758 6.48686 11.7158 6.47202 11.482 6.68354L3.93398 13.3892L0.657223 11.749C0.263863 11.5523 0.0115193 11.1589 0.000386514 10.721C-0.0107463 10.2831 0.219332 9.87495 0.597847 9.656L17.2228 0.156001C17.6199 -0.0703659 18.1098 -0.0481003 18.4846 0.207954Z"
fill="currentColor"
/>
</svg>
);
16 changes: 16 additions & 0 deletions src/components/icons/sidebar-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react";

export const SidebarIcon: React.FC = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="19"
height="17"
viewBox="0 0 19 17"
fill="none"
>
<path
d="M0 2.42857C0 1.08906 1.06504 0 2.375 0H16.625C17.935 0 19 1.08906 19 2.42857V14.5714C19 15.9109 17.935 17 16.625 17H2.375C1.06504 17 0 15.9109 0 14.5714V2.42857ZM2.375 4.85714V14.5714H8.3125V4.85714H2.375ZM16.625 4.85714H10.6875V14.5714H16.625V4.85714Z"
fill="currentColor"
/>
</svg>
);
16 changes: 16 additions & 0 deletions src/components/icons/vermerk-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react";

export const VermerkIcon: React.FC = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="21"
height="24"
viewBox="0 0 21 24"
fill="none"
>
<path
d="M4.5 0C2.01562 0 0 2.01562 0 4.5V19.5C0 21.9844 2.01562 24 4.5 24H18H19.5C20.3297 24 21 23.3297 21 22.5C21 21.6703 20.3297 21 19.5 21V18C20.3297 18 21 17.3297 21 16.5V1.5C21 0.670312 20.3297 0 19.5 0H18H4.5ZM4.5 18H16.5V21H4.5C3.67031 21 3 20.3297 3 19.5C3 18.6703 3.67031 18 4.5 18ZM6 6.75C6 6.3375 6.3375 6 6.75 6H15.75C16.1625 6 16.5 6.3375 16.5 6.75C16.5 7.1625 16.1625 7.5 15.75 7.5H6.75C6.3375 7.5 6 7.1625 6 6.75ZM6.75 9H15.75C16.1625 9 16.5 9.3375 16.5 9.75C16.5 10.1625 16.1625 10.5 15.75 10.5H6.75C6.3375 10.5 6 10.1625 6 9.75C6 9.3375 6.3375 9 6.75 9Z"
fill="#F39302"
/>
</svg>
);
14 changes: 13 additions & 1 deletion tailwind.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
/** @type {import('tailwindcss').Config} */
// eslint-disable-next-line @technologiestiftung/no-default-export
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {},
extend: {
colors: {
"dark-blue": "#1C2554",
"light-blue": "#A9C9E7",
"light-grey": "#F2F2F2",
"mid-grey": "#D7D7D7",
"dark-grey": "#333333",
},
fontFamily: {
arial: ["Arial"],
},
},
},
plugins: [],
};

0 comments on commit f2fbfb1

Please sign in to comment.