Skip to content

Commit

Permalink
Merge pull request #143 from ncs-northware/tailwind/css
Browse files Browse the repository at this point in the history
Rethink Tailwind, @northware/ui, Stylesheets
  • Loading branch information
onissen authored Nov 13, 2024
2 parents 8ebe66d + 468e035 commit 8f8e7a6
Show file tree
Hide file tree
Showing 28 changed files with 1,179 additions and 86 deletions.
11 changes: 11 additions & 0 deletions .changeset/cool-gorillas-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@northware/tailwind-config": minor
---

`@northware/tailwind-config` provides a shareable config preset to be used in every Northware App or Packages that needs uses Tailwind.

## Features

- Extends the Tailwind Theme to work with the Custom Google Font `Source Sans 3`.
- Defines a custom `secondary` color-set
- Aliases Default Color Sets with Custom Brand Names
173 changes: 173 additions & 0 deletions apps/docs/docs/30-Packages/tailwind-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# @northware/tailwind-config

Das Package `@northware/tailwind-config` exportiert eine `tailwind.config.js` Datei. Diese Konfigurationsdatei kann in Apss und Packages, die Tailwind verwenden als Preset in die Konfigurationdatei der App / des Pacakges importiert werden. Innerhalb der Konfigurationsdateien müssen dann nur noch Anpassungen vorgenommen werden, die nur für die einzelne App gelten.

## Tailwind in einer Next.js App nutzen

**1. Um Tailwind verwenden zu können, müssen `tailwindcss`, `postcss` und `autoprefixer` als Dev-Dependencies installiert werden:**

```cmd
pnpm add -D tailwindcss postcss autoprefixer
```

**2. Tailwind und PostCSS müssen konfigriert werden:**

```cmd
pnpm dlx tailwindcss init -p
```

**3. Anpassung der `tailwind.config.js`**

- `content`: Es muss definiert werden welche Dateien Tailwind nutzen.
- `presets`: Implementierung des Config-Presets aus `@northware/tailwind-config`
- `theme.extend.colors` (Optional): Über die Color Konfiguration aus `@northware/tailwind-config` hinaus kann eine Konfiguration innerhalb der App definiert werden. Hier sollte z.B. definiert werden, welche Farbe hinter `primary` steht. `primary` wird in UI und Apps als die hauptsächliche Brand-Color genutzt.

```js title="./tailwind.config.js"
/** @type {import('tailwindcss').Config} */

// colors wird genutzt, wenn die Standard-Farben von Tailwind mit einem anderen Namen genutzt werden sollen
const colors = require("tailwindcss/colors");

module.exports = {
//
content: ["./src/**/*.{js,ts,jsx,tsx,mdx}"],
presets: [require("@northware/tailwind-config")],
theme: {
extend: {
colors: {
primary: colors.sky,
},
},
},
plugins: [],
};
```

**4. Implementierung von Tailwind in die `globals.css`**

Die `globals.css` muss nun so konfiguriert werden, dass die Tailwind-Stylings in das Styling der App aufgenommen wird.

```css title="./src/app/globals.css"

@tailwind base;
@tailwind components;
@tailwind utilities;

...

```

**5. Einbinden der `globals.css` und `@northware/ui/styling.css`**

```jsx title="./src/app/layout.jsx"
// App-weites Styling
import "./globals.css";

// Styling aus dem UI-Package (nur nötig wenn die App @northware/ui verwendet)
import "@northware/ui/css";
```

