Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 11 additions & 1 deletion .agents/skills/pick-issue-to-pr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,17 @@ git commit --amend --no-edit # or adjust the message if the scope changed
git push --force-with-lease
```

- Reply to the review threads where useful.
- Reply to each review thread (`mcp__github__add_reply_to_pull_request_comment`, or `gh api`) saying what you did.

#### Resolve only what is actually resolved

After replying, **resolve a thread only when its feedback is fully addressed in the pushed commit** and you are confident the change satisfies it. Resolving has no direct MCP or `gh pr` command; use the GraphQL `resolveReviewThread` mutation, keyed on the **thread node id** (the `id` field like `PRRT_…` from `get_review_comments`, _not_ a comment id):

```bash
gh api graphql -f query='mutation($t:ID!){ resolveReviewThread(input:{threadId:$t}){ thread { isResolved } } }' -f t="PRRT_…"
```

**Leave the thread open for the reviewer whenever you are not closing the loop yourself**: replying with a question, pushing back or proposing an alternative not yet agreed, only partially addressing it, or deferring it to a follow-up. When in doubt, leave it open. Never resolve a thread you have not replied to.

Repeat until the PR is approved. **The branch ends with a single commit, always.**

Expand Down
83 changes: 83 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Contributing to Ippon UI

Thanks for taking the time to contribute. Ippon UI is a monorepo of independently
published packages (`@ippon-ui/styles`, `@ippon-ui/react`, `@ippon-ui/icons`).
This guide covers the shared workflow; each package has its own guide for the
conventions specific to it.

## Ownership

Every contributor is responsible for the code they submit: its quality, its tests,
and following it through review until it is merged. A pull request is not "thrown
over the wall" — you own it from the first commit to the merge, including
addressing review feedback and keeping it green in CI.

## Opening an issue

Issues are the source of truth for the work to be done. Before opening one:

- Search the [existing issues](https://github.com/ippontech/ui/issues) to avoid
duplicates.
- For a bug, describe the context, the expected behaviour, the actual behaviour,
and how to reproduce it.
- For a change or a new component, describe the need and the intended scope.

Keep an issue focused on a single concern: one issue, one change.

## Getting set up

This repository uses [mise](https://mise.jdx.dev) to manage tooling and tasks.
From the monorepo root:

```sh
mise trust # trust the local mise configuration
mise install # install the pinned tools (Node, pnpm, Tikui CLI)
mise setup # install dependencies
```

See the [README](./README.md) for the full list of tasks.

## Workflow

1. Pick or open an issue and assign it to yourself.
2. Create a branch from `main`.
3. Write the code in English (comments, identifiers, documentation).
4. Before committing, run:

```sh
mise format # format the code
mise lint # lint and auto-fix
mise test-unit-ci # run the unit tests
```

A pre-commit hook (lefthook) also checks formatting (Prettier) and SCSS
(Stylelint) on staged files.

## Commits

Commits follow [Conventional Commits](https://www.conventionalcommits.org):
`feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `test:`… Reference the issue in
the body or footer when relevant.

## Pull requests

- Target the `main` branch — never push to it directly.
- Open the pull request as a draft until it is ready for review.
- Keep it scoped to a single issue and link the issue with `Closes #<number>`.
- Make sure CI is green before requesting a review.

## Package guides

Each package documents its own conventions:

- [`styles/CONTRIBUTING.md`](./styles/CONTRIBUTING.md) — Pattern Library: Atomic
Design, CAP, tokens and quarks.
- [`react/CONTRIBUTING.md`](./react/CONTRIBUTING.md) — Component Library: React
components wrapping the Pattern Library.
- [`icons/CONTRIBUTING.md`](./icons/CONTRIBUTING.md) — icon font generated from
Ionicons.

## License

By contributing, you agree that your contributions are licensed under the
[Apache-2.0](./LICENSE) license.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ Common tasks:

See [`AGENTS.md`](./AGENTS.md) for the monorepo structure and conventions.

## Contributing

See [`CONTRIBUTING.md`](./CONTRIBUTING.md) for how to open an issue, the
development workflow, and the per-package guides.

## License

[Apache-2.0](./LICENSE) © Ippon Technologies
43 changes: 43 additions & 0 deletions icons/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Contributing to `@ippon-ui/icons`

