-
Notifications
You must be signed in to change notification settings - Fork 0
feat: hover + focus states for desktop interaction #3
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
base: main
Are you sure you want to change the base?
Changes from 5 commits
aea48eb
99af570
eccfdea
ced324c
7505266
0be009f
2317228
a5fa1d4
da1e37b
8d0414e
37b091f
8156ec0
f6b8aea
1cbb020
4349d6a
1bfade8
c021996
3e1834a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,17 @@ | ||
| # GORT | ||
|
|
||
| [](https://github.com/ClankerGuru) [](https://kotlinlang.org) [](https://www.jetbrains.com/compose-multiplatform/) [](https://github.com/ClankerGuru/gort/actions/workflows/ci.yml) [](https://central.sonatype.com/artifact/zone.clanker/gort) [](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. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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 |
||
|
|
||
| Named after the 8-foot robot from *The Day the Earth Stood Still* (1951). | ||
|
|
||
| --- | ||
|
|
||
| ## Install | ||
|
|
||
| ```kotlin | ||
|
|
@@ -17,6 +21,8 @@ dependencies { | |
| } | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ```kotlin | ||
|
|
@@ -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( | ||
|
|
@@ -43,6 +51,123 @@ GortTheme( | |
| } | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Components (52) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Section header also claims 52 components. Same inconsistency as above — update to match the actual count. 🤖 Prompt for AI Agents |
||
|
|
||
| ### 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: | ||
|
|
@@ -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) | ||
| 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() | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GRADLE_OPTSsyntax causes JVM args to be split incorrectly.The space in
-Dorg.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512mcauses-XX:MaxMetaspaceSize=512mto be parsed as a separate argument to the Gradle wrapper JVM rather than part oforg.gradle.jvmargsfor the daemon.🔧 Proposed fix: Set GRADLE_OPTS directly or use gradle.properties
Option 1: Use GRADLE_OPTS directly for wrapper JVM args
Option 2: Use JAVA_TOOL_OPTIONS for broader coverage
📝 Committable suggestion
🤖 Prompt for AI Agents