Quelle: [Framework Guide "Install Tailwind CSS with Next.js"](https://tailwindcss.com/docs/guides/nextjs)

## Tailwind mit der Tailwind CLI nutzen

Packages, in denen kein Framework verwendet wird (wie `@northware/ui`), können Tailwind mit Hilfe der **Tailwind CDN** verwenden.

**1. Installation von Tailwind CSS**

```cmd
pnpm add -D tailwindcss
```

**2. Tailwind Initialisieren**

```cmd
pnpm dlx tailwindcss init
```

**3. Anpassung der `tailwind.config.js`**

- `content`: Es muss definiert werden welche Dateien Tailwind nutzen.
- `presets`: Implementierung des Config-Presets aus `@northware/tailwind-config`
- `theme.extend.colors` (Optional): Über die Color Konfiguration aus `@northware/tailwind-config` hinaus kann eine Konfiguration innerhalb der App definiert werden. Hier sollte z.B. definiert werden, welche Farbe hinter `primary` steht. `primary` wird in UI und Apps als die hauptsächliche Brand-Color genutzt.

```js title="./tailwind.config.js"
/** @type {import('tailwindcss').Config} */

// colors wird genutzt, wenn die Standard-Farben von Tailwind mit einem anderen Namen genutzt werden sollen
const colors = require("tailwindcss/colors");

module.exports = {
//
content: ["./src/**/*.{js,ts,jsx,tsx,mdx}"],
presets: [require("@northware/tailwind-config")],
theme: {
extend: {
colors: {
primary: colors.sky,
},
},
},
plugins: [],
};
```

**4. Implementierung von Tailwind in eine CSS-Datei**

Innerhalb des Packages muss es eine CSS-Datei geben, in der Tailwind eingebunden wird (z.B. `./src/input.css`)

```css title="./src/css/input.css"

@tailwind base;
@tailwind components;
@tailwind utilities;

...

```

**5. Compiling Prozess starten**

Die Tailwind CLI muss nun die verwendeten Tailwind-Styles compilen. Dazu muss der folgende Command ausgeführt werden:

```cmd

pnpm tailwindcss -i ./src/css/input.css -o ./src/css/output.css --watch

```

Mit diesem Code compiled die Tailwind CLI das Styling nun also aus der `input.css` in die `output.css`.
Durch das `--watch` Flag wartet der Command auf Änderungen innerhalb des Packages und compiled live in die `output.css`

**6. `output.css` in die App integrieren**

Die `output.css` enthält nun nur die wirklich benötigten Stylings und kann innerhalb des Packages oder in anderen Packages und Apps überall dort verwendet werden, wo auf Teile des Packages zugegriffen wird.

```jsx title="./layout.jsx"
import "@northware/ui/css";
```

**Achtung:** Werden Stylesheets aus einem Package in einem anderen Package oder App verwendet, muss das bereitstellende Package diese CSS-Datei exportieren.

```json title="package.json"

{
...
"exports": {
"./css": "./src/css/output.css",
...
},
...
}

```

Quelle: [Tailwind Installation mit der CLI](https://tailwindcss.com/docs/installation)
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ Datei-Pfad: `theme/components/Nav.js`
Die Nav-Komponente ist für die Haupt-Navigation zuständig. Sie ist auf eine mobile Ansicht (SM-Breakpoint) angepasst.
Die Komponente ist sehr umfangreich. Vielleicht ist also nicht an jeder Stelle alles ganz verständlich. Als Grundlage für die Komponente habe ich eine [Navbar von Tailwind UI](https://tailwindui.com/components/application-ui/navigation/navbars)(die kostenlose Variante "Simple dark with menu button on left" mit dem React-Code). Diese Komponente nutzt schon von Haus einige Komponenten von [Headless UI](https://headlessui.com/) und Icons von [heroicons](https://heroicons.com/). Ich habe den Beispiel-Code dann an einigen Stellen verändert und erweitert.

![Navigation in der Desktop-Ansicht](../img/mainnav-desktop.png)
![Navigation in der Desktop-Ansicht](../../img/mainnav-desktop.png)

_Navigation in der Desktop-Ansicht_

![Navigation in der Mobile Ansicht](../img/mainnav-mobile.png)
![Navigation in der Mobile Ansicht](../../img/mainnav-mobile.png)

_Navigation in der Mobile Ansicht_

Expand Down
74 changes: 74 additions & 0 deletions apps/docs/docs/30-Packages/ui/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# @northware/ui

`@northware/ui` ist die Styling und UI-Component Library für die Northware Apps.
Das Package enthält Komponenten, die das Grundstyling der Apps übernehmen und Reusable Component, die die UI gestalten.

## Nutzung in anderen Apps

### UI-Styling und Tailwind

Innerhalb von Apps, die `@northware/ui` verwenden sollen, muss Tailwind CSS (und `autoprefixer` und `postcss` ) installiert und korrekt konfiguriert sein. Mehr dazu in den [`@northware/tailwind-config` Docs](../tailwind-config).

Um das Stylesheet von `@northware/ui` zu verwenden, muss es in der `layout.jsx` der App importiert werden. Enthalten die App auch eigene Stylesheets, müssen diese ebenfalls importiert werden.

```jsx title="./src/app/layout.jsx"
// Stylesheet der App oberhalb der UI-Styles
import "./globals.css";

// Stylesheet aus @northware/ui
import "@northware/ui/css";
```

## Features

### Tailwind CSS

Northware verwendet [Tailwind CSS](https://tailwindcss.com/) zum Styling.

Die **`tailwind.config.js`** innerhalb des Packages ermöglich die Nutzung innerhalb des Packages mit den folgenden Konfigurationen:

- `content` definiert, in welchen Ordnern die Tailwind Klassen verwendet werden können.
- Das UI-Package verwendet den Prefix `ui-`. Das bedeutet, das jede Tailwind-Klasse innerhalb des UI-Package mit diesem Prefix angegeben werden muss. Damit ist gewährleistet, das Tailwind-Klassen innerhalb des UI-Packages nicht mit Tailwind-Klassen außerhalb des Packages (z.B. in den Apps) in Konflikt kommen.
- Darüber hinaus verwendet das UI-Package die Basis-Konfigurationen aus [@northware/tailwind-config](../tailwind-config) als Preset. Alle Regelungen, die in diesem Package bereits getroffen wurden, müssen in der Konfigurationsdatei der UI nicht erneut definiert werden.

Das UI-Package verwendet die Tailwind CLI, um die Stylings aus den Komponenten der UI anzuwenden. Die `src/css/input.css` importiert dazu die Tailwind-Directives. Wird nun innerhalb des Packages bzw. in innerhalb der Turborepo das Script `dev` oder `build` aufgerufen, compiled die Tailwind CLI die innerhalb de UI-Packages verwendeten Stylings in die `src/css/output.css`. Diese Datei wird wiederum vom `@northware/ui`-Package exportiert und muss dann in die `layout.jsx` der Northware Apps importiert werden, um die UI-Komponenten richtig darstellen zu können.

### shadcn/ui

Das UI-Design ist inspiriert von [shadcn/ui](https://ui.shadcn.com/).
Da es sich bei dem UI-Package um kein vollständiges React-Framework hadelt, kann die **shadcn CLI** nicht verwendet werden.
Stattdessen müssen die schadcn Komponenten manuell implementiert werden.

### lucide-react

[Lucide React](https://lucide.dev/guide/packages/lucide-react) ist die von Northware verwendete Icon-Library.

### `cn()` Helper Function

Die Funktion `cn()` ist eine Helper Function die innerhalb des UI-Packages verwendet werden kann, um Conditional Tailwind Klassen zu vereinfachen.

#### Beispiel

```jsx
import { cn } from "../lib/cn";

export function HelloWorld({ className }) {
return (
<div className={cn(className, "ui-text-cockpit-300")}>
<h1 className="ui-text-4xl ui-font-medium">Hello World</h1>
</div>
);
}
```

Die Komponente `HelloWorld` exportiert einen `div` der eine `h1` enthält. Beide Elemente der Komponente sind mit Tailwind Klassen gestylet, sodass eine Implementierung ohne weitere Properties eine gestylete Überschrift ausgibt.
Die Komponente akzeptiert außerdem die Property `className`. Wird die Komponente mit der Property `className` implementiert, wird dieser Wert als `className` auf den `div` angewendet. Die Verwendung von `cn()` ermöglicht nun, das das Base-Styling der Komponete überschrieben wird.

```jsx
...
// Rendert eine blaue Überschrift (wegen ui-text-cockpit-300)
<HelloWorld />
...
// Rendert eine orangene Überschrift (text-trader-400) mit einem grünen Hintergrund
<HelloWorld className="bg-green-400 text-trader-400" />
```
3 changes: 2 additions & 1 deletion apps/northware-cockpit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
},
"dependencies": {
"@northware/auth": "workspace:*",
"@northware/ui": "workspace:*",
"@northware/theme": "workspace:*",
"@northware/ui": "workspace:*",
"drizzle-orm": "^0.36.1",
"next": "15.0.3",
"next-auth": "5.0.0-beta.25",
Expand All @@ -22,6 +22,7 @@
"devDependencies": {
"@northware/eslint-config": "workspace:*",
"@northware/tailwind-config": "workspace:*",
"autoprefixer": "^10.4.20",
"eslint": "^9.14.0",
"eslint-config-next": "^15.0.3",
"postcss": "^8",
Expand Down
31 changes: 25 additions & 6 deletions apps/northware-cockpit/src/app/dashboard/page.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
import { auth, signOut } from "@northware/auth/auth";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@northware/ui/components";

export default async function DashboardPage() {
let session = await auth();
console.log(session);
return (
<div className="flex h-screen bg-black">
<div className="w-screen h-screen flex flex-col space-y-5 justify-center items-center text-white">
You are logged in as {session?.user?.email}
<SignOut />
</div>
</div>
<>
You are logged in as {session?.user?.email}
<SignOut />
<Card className="bg-green-300">
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
</CardHeader>
<CardContent>
<p>Card Content</p>
</CardContent>
<CardFooter>
<p>Card Footer</p>
</CardFooter>
</Card>
<div className="size-24 rounded-md bg-cockpit-400">Test</div>
</>
);
}

Expand Down
3 changes: 3 additions & 0 deletions apps/northware-cockpit/src/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
10 changes: 6 additions & 4 deletions apps/northware-cockpit/src/app/layout.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "@northware/theme/global.sass";

import { source_sans } from "@northware/theme/fonts";
import "./globals.css";
import "@northware/ui/css";
import { source_sans } from "@northware/ui/fonts";

export const metadata = {
title: {
Expand All @@ -13,7 +13,9 @@ export default function RootLayout({ children }) {
return (
<html lang="de">
<body>
<main className={`${source_sans.variable} font-sans`}>{children}</main>
<main className={`${source_sans.variable} font-sans container`}>
{children}
</main>
</body>
</html>
);
Expand Down
5 changes: 2 additions & 3 deletions apps/northware-cockpit/src/app/login/page.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { LoginForm } from "@northware/auth/components";
import { signIn } from "@northware/auth/auth";
import template from "@northware/ui/templates/login";
import Image from "next/image";
export default function LoginPage() {
return (
<main className={`${template.login} ${template.cockpit}`}>
<section className={template.loginBox}>
<main className={`${""} ${""}`}>
<section className={""}>
<div id="loginForm">
<Image
src="/img/logo.svg"
Expand Down
2 changes: 1 addition & 1 deletion apps/northware-cockpit/src/app/page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Link from "next/link";
export default function Page() {
return (
<div>
<h1>Northware Cockpit</h1>
<h1 className="bg-cockpit-500 text-3xl size-16">Northware Cockpit</h1>
<Link href="/dashboard">Dashboard</Link>
</div>
);
Expand Down
Loading

0 comments on commit 8f8e7a6

Please sign in to comment.