Skip to content

Latest commit

 

History

History
301 lines (227 loc) · 15 KB

CONTRIBUTING.md

File metadata and controls

301 lines (227 loc) · 15 KB

Contributing Guide

Directory Structure

Directory Description
src Theme generation framework and utilities
src/core Theme generation framework (CSS vars, syntax highlighting styles)
src/functions Theme utilities (color calculations, etc.)
src/palette Theme palettes (GitHub / Gitea / Catppuccin)
src/types Theme color variable type definitions
src/vite-plugin Theme Vite build plugin
styles Theme style overrides
styles/common Reusable CSS style fragments
styles/public Base element or cross-page element styles
styles/components Page-specific styles
styles/templates Template-specific styles
themes Color theme definitions
primer Auto-generated Primer design tokens
scripts Build and utility scripts
templates Gitea template overrides (optional)
gitea Upstream Gitea reference files
screenshots Theme screenshots

Contribution Notes

Style contributions are not recommended, as Gitea themes are ultimately delivered as a single CSS file, which introduces issues like ordering/override conflicts and broad-reaching style impacts.

Each developer has their own approach, making it difficult for review to catch these issues, greatly increasing maintenance difficulty.

If you have confirmed understanding of Gitea's style layout and the project's approach, please first file an Issue to confirm scope and expected results, then develop and submit a PR.

If you believe you have a better approach, feel free to submit an Issue.

Important

When submitting a PR, please run bun commit

Pull Requests and Release Notes

