Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
aea48eb
feat: add Maven Central publishing + signing for v0.1.0
ClankerGuru Mar 18, 2026
99af570
docs: comprehensive README with all 52 components, badges, platforms
ClankerGuru Mar 18, 2026
eccfdea
feat: add hover + focus states for desktop interaction
ClankerGuru Mar 18, 2026
ced324c
feat: add Android target to catalog app
ClankerGuru Mar 19, 2026
7505266
feat: responsive catalog shell, press states, color schemes, typograp…
ClankerGuru Mar 19, 2026
0be009f
feat: component showcases, theme playground, icons page, Lucide icons
ClankerGuru Mar 19, 2026
2317228
fix: replace emoji with Lucide icons, fix table overflow, fix stray c…
ClankerGuru Mar 19, 2026
a5fa1d4
feat: show all button variants simultaneously, add Spinner component
ClankerGuru Mar 19, 2026
da1e37b
feat: GortScaffold, GortDrawer, Spinner, dialog scrim fix, color sche…
ClankerGuru Mar 19, 2026
8d0414e
feat: GortBottomBar, GortBottomSheet, GortListDetail, GortFab + catal…
ClankerGuru Mar 19, 2026
37b091f
feat: GortSideSheet + catalog showcase
ClankerGuru Mar 19, 2026
8156ec0
feat: GortSearchBar + catalog showcase
ClankerGuru Mar 19, 2026
f6b8aea
fix: GortSearchBar Chip params, app icon resources
ClankerGuru Mar 19, 2026
1cbb020
feat: bundle Lucide icons as :icons module, dependency substitution, …
ClankerGuru Mar 21, 2026
4349d6a
chore: remove OPSX-generated files from tracking
ClankerGuru Mar 21, 2026
1bfade8
feat: add core interaction components (Batch 1)
ClankerGuru Mar 21, 2026
c021996
feat: rewrite Batch 2 components
ClankerGuru Mar 21, 2026
3e1834a
feat: rewrite catalog screens (Batch 3)
ClankerGuru Mar 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,27 @@ jobs:

- name: Build and test
run: ./gradlew build
env:
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m"
Comment on lines +48 to +49

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

GRADLE_OPTS syntax causes JVM args to be split incorrectly.

The space in -Dorg.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m causes -XX:MaxMetaspaceSize=512m to be parsed as a separate argument to the Gradle wrapper JVM rather than part of org.gradle.jvmargs for the daemon.

🔧 Proposed fix: Set GRADLE_OPTS directly or use gradle.properties

Option 1: Use GRADLE_OPTS directly for wrapper JVM args

         env:
-          GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m"
+          GRADLE_OPTS: "-Xmx4g -XX:MaxMetaspaceSize=512m"

Option 2: Use JAVA_TOOL_OPTIONS for broader coverage

         env:
-          GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m"
+          JAVA_TOOL_OPTIONS: "-Xmx4g -XX:MaxMetaspaceSize=512m"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
env:
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m"
env:
GRADLE_OPTS: "-Xmx4g -XX:MaxMetaspaceSize=512m"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yml around lines 48 - 49, The GRADLE_OPTS
assignment is splitting JVM args because the space separates -XX:... from the
-Dorg.gradle.jvmargs value; update how JVM args are passed so both -Xmx4g and
-XX:MaxMetaspaceSize=512m are quoted/contained inside the org.gradle.jvmargs
property (i.e., set GRADLE_OPTS so that org.gradle.jvmargs receives a single
string containing both flags), or alternatively move the setting into
gradle.properties as org.gradle.jvmargs or use JAVA_TOOL_OPTIONS to apply the
JVM flags; adjust the environment entry that sets GRADLE_OPTS accordingly so
-XX:MaxMetaspaceSize=512m is not treated as a separate wrapper JVM argument.


- name: Publish test results
uses: dorny/test-reporter@v1
if: always()
if: always() && hashFiles('**/build/test-results/test/*.xml') != ''
with:
name: Test Results
path: '**/build/test-results/test/*.xml'
reporter: java-junit