This package generates an icon font from [Ionicons](https://ionic.io/ionicons).
It is a build step, not a hand-written collection: it ships the compiled font,
its stylesheet and the TypeScript types of every available icon name.

Read the repository's root `CONTRIBUTING.md` first for the shared workflow
(issues, branches, commits, pull requests).

## How it works

`index.ts` is the whole package. It:

1. Reads the SVG icons shipped by the `ionicons` dependency.
2. Categorises each icon (`logo-*`, `*-outline`, `*-sharp`, or filled) and
writes the `IconClassic`, `IconLogo` and `IconVariant` types to `types/`.
3. Fixes the SVGs and converts them to the `ionicons` font under `dist/`, with
the `ippon-ion` class-name prefix.

## Building

From the monorepo root:

```sh
mise icons-build # runs `node index.ts`
```

The generated `dist/` and `types/` are not committed. Most changes here mean
bumping the `ionicons` dependency (Renovate handles this) or adjusting the
generation in `index.ts`; rerun the build and check the produced types.

## What it produces

- A `dist/` folder with the `ionicons` web font and its stylesheet. Icons are
exposed as CSS classes prefixed with `ippon-ion` and support ligatures, so a
consuming application can render an icon from its name.
- A `types/index.d.ts` with the available icon names as types — `IconClassic`,
`IconLogo` and `IconVariant` (`'sharp' | 'outline'`) — to type props against
the existing icons.

## License

Contributions are licensed under [Apache-2.0](./LICENCE).
15 changes: 15 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ run = "pnpm test:unit:ci"
[tasks.styles-dev]
run = "pnpm --filter styles dev"

[tasks.styles-lint]
run = "pnpm --filter styles lint"

[tasks.styles-test-unit-ci]
run = "pnpm --filter styles test:unit:ci"

[tasks.react-lint]
run = "pnpm --filter react lint"

[tasks.react-test-unit-ci]
run = "pnpm --filter react test:unit:ci"

[tasks.icons-build]
run = "pnpm --filter icons build"

[tasks.styles-create-component]
dir="styles"
description="Create a style components using Tikui CLI"
Expand Down
86 changes: 86 additions & 0 deletions react/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Contributing to `@ippon-ui/react`

The React Component Library provides the **mechanical** part of each component:
React components that render the Pattern Library markup and expose typed props.
The Pattern Library owns the markup, the CSS classes and the visual states; refer
to its documentation for the classes and structure to use, and follow its CAP
convention (Component Alternative Part), tokens and Atomic Design hierarchy.

Read the repository's root `CONTRIBUTING.md` first for the shared workflow
(issues, branches, commits, pull requests).

## File organisation

Each component is made of:

- **Component**: `react/src/Ippon<ComponentName>.tsx` (PascalCase).
- **Test**: `react/test/Ippon<ComponentName>.spec.tsx`.
- **Export**: added to `react/src/index.ts`.

## Component conventions

```tsx
import type { DataSelectableWithChildren } from './DataSelectable.ts';
import { clsx } from 'clsx';
import { optionalToAlternativeClass } from './CAP.ts';

type IpponComponentProps = DataSelectableWithChildren<{
alternative?: 'primary' | 'secondary';
}>;

export const IpponComponent = (props: IpponComponentProps) => (
<div
className={clsx('ippon-component', optionalToAlternativeClass(props.alternative))}
data-selector={props.dataSelector}
>
<span className="ippon-component--label">{props.children}</span>
</div>
);
```

- Extend `DataSelectable<T>` (no children) or `DataSelectableWithChildren<T>`
Comment thread
Gnuk marked this conversation as resolved.
(with children); both provide `dataSelector?: string`.
- `data-selector` exposes the element so it can be targeted in tests
(Testing Library is configured with `testIdAttribute: 'data-selector'`); always
forward it.
- Use the types from `Tokens.ts` for colours and sizes (e.g.
`IpponTokenTextColor`, `IpponTokenSize`).
- Model CAP **alternatives** as union types and booleans like `border` as
optional props.
- Build class names with `clsx()` and the helpers from `CAP.ts`:
`optionalToAlternativeClass('primary')` → `'-primary'`,
`optionalToPrefixedAlternativeClass('shadow')('l1')` → `'-shadow-l1'`,
`toAlternativeClass(value)` (non-optional).

For a CAP **part** (`ippon-component--part`) with significant props, create a
dedicated sub-component and export both from the same file:

```tsx
type IpponComponentLabelProps = DataSelectableWithChildren<{
alternative?: 'strong';
}>;

export const IpponComponentLabel = (props: IpponComponentLabelProps) => (
<span
className={clsx('ippon-component--label', optionalToAlternativeClass(props.alternative))}
data-selector={props.dataSelector}
>
{props.children}
</span>
);
```

## Tests

Tests use Vitest and Testing Library and live in `react/test/`. Each test should
verify the base class name, every alternative, children rendering, the
`data-selector` binding, and any custom tag support. From the monorepo root:

```sh
mise react-lint # ESLint
mise react-test-unit-ci # Vitest
```

## License

Contributions are licensed under [Apache-2.0](./LICENCE).
112 changes: 112 additions & 0 deletions styles/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Contributing to `@ippon-ui/styles`

The Pattern Library represents the **visual** part of each component as SCSS/CSS:
the rendering and the states, not the mechanical behaviour. It is built with
[Tikui](https://tikui.org) and documents every component so any web application
can consume it, regardless of its technology.

Read the repository's root `CONTRIBUTING.md` first for the shared workflow
(issues, branches, commits, pull requests).

## Atomic Design

Components are organised following
[Atomic Design](https://atomicdesign.bradfrost.com), hierarchically composed:

- `atom/` — indivisible elements (button, badge, icon, text, title…).
- `molecule/` — groups of atoms (tabs, toggle, import-file…).
- `organism/` — groups of molecules (card, container, grid, header, modal…).
- `template/` — page layouts assembled from organisms, molecules and atoms.

`quark/` and `token/` hold the shared building blocks described below.

## CAP — Component Alternative Part

CSS classes follow the CAP convention:

- **Component**: the component name in `kebab-case` (`.ippon-button`).
- **Alternative**: an alternative or state, prefixed with `-` (`&.-primary`).
- **Part**: a part of the component, prefixed with `--` (`&--icon`).

```scss
.ippon-button {
&.-primary {
/* primary alternative */
}

&--icon {
/* icon part */
}
}
```

```html
<button class="ippon-button -primary">
<span class="ippon-button--icon">Icon</span>
<span class="ippon-button--text">Text</span>
</button>
```

## Tokens

A token is a style property (a colour, a font, a spacing…). It is a concept:
even when implemented with a CSS variable, do not confuse a token with a
variable. Tokens live in `token/`.

- **Base colours** carry a quantity from `100` to `900`
(`--ippon-color-green-500`). A base colour is never used directly by a
component.
- **Semantic colours** give a base colour a meaning (`positive` uses `green`)
and are grouped by usage: `surface`, `text-icon`, `border`, with alternatives
such as `primary`/`secondary` and `on-*` variants for content placed on a
surface (`--ippon-color-success-text-icon-on-primary`).

Components must use semantic colours, never base colours directly.

## Quarks

A quark is a portion of a component that cannot be used on its own (typically a
SCSS `@mixin`). Use a quark to share styling across components — for example a
`weights` mixin reused by both `Text` and `Title`. Quarks live in `quark/` and
produce no rendered output by themselves.

## Creating a component

Generate the scaffold with the Tikui CLI (from the monorepo root):

```sh
mise styles-create-component <component> --path <path>
Comment thread
Gnuk marked this conversation as resolved.
```

- `<component>` — name in `kebab-case` (e.g. `button-card`).
- `--path` — folder under `src/`, defaults to `atom`.
- The `ippon` prefix is applied automatically.

Each component is made of four files:

```
<component>/
<component>.mixin.pug
<component>.code.pug
<component>.render.pug
_<component>.scss
```

Document it by including its Markdown file where it should appear:

- `include:componentDoc(height=300) button/button.md` for atoms, molecules and
organisms (the optional `height` sizes the rendering).
- `include:templateDoc layout/layout.md` for templates.

## Checks

From the monorepo root:

```sh
mise styles-lint # Stylelint (auto-fix)
mise styles-test-unit-ci # Vitest + sass-true
```

## License

Contributions are licensed under [Apache-2.0](./LICENCE).
Loading