Submit changes through a pull request targeting dev, or stacked on another pull request; checks run for both. A merged pull request lands in the release draft as * <title> ([#<number>](<url>)), under the category of its label. The draft is written for the people who install the theme, so the title and the label decide what they read.

Titles

  • Use the strict format Area: Description, with a past-tense description of what changed for the reader: Introduced, Changed, Fixed, Removed.
  • Describe the effect, not the implementation: Branches: Fixed the pull request column on phones, not Branches: Changed branch.css.
  • The draft sorts by the exact area, so spell an area exactly as listed below.

Areas: Actions, Auth, Branches, Code, Commits, Dashboard, Editor, Explore, Forks, Forms, Insights, Issues, Labels, Milestones, Navbar, Notifications, Organizations, Packages, Profile, Projects, Pull requests, Releases, Repository, Settings, Teams, Templates, Themes.

Reuse an existing area whenever one fits; add a new area only for a page people recognise by that name, and add it to this list in the same pull request. Never use file, component or style names as an area.

Labels

Label Use for Draft section
feature a page, control or theme that is new to users What’s new
change a changed look, template or compatibility Enhancements
bug a fix for a bug that shipped in a release Fixes
dependencies a dependency or build-tool update Dependencies
skip-changelog anything a reader of the release would not notice not listed

Apply exactly one of them; the pull request metadata check enforces it with the title format. A fix for a bug that only existed on dev is skip-changelog. Add major when admins must act on upgrade, for example a new minimum Forgejo version; it raises the major version and does not add a section. suggestion marks an idea that has not been decided on yet.

Release notes and screenshots

The summary and the compatibility section at the top of the draft come from .github/release-notes.md when its front matter names the version the draft resolves to. Update it in the pull request that needs upgrade steps or warnings, instead of editing the draft.

A pull request that changes how a page looks shows it in a Before and after table in its description: the same page, viewport and state, captured in the dev preview.

Development Environment

The theme depends on the Bun runtime. Please ensure Bun is installed in your environment. Bun 1.3.14 or later is recommended.

Please use VSCode for development and install the recommended extensions in the repository.

If you prefer fewer extensions, you must install the vscode-styled-components extension, which is used for rendering and checking CSS template strings in TypeScript.

VSCode 1.102.0 or later is recommended for development, as this version and above support hex color rendering in TypeScript code.

Development Workflow

Install Dependencies

bun install

Set Environment Variables

Create a .env file in the project root. Refer to .env.example for available variables.

Environment variables are used to send compiled themes to a server for quick preview.

Compile Themes

Compile and sync to remote server for preview:

bun bundle:dev

Compile all themes:

bun bundle

Format project code:

bun fmt

For PR submission — check and compile all project code with formatting:

bun commit

Development Conventions

src, styles, and themes are the project's main directories.

When referencing across modules, use package exports paths. For example: import { defineTheme } from "@lutinglt/gitea-github-theme/core"

When referencing files within the same module, use relative paths. For example: import { defineTheme } from "./theme"

Color Theme Contributions

Theme file naming format: themeName.ts, used together with theme.config.ts registration.

If a theme has both dark and light variants, the framework automatically generates an auto color theme.

The project accepts custom themes and will include them in published releases, but the project owner does not participate in their maintenance or review.

Please add your author info at the top of the color theme file so Issue reporters can @ mention you.

It is recommended to use defineTheme with the ThemeColor type to define theme colors. The framework will automatically compute and generate all Gitea CSS variables.

Color calculation functions can be imported from @lutinglt/gitea-github-theme/core (scaleColorLight, rgba), or use the color2k library for additional color manipulation.

Example: themes/my-theme.ts

/**
 * @author your-name
 * @description theme description
 */
import { defineTheme, scaleColorLight } from "@lutinglt/gitea-github-theme/core";
import type { ThemeColor, Syntax } from "@lutinglt/gitea-github-theme/core";

const themeColor: ThemeColor = {
  isDarkTheme: true,
  primary: "#0969da",
  primaryContrast: "#f0f6fc",
  secondary: "#30363d",
  base: { red: "#f85149", orange: "#d29922" /* ... */ },
  console: {
    /* ... */
  },
  diff: {
    /* ... */
  },
  other: {
    /* ... */
  },
  github: {
    /* ... */
  },
};

const syntaxColor: Syntax = {
  /* Custom code highlight colors, or import from another theme */
};

export default defineTheme({ colorType: "theme", themeColor, syntaxColor });

To use Gitea's native color format, use colorType: "gitea" with the GiteaColor type:

import type { GiteaColor, Syntax } from "@lutinglt/gitea-github-theme/core";
import { defineTheme } from "@lutinglt/gitea-github-theme/core";

const giteaColor: GiteaColor = {
  /* ... */
};
const syntaxColor: Syntax = {
  /* ... */
};
export default defineTheme({ colorType: "gitea", themeColor: giteaColor, syntaxColor });

After completing theme color development, register the theme series in theme.config.ts, compile it, and take screenshots in a Gitea instance. Place them in the screenshots directory with filenames matching the theme names. (Cloning the repository is recommended to avoid leaking personal information.)

Then add screenshot information to README.md.

For color reuse patterns, see the colorblind theme implementation in themes/github.ts.

Theme Style Contributions

Theme styles use the css() template string for development. Strings are processed by LightningCSS and support CSS nesting syntax. Do not use SCSS functions; for complex processing, use TypeScript libraries such as the bundled color2k library.

For complex logic, it is recommended to extract it into functions under the src/functions directory.

Reuse shared page controls

Use components/common/*/*.css for sidebars, search fields, selects, counters, switches, empty states, and compact buttons, and components/common/dropdown/* for dropdown variants. templates/base/head_navbar.tmpl loads the shared styles and controllers for all pages. Keep page layout rules in the page stylesheet and pass the page's existing routes, permissions, and form values into the shared controls.

  • Sidebar: add theme-sidebar-layout and a unique data-theme-sidebar storage key to the page, then use theme-sidebar, theme-sidebar-content, and theme-sidebar-main for its children. Include shared/theme/sidebar_toggle inside the sidebar and a button with data-theme-sidebar-toggle and data-theme-sidebar-expand beside the page title. The controller preserves desktop collapse preferences and starts collapsed on mobile. See templates/repo/issue/sidebar.tmpl and templates/org/repository_nav.tmpl.
  • Search: call components/common/search/search with Value and Placeholder inside the existing form; do not write a search input in a page template. Kind selects the variant: submit (default, trailing search button), icon (leading search icon, as on releases and Actions), or plain. Name defaults to q, Label overrides the accessible name, and Class adds a page layout hook to the field. For a client-side filter that is never submitted, pass Local with an ID for its controller. Keep hidden filter inputs in the form and size the field from the page stylesheet through its Class or parent; an unconstrained wrapper can shrink it. A control built by a script uses the theme-search-field class directly. Forgejo's native query/mode/submit group (shared/search/combo_multi) opts in with theme-search-control on its form.
  • Dropdowns: call components/common/dropdown/dropdown with Kind (single, multiple, or actions), Label, Items (the content template name), and Data (the page context). Title, Icon, IconOnly, UpdateLabel, and Quiet customize the header and trigger. Use components/common/dropdown/option for radio or checkbox rows; action rows are links or buttons with theme-dropdown-action. Single-choice menus use checkmarks, multiple-choice menus use native checkboxes, and action menus omit selection indicators. The controller handles Escape, outside clicks, and opening one menu at a time. See components/repository/filter/filter, components/repository/sort/sort, and org/action_menu_items.
  • Buttons: keep Forgejo's native ui button classes on buttons Forgejo already renders; the theme styles those globally. For a button the theme adds, use button theme-control (32px, 12px inline padding) instead of sizing it in a page stylesheet, with theme-control-wide for the 16px padding GitHub uses on profile pages or theme-control-small for 28px controls. Use theme-icon-button only for icon-only controls. Keep native primary, secondary, and permission checks on actions, and leave page stylesheets to layout such as flex and order.
  • Counter: add theme-counter to a count pill next to a tab, heading, or filter, including ones a script creates. Add theme-counter-tab inside a tab, where GitHub's counter is 18px tall and semibold. Keep only layout (margin, flex) under the page's own class.
  • Segmented switch: use <nav class="theme-switch"> with links and active on the current one, as on the releases and tags pages.
  • Empty state: use theme-empty for a bordered "nothing here" box holding an icon, an h2 or h3, and an optional paragraph. templates/user/profile_empty.tmpl renders one from Icon, Title, and Description. Add theme-empty-compact for the smaller, borderless block GitHub shows inside a list. Short inline messages inside a list or menu stay plain text.
  • Label: use Forgejo's native ui basic label for outline labels such as visibility or package type; do not build a page-specific pill.
  • Select: wrap a native <select class="theme-select"> in <span class="theme-select-wrap">. The options stay in the page template. See templates/user/profile_packages.tmpl.

For repository filtering, add data-theme-repository-search to the form and render components/repository/results/results after it. repository-search.js updates that result fragment through the same server-rendered GET route, preserves search and sort values, and cancels obsolete requests. Checkbox criteria combine, while opposing values of one criterion are exclusive. Clear filters is an action, not a selectable option. Keep tab=overview or tab=repositories in the organization form; query parameters alone do not determine the page layout. Use org/repository_pagination so pagination retains the same view even without the enhancement script. Errors leave the previous results visible and display a retry message; browser history restores the server-rendered controls and results.

After changing a component, verify each consuming page at desktop and mobile widths. Check search submission, retained filters, sidebar focus and collapse behavior, and Escape/outside-click dismissal for select menus.

Use theme tokens

All colors used in theme styles must use color variables. Import them via import { themeVars } from "@lutinglt/gitea-github-theme/core".

When using theme-specific color variables like ${themeVars.github.xxx}, please add the file and variable to the corresponding variable's comment in src/types/color/github.

For small border-radius values (6px), use the global border-radius variable. Import via import { otherThemeVars } from "@lutinglt/gitea-github-theme/core" and use ${otherThemeVars.border.radius}.