10 KiB
| description | paths | ||||
|---|---|---|---|---|---|
| Design-system generations (DS1/DS2/DS3), component pattern, KDoc & API conventions, storybook |
|
Design System
The app currently hosts three generations of the design system (DS) side by side. They differ by
folder, token set (colors / typography / dimensions), and the @Preview wrapper. Knowing which
generation a component belongs to is essential so you don't mix tokens or pull the wrong building blocks.
Three generations
| Generation | Folder | Colors | Typography | Dimensions | Preview wrapper |
|---|---|---|---|---|---|
| DS1 (legacy) | core/ui/src/main/java/com/tangem/core/ui/components/ |
TangemTheme.colors |
TangemTheme.typography |
TangemTheme.dimens |
TangemThemePreview |
| DS2 (redesign) | core/ui/src/main/java/com/tangem/core/ui/ds/ |
TangemTheme.colors2 |
TangemTheme.typography2 |
TangemTheme.dimens2 |
TangemThemePreviewRedesign |
| DS3 (target) | core/ui/src/main/java/com/tangem/core/ui/ds2/ |
TangemTheme.colors3 |
TangemTheme.typography3 |
TangemTheme.dimens2 |
TangemThemePreviewRedesign |
Mind the numbering mismatch: folder
dsis DS2, folderds2is DS3. Thecolors2/typography2tokens are@Deprecated(ReplaceWithcolors3/typography3).
- DS1 — the entire current app is built on it. Do not add new components here.
- DS2 — redesign components. A transitional generation; don't write new components in it, only maintain what already exists.
- DS3 — the newest design system; the whole app is being migrated to it. Build new DS components here.
Using DS3 in features
All DS3 components (folder ds2) may be used in features starting from app version 6.0. Before
6.0 they must not be used on product screens.
If a needed component does not yet exist in DS3, add it by analogy with the existing ones (see the pattern below).
DS3 component pattern
Study the existing components as references:
- Simple:
ds2/checkbox/TangemCheckmark.kt— single file, a public@Composablefunction +@Preview. - Composite:
ds2/button/—TangemButton.kt(public API),TangemButtonInternal.kt(private inner layout),TangemButtonExt.kt(variant / size tokens).
Pattern rules:
- Package & location.
com.tangem.core.ui.ds2.<component>, foldercore/ui/.../ds2/<component>/. The component name isTangem<Name>. - DS3 tokens only. Colors —
TangemTheme.colors3.*, text —TangemTheme.typography3.*, dimensions —TangemTheme.dimens2.*. Nocolors/colors2/ hardcoded values (literal dp/colors are acceptable only inside@Preview, where you add@Suppress("MagicNumber")). - Signature.
modifier: Modifier = Modifieris mandatory (defaulting toModifier, placed first among the optional params or right after the required ones). Express variants/sizes via a nestedenuminobject Tangem<Name>(likeTangemButton.Variant/TangemButton.Size), not boolean flags. - Accessibility. Pass
contentDescription, set theRole, markdisabled()insemantics, and handle focus/press state viainteractionSource. - KDoc + Figma link. Above the public function — KDoc describing behavior, every parameter, and a link to the Figma node (see the KDoc requirements below).
- Previews. Two
@Previews (Light + Dark viaUI_MODE_NIGHT_YES), wrapped inTangemThemePreviewRedesign { ... }, withTangemTheme.colors3.bg.primaryas the background. Preview helpers (PreviewRow,Section, etc.) are private in the same file. - Composite components (many variants / heavy layout) are split into 3 files like the button:
public
Tangem<Name>.kt, privateTangem<Name>Internal.kt, tokensTangem<Name>Ext.kt.
API conventions
Public properties live in the object
Any public type the component exposes — variant/size/role/align enums, status classes, constants —
is declared inside the namesake object Tangem<Name>, not as a top-level type. This keeps a single
Tangem<Name>.Variant / Tangem<Name>.Size / Tangem<Name>.Role namespace at the call site and
avoids polluting the package.
object TangemTopNavigation {
/** Horizontal alignment of the center content slot. */
enum class ContentAlign { Start, Center }
}
// usage: TangemTopNavigation.ContentAlign.Center
References: TangemTopNavigation.ContentAlign, TangemNavigationText.Role, TangemButton.Variant /
TangemButton.Size.
Provide convenient overloads
A component should ship ergonomic overloads so callers don't assemble boilerplate for the common case. Two acceptable shapes:
- Additional
@Composable funoverloads with simpler parameters that delegate to the base one.TangemTopNavigationhas a low-level slot-based overload (startButton/endButton/contentColumnlambdas) plus several high-level overloads takingtitle/subtitle/onBack/onClosethat wire the predefined buttons and the title/subtitle center for you. - Extension functions on the
objectfor named presets — e.g.@Composable fun TangemButton.Back(…)andTangemButton.Close(…)inTangemButtonExt.ktexpose ready-made button presets while reading asTangemButton.Back { … }at the call site.
Each overload keeps the same rules as the base component (modifier first among optionals, DS3 tokens,
its own KDoc — see below).
Sub-components are first-class
Internal building blocks that are themselves public (e.g. TangemNavigationText, used for the
TangemTopNavigation title/subtitle slots) follow the exact same rules as a top-level component:
DS3 tokens only, modifier: Modifier = Modifier, public properties in their own object
(TangemNavigationText.Role), full KDoc, and their own Storybook entry where it makes sense. Don't
treat "helper" composables as second-class — if a feature can call it, it is a documented DS component.
KDoc requirements for components
Every public DS component (and any non-trivial public composable) must carry a KDoc block. Use
ds2/button/TangemButton.kt and ds2/checkbox/TangemCheckmark.kt as the canonical examples.
A component KDoc must contain, in order:
- Summary line. One sentence stating what the component is and which generation it belongs to —
start with
Design-system v2 …for DS3 components (matches the existing wording). - Figma link. A markdown link to the exact Figma node:
[Figma](https://www.figma.com/design/…?node-id=…). A component without a Figma reference is not review-ready. - Behavior notes (when behavior is non-obvious). A short prose paragraph or a bulleted
Behavior notes:list covering state-dependent rendering — loading, disabled/enabled, icon-only vs. labeled, focus ring, animations, what overrides what. Describe observable behavior, not the implementation. @paramfor every parameter. No parameter may be left undocumented — includingmodifierwhen its effect is non-trivial (e.g. "PassModifier.fillMaxWidth()to switch to fixed-width layout"). Each@paramstates the meaning and the consequences of notable values (null→ non-interactive,false→ dimmed & clicks ignored, etc.).- Accessibility guidance where relevant — e.g. when
contentDescriptionshould be supplied (icon-only buttons, loading state, disabled state) and what it announces.
Additional rules:
- Document the nested
enums (Variant,Size,Status, …) too: a short KDoc on the enum and, where the options aren't self-explanatory, a one-line description per entry (seeTangemButton.Variant). - Keep KDoc about contract and behavior, not internals. Implementation comments explaining why
a specific approach was taken belong to inline
//comments inside the body, not the KDoc. - Reference other DS types with
[TangemSurface]/[TangemButton.Variant]link syntax so they resolve in the IDE. - Detekt enforces missing-KDoc-on-public-API style checks on
core:ui; run./gradlew :core:ui:detektMain.
Storybook
Add every DS3 component to the Storybook (module features/tester) — a live on-device/emulator
component gallery (Tester → Storybook → DS Components).
Use the add-storybook-component skill — it wires the entity, the Build factory, the Composable
page, and registers it in the correct list. Run: /add-storybook-component TangemCheckmark (DS).
Page layout guidelines live in
features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/storybook/STORYBOOK.md.
Checklist: adding a new DS3 component
- Component created under
core/ui/.../ds2/<component>/, packagecom.tangem.core.ui.ds2.<component>. - Named
Tangem<Name>; first optional parameter ismodifier: Modifier = Modifier. - Uses only DS3 tokens:
colors3,typography3,dimens2. No hardcoded values outside previews. - Variants/sizes expressed as an
enuminsideobject Tangem<Name>(not a set of boolean flags). - All public types (enums, statuses, constants) declared inside the
object Tangem<Name>. - Convenient overloads provided (simpler
@Composableoverloads and/orobjectextension presets). - Public sub-components (e.g.
TangemNavigationText) follow the same rules + KDoc as a full component. - States handled: enabled/disabled, press/focus (
interactionSource), loading (if applicable). - Accessibility:
contentDescription,Role,disabled()insemantics. - KDoc per the requirements above (summary + Figma link + behavior notes + every
@param+ a11y). - Two
@Previews (Light/Dark) inTangemThemePreviewRedesign, backgroundcolors3.bg.primary. - Heavy component split into
Tangem<Name>.kt/…Internal.kt/…Ext.kt. - Storybook page added (
add-storybook-componentskill). - Detekt passes:
./gradlew :core:ui:detektMain(plus./gradlew :features:tester:impl:assembleGoogleDebugif you touched the Storybook). - Use in product features only from app version 6.0 onward.