- name: Publish to Maven Central
continue-on-error: true
run: ./gradlew publishAllPublicationsToMavenCentralRepository
run: ./gradlew :gort:publishAllPublicationsToMavenCentralRepository
env:
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m"

- name: Attach JARs to release
run: |
find . -path '*/build/libs/*.jar' -exec gh release upload "${{ github.event.release.tag_name }}" {} --clobber \;
find . -path '*/gort/build/libs/*.jar' -exec gh release upload "${{ github.event.release.tag_name }}" {} --clobber \;
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
207 changes: 171 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
# GORT

[![🤖 clanker](https://img.shields.io/badge/🤖-clanker-black?style=flat-square)](https://github.com/ClankerGuru) [![Kotlin](https://img.shields.io/badge/Kotlin-2.3-7F52FF?style=flat-square&logo=kotlin&logoColor=white)](https://kotlinlang.org) [![Compose](https://img.shields.io/badge/Compose-1.10-4285F4?style=flat-square&logo=jetpackcompose&logoColor=white)](https://www.jetbrains.com/compose-multiplatform/) [![CI](https://github.com/ClankerGuru/gort/actions/workflows/ci.yml/badge.svg)](https://github.com/ClankerGuru/gort/actions/workflows/ci.yml) [![Maven Central](https://img.shields.io/maven-central/v/zone.clanker/gort?label=Maven%20Central&style=flat-square)](https://central.sonatype.com/artifact/zone.clanker/gort) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE)

> *A neobrutalist design system for Compose Multiplatform.*

**Bold. Loud. Unapologetic.**

Gort is an opinionated UI component library that replaces Material 3 with thick borders, hard offset shadows, flat colors, and monospace type. Built on Compose Foundation — no Material dependency. Works on Android, iOS, Desktop, and Web.
Gort is an opinionated UI component library that replaces Material 3 with thick borders, hard offset shadows, flat colors, and monospace type. **52 components.** Pure Compose Foundation — zero Material dependency. Every platform Compose supports.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Component count mismatch: claims 52, but 57 listed.

The documentation states "52 components." but counting the component tables yields 57 components (Core Input: 15, Display: 12, Feedback: 8, Navigation: 6, Data & Compound: 11, Chat: 2, Foundation: 3).

Please reconcile the count with the actual component list.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` at line 9, The README's component count string "**52
components.**" is incorrect; reconcile it with the actual component list (Core
Input, Display, Feedback, Navigation, Data & Compound, Chat, Foundation) and
update the count to the correct number (57) or adjust the listed components to
match 52; locate the sentence containing "52 components." in README.md and
replace it with the accurate count and/or update the category tables so the
total matches the stated number.


Named after the 8-foot robot from *The Day the Earth Stood Still* (1951).

---

## Install

```kotlin
Expand All @@ -17,6 +21,8 @@ dependencies {
}
```

---

## Quick Start

```kotlin
Expand All @@ -27,9 +33,11 @@ GortTheme {
}
```

---

## Custom Theme

Swap the colors. Keep the structure. It still looks good.
Swap the colors. Keep the structure. It still looks like Gort.

```kotlin
GortTheme(
Expand All @@ -43,6 +51,123 @@ GortTheme(
}
```

---

## Components (52)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Section header also claims 52 components.

Same inconsistency as above — update to match the actual count.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` at line 56, The section header "## Components (52)" is
inconsistent with the actual component list; update the header string in
README.md (the "## Components (52)" line) to reflect the true count of
components by replacing "(52)" with the actual number that matches the list
below so the header and the component list are consistent.


### Core Input
| Component | Description |
|-----------|-------------|
| `Button` | Primary, secondary, tertiary, outlined — shadow-press animation |
| `IconButton` | Compact icon-only button |
| `TextField` | Thick-bordered text input |
| `TextArea` | Multi-line text input |
| `Toggle` | Mechanical on/off switch |
| `Checkbox` | Chunky checkmark |
| `RadioButton` | Exclusive selection |
| `Slider` | Range input with track + thumb |
| `NumberStepper` | Increment/decrement numeric input |
| `ChoiceGroup` | Single/multi select option group |
| `Rating` | Star rating input |
| `Dropdown` | Select menu with popup |
| `DatePicker` | Date selection |
| `TimePicker` | Time selection |
| `ColorPicker` | Color selection with palette |

### Display
| Component | Description |
|-----------|-------------|
| `Card` | Bordered card with hard offset shadow |
| `Badge` | Notification indicator |
| `Tag` | Categorical label |
| `Chip` | Removable tag/filter |
| `Avatar` | User identity with fallback |
| `Divider` | Thick horizontal rule |
| `Stamp` | Rotated approval/status mark |
| `Skeleton` | Loading placeholder |
| `Code` | Code block with syntax highlighting |
| `InlineCode` | Inline code span |
| `Kbd` | Keyboard shortcut display |
| `MarkdownRenderer` | Markdown to Compose UI |

### Feedback
| Component | Description |
|-----------|-------------|
| `Dialog` | Modal with shadow |
| `Snackbar` | Inline notification bar |
| `Toast` | Temporary popup notification |
| `Tooltip` | Hover info popup |
| `Banner` | Full-width alert strip |
| `Callout` | Highlighted info block |
| `Notification` | Rich notification card |
| `ProgressBar` | Determinate/indeterminate progress |

### Navigation
| Component | Description |
|-----------|-------------|
| `TopBar` | App bar with thick bottom border |
| `NavigationRail` | Side navigation |
| `Tabs` | Tab strip |
| `Breadcrumb` | Path navigation |
| `Pagination` | Page navigation controls |
| `SegmentedControl` | Toggle between views |

### Data & Compound
| Component | Description |
|-----------|-------------|
| `Table` | Data table with borders |
| `ListItem` | Structured list row |
| `Timeline` | Vertical event timeline |
| `Stepper` | Multi-step progress |
| `Accordion` | Collapsible sections |
| `FileTree` | Hierarchical file browser |
| `CommandPalette` | Searchable command menu |
| `FormField` | Label + input + error wrapper |
| `Widget` | Dashboard card container |
| `Calendar` | Monthly calendar view |
| `Marquee` | Scrolling text ticker |

### Chat
| Component | Description |
|-----------|-------------|
| `ChatBubble` | Message bubble (sent/received) |
| `ChatInput` | Message composer with actions |

### Foundation
| Component | Description |
|-----------|-------------|
| `Surface` | Base layer with border + hard offset shadow |
| `DrawSurface` | Freeform drawing canvas |
| `ColorPalette` | Preset color swatch picker |

---

## Theme System

Eight customizable token groups:

| Token | Class | What it controls |
|-------|-------|-----------------|
| Colors | `GortColors` | Primary, secondary, surface, error, text |
| Typography | `GortTypography` | Display, headline, title, body, label (shorthand aliases) |
| Borders | `GortBorders` | Width and color for all bordered components |
| Shadows | `GortShadows` | Hard offset shadow size and color |
| Corners | `GortCorners` | Border radius across components |
| Spacing | `GortSpacing` | Consistent padding/margin scale |
| Animation | `GortAnimation` | Duration and easing for press/hover/transitions |

### Design Tokens (Defaults)

| Token | Default |
|-------|---------|
| Border | 3dp solid |
| Shadow | 4dp × 4dp hard offset |
| Corners | 4dp radius |
| Font | JetBrains Mono |
| Press animation | 80ms snap (shadow collapses on press) |

---

## Accessibility

One-line toggle to OpenDyslexic for dyslexia-friendly reading:
Expand All @@ -55,52 +180,62 @@ GortTheme(
}
```

## Components
---

### Core
- `Button` — Primary, secondary, tertiary, outlined
- `Card` — Bordered card with offset shadow
- `TextField` — Thick-bordered input
- `Toggle` — Mechanical switch
- `Checkbox` — Chunky checkmark
- `Chip` — Tag/label
- `Divider` — Thick rule
- `Badge` — Notification dot
## Platforms

### Layout
- `Scaffold` — App shell
- `TopBar` — Nav bar with thick bottom border
- `BottomBar` — Tab bar with thick top border
| Platform | Target | Status |
|----------|--------|--------|
| Android | `androidTarget()` | ✅ |
| Desktop | `jvm("desktop")` | ✅ |
| Web (WASM) | `wasmJs { browser() }` | ✅ |
| Web (JS) | `js { browser(); nodejs() }` | ✅ |
| iOS | `iosArm64()`, `iosSimulatorArm64()` | ✅ |
| macOS | `macosArm64()` | ✅ |

### Feedback
- `Dialog` — Modal with shadow
- `Snackbar` — Toast notification
- `Tooltip` — Info popup
**6 targets.** All from a single codebase. No platform-specific code required.

## Design Tokens
---

| Token | Default |
|-------|---------|
| Border | 3dp solid |
| Shadow | 4dp × 4dp hard offset |
| Corners | 4dp radius |
| Font | JetBrains Mono |
| Accessibility Font | OpenDyslexic |
| Press animation | 80ms snap |
## Catalog App

## Platforms
The `:catalog` module is a live showcase of every component. Runs on Desktop and Web (WASM):

```bash
./gradlew :catalog:run # Desktop
./gradlew :catalog:wasmJsBrowserRun # Web
```

8 screens: Buttons, Inputs, Display, Navigation, Feedback, Compound, Data, Chat — with dark/light toggle and sidebar navigation.

- ✅ Android
- ✅ iOS (arm64 + simulator)
- ✅ Desktop (JVM)
- ✅ Web (Kotlin/WASM)
---

## Philosophy

Material 3 is fine. It's also everywhere. Every Compose app looks the same.

Gort is for apps that refuse to blend in.
Gort is the first **fun, opinionated alternative to Material 3 for Compose Multiplatform**:

- **Pure Foundation** — depends only on `compose.foundation`, `compose.runtime`, `compose.ui`
- **No Material** — not a theme on top of Material. No Material dependency at all.
- **Shadow-press is the signature** — interactive components have a hard offset shadow that collapses on press. That's the feel.
- **Extensible, not flexible** — you swap colors, but the structural style (borders, shadows, typography) stays. That's the point.
- **No prefix** — it's `Button`, not `GortButton`. Package namespace handles disambiguation.

---

## Dependencies

```
compose.foundation
compose.runtime
compose.ui
```

That's it. No Material 3. No third-party libraries.

---

## License

MIT © [ClankerGuru](https://github.com/ClankerGuru)
[MIT](LICENSE) © [ClankerGuru](https://github.com/ClankerGuru)
24 changes: 24 additions & 0 deletions catalog/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.composeMultiplatform)
alias(libs.plugins.composeCompiler)
alias(libs.plugins.androidApplication)
}

kotlin {
jvm("desktop")
androidTarget()
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
wasmJs { browser() }

Expand All @@ -22,6 +24,28 @@ kotlin {
implementation(compose.desktop.currentOs)
}
}

androidMain.dependencies {
implementation("androidx.activity:activity-compose:1.10.1")
}
}
}

android {
namespace = "zone.clanker.gort.catalog"
compileSdk = 35

defaultConfig {
applicationId = "zone.clanker.gort.catalog"
minSdk = 24
targetSdk = 35
versionCode = 1
versionName = "0.1.0"
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}

Expand Down
16 changes: 16 additions & 0 deletions catalog/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:label="Gort Catalog"
android:theme="@android:style/Theme.Material.Light.NoActionBar">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package zone.clanker.gort.catalog

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
CatalogApp()
}
}
}
Loading