Add container components

This commit is contained in:
araemer 2025-10-25 21:19:08 +02:00
parent f867cd3601
commit ca7851939f
8 changed files with 55 additions and 38 deletions

View file

@ -39,9 +39,4 @@
@apply text-sm text-red-600; @apply text-sm text-red-600;
} }
/* containers */
.highlight-container-bg {
@apply bg-gray-200 rounded p-2;
}
} }

View file

@ -0,0 +1,26 @@
import clsx from "clsx";
import React, {type ReactNode} from "react";
type BoxContainerProps = React.HTMLAttributes<HTMLDivElement> & {
/** Content to render inside the container */
children: ReactNode;
};
/**
* Box Container for highlighting content
*
* Accepts any div attributes (e.g. `className`, `title`, `onClick`, or DnD listeners).
*/
export function BoxContainer({children, className, ...rest}: BoxContainerProps) {
return (
<div
{...rest}
className={clsx(
"bg-gray-200 rounded p-2",
className
)}
>
{children}
</div>
);
}

View file

@ -1,23 +1,22 @@
import type {ReactNode} from "react"; import React, {type ReactNode} from "react";
import clsx from "clsx"; import clsx from "clsx";
type ButtonGroupLayoutProps = { type ButtonGroupLayoutProps = React.HTMLAttributes<HTMLDivElement> & {
/** Content to render inside the header */ /** Content to render inside the header */
children: ReactNode; children: ReactNode;
/** Optional additional Tailwind classes */
className?: string;
}; };
/** /**
* A layout for horizontally aligning buttons as usually a save button is accompanied by a cancel button * A layout for horizontally aligning buttons as usually a save button is accompanied by a cancel button
* @param children Children of the layout, i.e., buttons * @param children Children of the layout, i.e., buttons
* @param className Optional additional styles * @param className Optional additional styles
* @param props all other props by html div that might be needed
* @constructor * @constructor
*/ */
export default function ButtonGroupLayout({children, className = ""}: ButtonGroupLayoutProps) { export default function ButtonGroupLayout({children, className, ...rest}: ButtonGroupLayoutProps) {
return ( return (
<div <div
{...rest}
className={clsx( className={clsx(
"flex gap-4 mt-8", "flex gap-4 mt-8",
className className

View file

@ -1,24 +1,23 @@
import type {ReactNode} from "react"; import React, {type ReactNode} from "react";
import clsx from "clsx"; import clsx from "clsx";
type ContentBackgroundProps = { type ContentBackgroundProps = React.HTMLAttributes<HTMLDivElement> & {
/** Content to render inside the container */ /** Content to render inside the container */
children: ReactNode; children: ReactNode;
/** Optional additional Tailwind classes */
className?: string;
}; };
/** /**
* Background for the content area of a page * Background for the content area of a page
* @param children Children the page, i.e., header and body * @param children Children the page, i.e., header and body
* @param className Optional additional styles * @param className Optional additional styles
* @param props all other props by html div that might be needed
* @see ContentBody.tsx * @see ContentBody.tsx
* @constructor * @constructor
*/ */
export default function ContentBackground({children, className = ""}: ContentBackgroundProps) { export default function ContentBackground({children, className, ...props}: ContentBackgroundProps) {
return ( return (
<div <div
{...props}
className={clsx( className={clsx(
"bg-gray-100 w-full min-h-screen max-w-6xl shadow-xl p-8", "bg-gray-100 w-full min-h-screen max-w-6xl shadow-xl p-8",
className className

View file

@ -1,23 +1,22 @@
import {type ReactNode} from "react"; import React, {type ReactNode} from "react";
import clsx from "clsx"; import clsx from "clsx";
type ContentBodyProps = { type ContentBodyProps = React.HTMLAttributes<HTMLDivElement> & {
/** Content to render inside the container */ /** Content to render inside the container */
children: ReactNode; children: ReactNode;
/** Optional additional Tailwind classes */
className?: string;
}; };
/** /**
* Body for the content area of a page * Body for the content area of a page
* @param children Children the page, i.e., header and body * @param children Children the page, i.e., header and body
* @param className Optional additional styles * @param className Optional additional styles
* @param props all other props by html div that might be needed
* @constructor * @constructor
*/ */
export default function ContentBody({children, className = ""}: ContentBodyProps) { export default function ContentBody({children, className, ...props}: ContentBodyProps) {
return ( return (
<div <div
{...props}
className={clsx( className={clsx(
"p-6 max-w-2xl mx-auto", "p-6 max-w-2xl mx-auto",
className className

View file

@ -1,23 +1,22 @@
import type {ReactNode} from "react"; import React, {type ReactNode} from "react";
import clsx from "clsx"; import clsx from "clsx";
type HorizontalInputGroupLayoutProps = { type HorizontalInputGroupLayoutProps = React.HTMLAttributes<HTMLDivElement> & {
/** Content to render inside the group */ /** Content to render inside the group */
children: ReactNode; children: ReactNode;
/** Optional additional Tailwind classes */
className?: string;
}; };
/** /**
* A layout for horizontally aligning inputs and buttons - designed for pages with several input items in a row * A layout for horizontally aligning inputs and buttons - designed for pages with several input items in a row
* @param children Children of the layout, i.e., inputs * @param children Children of the layout, i.e., inputs
* @param className Optional additional styles * @param className Optional additional styles
* @param props all other props by html div that might be needed
* @constructor * @constructor
*/ */
export default function HorizontalInputGroupLayout({children, className = ""}: HorizontalInputGroupLayoutProps) { export default function HorizontalInputGroupLayout({children, className, ...props}: HorizontalInputGroupLayoutProps) {
return ( return (
<div <div
{...props}
className={clsx( className={clsx(
"flex gap-2 mb-2 items-center", "flex gap-2 mb-2 items-center",
className className

View file

@ -1,23 +1,22 @@
import {type ReactNode} from "react"; import React, {type ReactNode} from "react";
import clsx from "clsx"; import clsx from "clsx";
type PageContainerProps = { type PageContainerProps = React.HTMLAttributes<HTMLDivElement> & {
/** Content to render inside the container */ /** Content to render inside the container */
children: ReactNode; children: ReactNode;
/** Optional additional Tailwind classes */
className?: string;
}; };
/** /**
* Container for a page providing the correct dimensions to its children * Container for a page providing the correct dimensions to its children
* @param children Children the page, i.e., header and body * @param children Children the page, i.e., header and body
* @param className Optional additional styles * @param className Optional additional styles
* @param props all other props by html div that might be needed
* @constructor * @constructor
*/ */
export default function PageContainer({children, className = ""}: PageContainerProps): ReactNode { export default function PageContainer({children, className, ...rest}: PageContainerProps): ReactNode {
return ( return (
<div <div
{...rest}
className={clsx( className={clsx(
"flex items-center w-screen justify-center min-h-screen ;", "flex items-center w-screen justify-center min-h-screen ;",
className className

View file

@ -13,6 +13,7 @@ import ButtonGroupLayout from "../basics/ButtonGroupLayout.tsx";
import ContentBackground from "../basics/ContentBackground.tsx"; import ContentBackground from "../basics/ContentBackground.tsx";
import ContentBody from "../basics/ContentBody.tsx"; import ContentBody from "../basics/ContentBody.tsx";
import PageContainer from "../basics/PageContainer.tsx"; import PageContainer from "../basics/PageContainer.tsx";
import {BoxContainer} from "../basics/BoxContainer.tsx";
/** /**
@ -102,8 +103,8 @@ export default function RecipeDetailPage() {
)} )}
{/* Servings */} {/* Servings */}
<div <BoxContainer
className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 highlight-container-bg mb-4"> className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-4">
<p> <p>
Für {recipeWorkingCopy.servings.amount} {recipeWorkingCopy.servings.unit} Für {recipeWorkingCopy.servings.amount} {recipeWorkingCopy.servings.unit}
</p> </p>
@ -114,7 +115,7 @@ export default function RecipeDetailPage() {
min={1} min={1}
className="justify-end sm:justify-center" className="justify-end sm:justify-center"
/> />
</div> </BoxContainer>
{/* Ingredients */} {/* Ingredients */}
<h2>Zutaten</h2> <h2>Zutaten</h2>