-
Notifications
You must be signed in to change notification settings - Fork 19
docs: update code guidelines and add UI component skill #1220
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
Open
bmahabirbu
wants to merge
1
commit into
kortex-hub:main
Choose a base branch
from
bmahabirbu:docs/code-guidelines-ui-components
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| # UI Component Development Guide for Kortex | ||
|
|
||
| ## Core Rules | ||
|
|
||
| ### 1. Check `@podman-desktop/ui-svelte` before building from scratch | ||
|
|
||
| Before creating any new UI component, **always check `@podman-desktop/ui-svelte` first**. This is the shared component library that Kortex builds on. Only build custom components when nothing in this library fits. | ||
|
|
||
| **Available components from `@podman-desktop/ui-svelte`:** | ||
|
|
||
| | Component | Purpose | | ||
| | ------------------------------------------------------------------------------ | ------------------- | | ||
| | `Button`, `CloseButton`, `Expandable` | Button variants | | ||
| | `Input`, `NumberInput`, `SearchInput` | Form inputs | | ||
| | `Checkbox` | Checkboxes | | ||
| | `Dropdown`, `DropdownMenu` | Selection menus | | ||
| | `Table`, `TableColumn`, `TableRow`, `TableSimpleColumn`, `TableDurationColumn` | Data tables | | ||
| | `DetailsPage`, `FormPage`, `NavPage`, `Page` | Page layouts | | ||
| | `Modal` | Modal dialogs | | ||
| | `Tab` | Tab navigation | | ||
| | `Tooltip` | Tooltips | | ||
| | `Link` | Styled links | | ||
| | `Spinner`, `LinearProgress` | Loading indicators | | ||
| | `StatusIcon` | Status indicators | | ||
| | `EmptyScreen`, `FilteredEmptyScreen` | Empty state views | | ||
| | `ErrorMessage` | Error alerts | | ||
| | `Carousel` | Carousel | | ||
| | `ListOrganizer` | List management | | ||
| | `SettingsNavItem` | Settings navigation | | ||
|
|
||
| **Icons** are available from `@podman-desktop/ui-svelte/icons` (see rule 3 below). | ||
|
|
||
| **Priority order when building UI:** | ||
|
|
||
| 1. Use a component from `@podman-desktop/ui-svelte` | ||
| 2. Use an existing Kortex shared component (see rule 4) | ||
| 3. Extend an existing component if close but not quite right | ||
| 4. Only build from scratch as a last resort | ||
|
|
||
| ### 2. Never use Tailwind colors directly | ||
|
|
||
| **Never use raw Tailwind color classes** like `bg-red-500`, `text-gray-700`, `border-blue-300`, etc. | ||
|
|
||
| Always use CSS variables from the color-registry so that values can be tuned by themes (light/dark mode and custom themes). | ||
|
|
||
| Format: `[var(--pd-<color-name>)]` | ||
|
|
||
| ```svelte | ||
| <!-- WRONG --> | ||
| <div class="bg-gray-800 text-white border-purple-500">...</div> | ||
|
|
||
| <!-- CORRECT --> | ||
| <div class="bg-[var(--pd-content-bg)] text-[var(--pd-content-text)] border-[var(--pd-content-divider)]">...</div> | ||
| ``` | ||
|
|
||
| Non-color Tailwind utilities (layout, spacing, sizing, typography, borders, effects) are fine. | ||
|
|
||
| ### 3. Use the Icon component for all icons | ||
|
|
||
| Use the `Icon` component from `@podman-desktop/ui-svelte/icons` instead of inline SVGs, custom icon wrappers, or direct `<Fa>` usage. | ||
|
|
||
| ```svelte | ||
| <script lang="ts"> | ||
| import { Icon } from '@podman-desktop/ui-svelte/icons'; | ||
| import { faGear } from '@fortawesome/free-solid-svg-icons'; | ||
| </script> | ||
|
|
||
| <!-- CORRECT --> | ||
| <Icon icon={faGear} size="xs" /> | ||
|
|
||
| <!-- WRONG: inline SVG --> | ||
| <svg viewBox="0 0 512 512"><path d="M..."/></svg> | ||
|
|
||
| <!-- WRONG: direct Fa usage --> | ||
| <Fa icon={faGear} /> | ||
| ``` | ||
|
|
||
| The Icon component supports: | ||
|
|
||
| - FontAwesome `IconDefinition` objects (via `<Fa>` internally) | ||
| - Font class icon strings (`fas fa-*`, `far fa-*`, `fab fa-*`, or `-icon` suffix) | ||
| - Data URI images (strings starting with `data:image/`) | ||
| - Svelte Components | ||
|
|
||
| ### 4. Reuse existing Kortex Svelte components | ||
|
|
||
| If `@podman-desktop/ui-svelte` doesn't have what you need, check Kortex's own shared components before building from scratch: | ||
|
|
||
| **Primary shared component locations:** | ||
|
|
||
| - `packages/renderer/src/lib/ui/` — Core UI components (~50 components) | ||
| - `packages/renderer/src/lib/button/` — Button components | ||
| - `packages/renderer/src/lib/table/` — Table components | ||
| - `packages/renderer/src/lib/modal/` — Modal dialogs | ||
| - `packages/renderer/src/lib/forms/` — Form components | ||
| - `packages/renderer/src/lib/dialogs/` — Dialog components | ||
| - `packages/renderer/src/lib/appearance/` — Theme/appearance components | ||
|
|
||
| **Key reusable components include:** | ||
|
|
||
| | Component | File | Purpose | | ||
| | ----------------- | ------------------------------- | ---------------------------- | | ||
| | `Badge` | `lib/ui/Badge.svelte` | Status badges and labels | | ||
| | `Button` | `lib/button/Button.svelte` | Standard buttons | | ||
| | `DetailsPage` | `lib/ui/DetailsPage.svelte` | Detail view layouts | | ||
| | `FormPage` | `lib/ui/FormPage.svelte` | Form page layouts | | ||
| | `Label` | `lib/ui/Label.svelte` | Form labels | | ||
| | `SlideToggle` | `lib/ui/SlideToggle.svelte` | Toggle switches | | ||
| | `Typeahead` | `lib/ui/Typeahead.svelte` | Autocomplete inputs | | ||
| | `StatusDot` | `lib/ui/StatusDot.svelte` | Status indicators | | ||
| | `Steps` | `lib/ui/Steps.svelte` | Step-by-step wizards | | ||
| | `WarningMessage` | `lib/ui/WarningMessage.svelte` | Warning banners | | ||
| | `FileInput` | `lib/ui/FileInput.svelte` | File upload inputs | | ||
| | `PasswordInput` | `lib/ui/PasswordInput.svelte` | Password fields | | ||
| | `CopyToClipboard` | `lib/ui/CopyToClipboard.svelte` | Clipboard copy functionality | | ||
|
|
||
| Always search for existing components before creating new ones. If an existing component is close but not quite right, prefer extending it over duplicating it. | ||
|
|
||
| ## How the Color Registry Works | ||
|
|
||
| Colors are defined in `packages/main/src/plugin/color-registry.ts` in the `initColors()` method, organized by category. | ||
|
|
||
| ### Finding the right color variable | ||
|
|
||
| 1. Open `packages/main/src/plugin/color-registry.ts` | ||
| 2. Find the appropriate category in `initColors()` (e.g. `initButton()`, `initInput()`, `initTable()`) | ||
| 3. Each category has a prefix constant (e.g. `const button = 'button-';`) | ||
| 4. The CSS variable name is `--pd-` + prefix + specific name | ||
|
|
||
| ### Common color categories and prefixes | ||
|
|
||
| | Category | Prefix | Example variable | Usage | | ||
| | ---------- | -------------- | ------------------------ | ---------------------- | | ||
| | Content | `content-` | `--pd-content-bg` | Page backgrounds, text | | ||
| | Button | `button-` | `--pd-button-primary-bg` | Button colors | | ||
| | Input | `input-field-` | `--pd-input-field-bg` | Form input colors | | ||
| | Table | `table-` | `--pd-table-header-bg` | Table styling | | ||
| | Modal | `modal-` | `--pd-modal-bg` | Modal dialogs | | ||
| | Card | `card-` | `--pd-card-bg` | Card components | | ||
| | Tab | `tab-` | `--pd-tab-active-bg` | Tab navigation | | ||
| | Status | `status-` | `--pd-status-running` | Status indicators | | ||
| | Navigation | `global-nav-` | `--pd-global-nav-bg` | Navigation bars | | ||
|
|
||
| ### Example: Styling a new component | ||
|
|
||
| ```svelte | ||
| <script lang="ts"> | ||
| import { Button } from '@podman-desktop/ui-svelte'; | ||
| import { Icon } from '@podman-desktop/ui-svelte/icons'; | ||
| import { faPlus } from '@fortawesome/free-solid-svg-icons'; | ||
| </script> | ||
|
|
||
| <div class="bg-[var(--pd-content-bg)] text-[var(--pd-content-text)] p-4 rounded-lg"> | ||
| <h2 class="text-[var(--pd-content-header)]">Title</h2> | ||
| <p class="text-[var(--pd-content-text)]">Description</p> | ||
|
|
||
| <Button on:click={handleAction}> | ||
| <Icon icon={faPlus} size="xs" /> | ||
| Add Item | ||
| </Button> | ||
| </div> | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,101 @@ import { WinPlatform } from './win-platform'; | |
| import type { WSL2Check } from '../checks/windows/wsl2-check'; | ||
| ``` | ||
|
|
||
| ### UI Colors | ||
|
|
||
| Never use raw Tailwind color classes (e.g. `bg-red-500`, `text-gray-700`, `border-blue-300`) directly. Always use CSS variables from the color-registry so values can be tuned by themes (light/dark mode and custom themes). | ||
|
|
||
| Format: `[var(--pd-<color-name>)]` | ||
|
|
||
| ✅ **Use this pattern:** | ||
|
|
||
| ```svelte | ||
| <div class="bg-[var(--pd-content-bg)] text-[var(--pd-content-text)]">...</div> | ||
| <Button class="bg-[var(--pd-button-primary-bg)]"/> | ||
| ``` | ||
|
|
||
| 🚫 **Instead of:** | ||
|
|
||
| ```svelte | ||
| <div class="bg-gray-800 text-white">...</div> | ||
| <Button class="bg-purple-500"/> | ||
| ``` | ||
|
|
||
| Non-color Tailwind utilities (layout, spacing, sizing, typography, borders, effects) are fine to use directly. | ||
|
|
||
| To find the right color variable: | ||
|
|
||
| 1. Open `packages/main/src/plugin/color-registry.ts` | ||
| 2. Find the appropriate category in `initColors()` (e.g. `initButton()`, `initInput()`, `initTable()`) | ||
| 3. Each category has a prefix constant (e.g. `const button = 'button-';`) | ||
| 4. The CSS variable is `--pd-` + prefix + specific name (e.g. `--pd-button-primary-bg`) | ||
|
|
||
| ### Usage of `@podman-desktop/ui-svelte` components | ||
|
|
||
| Before creating any new UI component from scratch, **always check `@podman-desktop/ui-svelte` first**. This is the shared component library that Kortex builds on. Available components: | ||
|
|
||
| | Component | Import | Purpose | | ||
| | ------------------------------------------------------------------------------ | --------------------------------- | ---------------------- | | ||
| | `Button`, `CloseButton`, `Expandable` | `@podman-desktop/ui-svelte` | Button variants | | ||
| | `Input`, `NumberInput`, `SearchInput` | `@podman-desktop/ui-svelte` | Form inputs | | ||
| | `Checkbox` | `@podman-desktop/ui-svelte` | Checkboxes | | ||
| | `Dropdown`, `DropdownMenu` | `@podman-desktop/ui-svelte` | Selection menus | | ||
| | `Table`, `TableColumn`, `TableRow`, `TableSimpleColumn`, `TableDurationColumn` | `@podman-desktop/ui-svelte` | Data tables | | ||
| | `DetailsPage`, `FormPage`, `NavPage`, `Page` | `@podman-desktop/ui-svelte` | Page layouts | | ||
| | `Modal` | `@podman-desktop/ui-svelte` | Modal dialogs | | ||
| | `Tab` | `@podman-desktop/ui-svelte` | Tab navigation | | ||
| | `Tooltip` | `@podman-desktop/ui-svelte` | Tooltips | | ||
| | `Link` | `@podman-desktop/ui-svelte` | Styled links | | ||
| | `Spinner`, `LinearProgress` | `@podman-desktop/ui-svelte` | Loading indicators | | ||
| | `StatusIcon` | `@podman-desktop/ui-svelte` | Status indicators | | ||
| | `EmptyScreen`, `FilteredEmptyScreen` | `@podman-desktop/ui-svelte` | Empty state views | | ||
| | `ErrorMessage` | `@podman-desktop/ui-svelte` | Error alerts | | ||
| | `Carousel` | `@podman-desktop/ui-svelte` | Carousel | | ||
| | `ListOrganizer` | `@podman-desktop/ui-svelte` | List management | | ||
| | `SettingsNavItem` | `@podman-desktop/ui-svelte` | Settings navigation | | ||
| | `Icon` | `@podman-desktop/ui-svelte/icons` | Unified icon rendering | | ||
|
Contributor
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. Maybe I would add some refference here to something more dynamic and not hardcoded, but we can iterate on this |
||
|
|
||
| ### Usage of Icon component | ||
|
|
||
| Use the `Icon` component from `@podman-desktop/ui-svelte/icons` for rendering icons. The Icon component supports FontAwesome `IconDefinition` objects, font class strings (`fas fa-*`, `far fa-*`, `fab fa-*`), data URI images, and Svelte components. | ||
|
|
||
| ✅ **Use this pattern:** | ||
|
|
||
| ```svelte | ||
| <script lang="ts"> | ||
| import { Icon } from '@podman-desktop/ui-svelte/icons'; | ||
| import { faGear } from '@fortawesome/free-solid-svg-icons'; | ||
| </script> | ||
|
|
||
| <Icon icon={faGear} size="xs" /> | ||
| ``` | ||
|
|
||
| 🚫 **Instead of:** | ||
|
|
||
| ```svelte | ||
| <!-- Don't use raw SVG paths or custom icon wrappers --> | ||
| <svg viewBox="0 0 512 512"><path d="M..."/></svg> | ||
|
|
||
| <!-- Don't use inline Fa components directly --> | ||
| <Fa icon={faGear} /> | ||
|
|
||
| <!-- Don't use raw class strings --> | ||
| <i class="fas fa-gear"></i> | ||
| ``` | ||
|
|
||
| ### Reuse existing Kortex Svelte components | ||
|
|
||
| If `@podman-desktop/ui-svelte` doesn't have what you need, check Kortex's own shared components before building from scratch: | ||
|
|
||
| - `packages/renderer/src/lib/ui/` — Kortex-specific UI components (Badge, CopyToClipboard, StatusDot, Steps, SlideToggle, Typeahead, etc.) | ||
| - `packages/renderer/src/lib/button/` — Button components | ||
| - `packages/renderer/src/lib/table/` — Table components | ||
| - `packages/renderer/src/lib/modal/` — Modal dialogs | ||
| - `packages/renderer/src/lib/forms/` — Form components | ||
| - `packages/renderer/src/lib/dialogs/` — Dialog components | ||
|
|
||
| If an existing component is close but not quite right, prefer extending it over duplicating it. | ||
|
|
||
| ### Svelte | ||
|
|
||
| On templates of Svelte components, avoid using inline code and arrow functions. Instead, call a function defined in the script part of the component. | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Keep color-registry button examples consistent with actual registered IDs.
This section repeats the same
button-example naming; once verified inpackages/main/src/plugin/color-registry.ts, please mirror the exact prefix/variable names here too, so both docs stay consistent.🤖 Prompt for AI Agents