Getting Started
Install the private workspace package, load its real stylesheets and verify a usable React interface.
Supported delivery model
@mobtranslate/ui is a private source package in packages/ui. It is not a published npm installation contract. Its main and types entries point to src/index.ts, so the consuming bundler must compile TypeScript and React JSX. This styleguide uses Next.js 16, React 19 and Tailwind CSS 4; that is the currently verified web setup.
The package and its two consumers, styleguide and web, require React and React DOM ^19.2.7. Use the lockfile’s matching runtime and React 19 types. React 18 is outside this release contract; a wider peer range would need its own compatibility evidence.
| Requirement | Actual workspace contract |
|---|---|
| Package dependency | "@mobtranslate/ui": "workspace:*" |
| Component entry | import { Button, Input } from "@mobtranslate/ui" |
| Source compilation | Next transpilePackages: ["@mobtranslate/ui"] |
| Token stylesheet | @mobtranslate/ui/src/tokens/tokens.css |
| Component stylesheet | @mobtranslate/ui/src/components/components.css |
| Styling pipeline | Tailwind 4 through @tailwindcss/postcss |
| Native platforms | DOM/CSS components; not React Native or native Android/iOS widgets |
Run this styleguide
Run these commands from the repository root. Use the repository’s declared pnpm 9.15.0 package manager and the lockfile; a different manager/version is a separate compatibility check. The filtered installation includes the UI dependency without launching unrelated apps. Install first, then generate/check assets and start one server on the chosen port.
pnpm --filter styleguide... install --frozen-lockfile
pnpm --filter styleguide dev --hostname 127.0.0.1
# Local preview: http://127.0.0.1:3003Add another workspace consumer
Replace my-app with an existing package name from apps/. Add the workspace dependency to that app; a registry-only install outside this repository cannot satisfy workspace:*. Match the app’s React and React DOM versions. Keep server-only credentials outside client component code.
pnpm --filter my-app add "@mobtranslate/ui@workspace:*"
pnpm --filter my-app add -D tailwindcss@4.3.1 @tailwindcss/postcss@4.3.1 postcss@8.5.15Configure compilation and styles
In next.config.js, enable transpilePackages for the source package. In postcss.config.mjs, register @tailwindcss/postcss. The following global CSS paths resolve against the actual installed workspace package. The @source path assumes globals.css is in apps/my-app/app/; adjust the relative source path if the file moves. Import the global stylesheet once from the app root layout.
- Next config: module.exports = { transpilePackages: ["@mobtranslate/ui"] };
- PostCSS config: export default { plugins: { "@tailwindcss/postcss": {} } };
- Root layout: import "./globals.css". Use a real html lang value and a meaningful main landmark.
- Do not rely on a TypeScript path alias to prove package resolution. This styleguide now resolves the actual workspace dependency.
@import "tailwindcss";
@import "@mobtranslate/ui/src/tokens/tokens.css";
@import "@mobtranslate/ui/src/components/components.css";
@source "../../../packages/ui/src";First checked interactive example
This example is compiled from the same source displayed below. It has a persistent label, connected help/error text, explicit submission, retained input and an honest local result. It does not invent language content or pretend a request was published.
'use client';
import { useId, useState } from 'react';
import { Button, Input } from '@mobtranslate/ui';
export function EntryFormExample() {
const id = useId();
const [text, setText] = useState('');
const [error, setError] = useState('');
const [status, setStatus] = useState('');
return <form noValidate className="space-y-3" onSubmit={event => {
event.preventDefault();
if (!text.trim()) {
setError('Enter search text before trying this example.');
setStatus('');
event.currentTarget.querySelector<HTMLInputElement>('input')?.focus();
return;
}
setError('');
setStatus(`Local example received “${text}”. No search or publication was sent.`);
}}>
<label htmlFor={id} className="block font-medium">Search text</label>
<Input id={id} value={text} required state={error ? 'error' : 'default'}
aria-describedby={`${id}-help${error ? ` ${id}-error` : ''}`}
onChange={event => { setText(event.target.value); setError(''); setStatus(''); }} />
<p id={`${id}-help`} className="text-sm">Use your own text. This local demo does not return language content.</p>
{error && <p id={`${id}-error`} role="alert" className="text-sm">{error}</p>}
<Button type="submit">Try local form</Button>
<p role="status" className="text-sm">{status}</p>
</form>;
}
Server and client boundaries
- Keep useState, event handlers, browser storage and DOM access in client components. Put "use client" before imports in the file that defines the interactive boundary.
- Server-render the document structure and source-backed content where practical. Pass serializable values across the boundary; do not expose secrets in props.
- Choose controlled state when the app needs to validate or persist it. Use defaultValue/defaultOpen for an uncontrolled initial value, not as a substitute for later updates.
- A disabled submit button is not a request handler. Implement pending, cancellation, recovery and the actual persistence outcome in the consuming app.
Verify the setup
Stop the development server before starting production on the same port. The build checks TypeScript; it does not replace browser operation, accessibility review or verification of real data writes.
pnpm --filter styleguide lint
pnpm --filter styleguide typecheck
pnpm --filter styleguide tokens:check
pnpm --filter styleguide examples:check
pnpm --filter styleguide build
pnpm --filter styleguide start --hostname 127.0.0.1
# In another terminal, with agent-browser installed:
pnpm --filter styleguide test:browserTroubleshooting
| Symptom | Check | Recovery |
|---|---|---|
| Cannot resolve @mobtranslate/ui | Workspace dependency and filtered install | Install from the repository root; inspect the package link. |
| Unstyled controls | Both package /src CSS imports and PostCSS setup | Load global CSS once; inspect a real computed token value. |
| Missing utility styles | Tailwind source scanning and app-relative @source | Include the package source; use literal class names for generated variants. |
| Invalid hook or duplicate React | React/React DOM versions and dependency graph | Align the consumer’s versions and investigate duplicate runtime copies. |
| Browser navigation timeout during startup | Cold compilation, memory and disk contention | Inspect the same process/port and wait for an actual successful route response. An observation timeout alone does not justify restarting it; test the built production server. |
| Light choice changes with system theme | Explicit .light and .dark plus mt-theme key | Use the verified theme controller and system/storage listeners. |