@freightos/freightwind 2.1.1 → 2.1.3-host-isolation.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Freightos
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Freightos
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,28 +1,56 @@
1
- # @freightos/freightwind
2
-
3
- FreightWind Design System — React UI components for Freightos applications.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install @freightos/freightwind @freightos/freightwind/icons
9
- ```
10
-
11
- ## Usage
12
-
13
- ```tsx
14
- import { Button, Alert, Badge } from '@freightos/freightwind';
15
- import '@freightos/freightwind/tokens.css';
16
- ```
17
-
18
- Components require Tailwind CSS v4 with the FDS design tokens loaded via `tokens.css`.
19
-
20
- ## Peer Dependencies
21
-
22
- - `react` >= 18
23
- - `react-dom` >= 18
24
- - `@freightos/freightwind/icons` >= 1.0.0
25
-
26
- ## License
27
-
28
- MIT
1
+ # @freightos/freightwind
2
+
3
+ FreightWind Design System — React UI components for Freightos applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @freightos/freightwind @freightos/freightwind/icons
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```tsx
14
+ import { Button, Alert, Badge } from '@freightos/freightwind';
15
+ import '@freightos/freightwind/tokens.css';
16
+ ```
17
+
18
+ Components require Tailwind CSS v4 with the FDS design tokens loaded via `tokens.css`.
19
+
20
+ ## Host isolation (WebCargo)
21
+
22
+ When mounting FreightWind inside the WebCargo host, also import the WebCargo
23
+ isolation sheet and wrap your App in a `.fw-root` element:
24
+
25
+ ```tsx
26
+ import '@freightos/freightwind/tokens.css';
27
+ import '@freightos/freightwind/host-isolation/webcargo.css';
28
+
29
+ <div className="fw-root">
30
+ <App />
31
+ </div>
32
+ ```
33
+
34
+ The sheet ports Tailwind's standard Preflight scoped to `.fw-root` via
35
+ `:where()` (zero added specificity), plus a focus-bleed cancellation keyed
36
+ on the `.fw-base` per-element marker so it covers FW components rendered
37
+ inside Radix portals (Dialog / Popover / Tooltip / DropdownMenu / Select).
38
+ It exists solely to neutralize WebCargo's Bootstrap-style host CSS that
39
+ targets bare element selectors (`h1-h6 { margin-bottom: .5rem }`,
40
+ `button { border-radius: 0 }`, `button:focus { outline: 5px auto … }`, …) —
41
+ it does NOT impose FW-specific styling, so it never drifts from FW design
42
+ tokens.
43
+
44
+ Skip this file when consuming FreightWind in a clean host (Vite playground,
45
+ greenfield Next.js apps, partner sites without Bootstrap) — there is no host
46
+ CSS to fight there.
47
+
48
+ ## Peer Dependencies
49
+
50
+ - `react` >= 18
51
+ - `react-dom` >= 18
52
+ - `@freightos/freightwind/icons` >= 1.0.0
53
+
54
+ ## License
55
+
56
+ MIT
@@ -80,5 +80,5 @@ function Chip({ variant = 'default', icon, closable, onClose, badge, children, }
80
80
  };
81
81
  const IconComp = icon ? icon_utils_1.iconMap[icon] : null;
82
82
  const iconOnly = !!icon && !children;
83
- return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)(chipVariants({ variant }), iconOnly && 'justify-center', badge !== undefined && (typeof badge === 'string' ? badge.length > 0 : badge > 0) && '!pl-0.5'), children: [badge !== undefined && (typeof badge === 'string' ? badge.length > 0 : badge > 0) && ((0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('mr-1 inline-flex items-center justify-center rounded-full min-w-[16px] h-4 px-1 text-[10px] font-fds-semibold leading-none', badgeColors[variant]), children: typeof badge === 'number' && badge > 99 ? '99+' : badge })), IconComp && (0, jsx_runtime_1.jsx)(IconComp, { size: "xs", className: children ? 'mr-fds-sm' : '' }), children, closable && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: handleClose, "aria-label": "Remove", className: "fw-base ml-fds-sm inline-flex cursor-pointer items-center hover:opacity-70", children: (0, jsx_runtime_1.jsx)(icons_1.IconClear, { size: "xxs" }) }))] }));
83
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)(chipVariants({ variant }), iconOnly && 'justify-center', badge !== undefined && (typeof badge === 'string' ? badge.length > 0 : badge > 0) && '!ps-0.5'), children: [badge !== undefined && (typeof badge === 'string' ? badge.length > 0 : badge > 0) && ((0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('me-1 inline-flex items-center justify-center rounded-full min-w-[16px] h-4 px-1 text-[10px] font-fds-semibold leading-none', badgeColors[variant]), children: typeof badge === 'number' && badge > 99 ? '99+' : badge })), IconComp && (0, jsx_runtime_1.jsx)(IconComp, { size: "xs", className: children ? 'me-fds-sm' : '' }), children, closable && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: handleClose, "aria-label": "Remove", className: "fw-base ms-fds-sm inline-flex cursor-pointer items-center hover:opacity-70", children: (0, jsx_runtime_1.jsx)(icons_1.IconClear, { size: "xxs" }) }))] }));
84
84
  }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderInputIcon = exports.iconMap = exports.useStableId = exports.cn = void 0;
4
+ var utils_1 = require("./utils");
5
+ Object.defineProperty(exports, "cn", { enumerable: true, get: function () { return utils_1.cn; } });
6
+ var use_stable_id_1 = require("./use-stable-id");
7
+ Object.defineProperty(exports, "useStableId", { enumerable: true, get: function () { return use_stable_id_1.useStableId; } });
8
+ var icon_utils_1 = require("./icon-utils");
9
+ Object.defineProperty(exports, "iconMap", { enumerable: true, get: function () { return icon_utils_1.iconMap; } });
10
+ Object.defineProperty(exports, "renderInputIcon", { enumerable: true, get: function () { return icon_utils_1.renderInputIcon; } });
@@ -42,6 +42,6 @@ function Chip({ variant = 'default', icon, closable, onClose, badge, children, }
42
42
  };
43
43
  const IconComp = icon ? iconMap[icon] : null;
44
44
  const iconOnly = !!icon && !children;
45
- return (_jsxs("div", { className: cn(chipVariants({ variant }), iconOnly && 'justify-center', badge !== undefined && (typeof badge === 'string' ? badge.length > 0 : badge > 0) && '!pl-0.5'), children: [badge !== undefined && (typeof badge === 'string' ? badge.length > 0 : badge > 0) && (_jsx("span", { className: cn('mr-1 inline-flex items-center justify-center rounded-full min-w-[16px] h-4 px-1 text-[10px] font-fds-semibold leading-none', badgeColors[variant]), children: typeof badge === 'number' && badge > 99 ? '99+' : badge })), IconComp && _jsx(IconComp, { size: "xs", className: children ? 'mr-fds-sm' : '' }), children, closable && (_jsx("button", { type: "button", onClick: handleClose, "aria-label": "Remove", className: "fw-base ml-fds-sm inline-flex cursor-pointer items-center hover:opacity-70", children: _jsx(IconClear, { size: "xxs" }) }))] }));
45
+ return (_jsxs("div", { className: cn(chipVariants({ variant }), iconOnly && 'justify-center', badge !== undefined && (typeof badge === 'string' ? badge.length > 0 : badge > 0) && '!ps-0.5'), children: [badge !== undefined && (typeof badge === 'string' ? badge.length > 0 : badge > 0) && (_jsx("span", { className: cn('me-1 inline-flex items-center justify-center rounded-full min-w-[16px] h-4 px-1 text-[10px] font-fds-semibold leading-none', badgeColors[variant]), children: typeof badge === 'number' && badge > 99 ? '99+' : badge })), IconComp && _jsx(IconComp, { size: "xs", className: children ? 'me-fds-sm' : '' }), children, closable && (_jsx("button", { type: "button", onClick: handleClose, "aria-label": "Remove", className: "fw-base ms-fds-sm inline-flex cursor-pointer items-center hover:opacity-70", children: _jsx(IconClear, { size: "xxs" }) }))] }));
46
46
  }
47
47
  export { Chip, chipVariants };
@@ -0,0 +1,3 @@
1
+ export { cn } from './utils';
2
+ export { useStableId } from './use-stable-id';
3
+ export { iconMap, renderInputIcon } from './icon-utils';
@@ -0,0 +1,4 @@
1
+ export { cn } from './utils';
2
+ export { useStableId } from './use-stable-id';
3
+ export { iconMap, renderInputIcon } from './icon-utils';
4
+ export type { IconName, InputShellSize } from './icon-utils';
@@ -1,233 +1,233 @@
1
- # FreightWind Design System
2
-
3
- FreightWind is the Freightos Design System — a React component library styled with Tailwind CSS v4 and FDS (Freightos Design System) tokens.
4
-
5
- ## Complete Setup
6
-
7
- Follow ALL steps below to properly set up FreightWind in a React project.
8
-
9
- ### Step 1 — Install dependencies
10
-
11
- ```bash
12
- npm install @freightos/freightwind @freightos/freightwind/icons tailwindcss @tailwindcss/vite
13
- ```
14
-
15
- `@freightos/freightwind/icons` is a required peer dependency that provides all iconography. Tailwind CSS v4 is required for component styling.
16
-
17
- ### Step 2 — Configure Tailwind CSS v4
18
-
19
- FreightWind requires Tailwind CSS v4. Set it up with your bundler:
20
-
21
- **Vite** — add the Tailwind plugin to `vite.config.ts`:
22
-
23
- ```ts
24
- import tailwindcss from '@tailwindcss/vite';
25
- import { defineConfig } from 'vite';
26
- import react from '@vitejs/plugin-react';
27
-
28
- export default defineConfig({
29
- plugins: [react(), tailwindcss()],
30
- });
31
- ```
32
-
33
- ### Step 3 — Set up your global CSS file
34
-
35
- **CRITICAL**: Your main CSS file must import Tailwind AND FreightWind tokens in the correct order. The tokens.css file uses Tailwind v4's `@theme inline` directive to register color utilities (like `bg-fds-blue-30`, `text-fds-gray-80`, etc.) — this ONLY works when imported inside a CSS file that Tailwind processes.
36
-
37
- Create or update your main CSS file (e.g. `src/index.css` or `src/styles/globals.css`):
38
-
39
- ```css
40
- /* Step A: Import Tailwind CSS — this MUST come first */
41
- @import "tailwindcss";
42
-
43
- /* Step B: Import FreightWind tokens — MUST be in this same CSS file, AFTER tailwindcss.
44
- This registers all FDS color utilities (bg-fds-blue-30, text-fds-gray-80, etc.),
45
- spacing tokens, typography tokens, and custom utilities used by components.
46
-
47
- DO NOT import this as a <link> tag in HTML — it must be processed by Tailwind's
48
- CSS engine for @theme inline to work. */
49
- @import "@freightos/freightwind/tokens.css";
50
-
51
- /* Step C: Global base styles — REQUIRED for components to render correctly */
52
- * {
53
- -webkit-font-smoothing: antialiased;
54
- -moz-osx-font-smoothing: grayscale;
55
- }
56
-
57
- body {
58
- background-color: var(--ground);
59
- color: var(--foreground);
60
- font-family: 'Open Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
61
- font-size: 0.875rem; /* 14px — FDS base font size */
62
- line-height: 1.5;
63
- }
64
- ```
65
-
66
- **IMPORTANT NOTES:**
67
- - `@import "@freightos/freightwind/tokens.css"` MUST be inside the same CSS file as `@import "tailwindcss"` — never in a separate file or `<link>` tag
68
- - The import order matters: `tailwindcss` first, then `tokens.css`
69
- - If tokens are imported separately or in the wrong order, Tailwind utility classes like `bg-fds-purple-2`, `bg-fds-gray-20`, `text-fds-blue-30`, etc. will NOT work and components will have missing styles
70
-
71
- ### Step 4 — Load the Open Sans font
72
-
73
- FreightWind uses **Open Sans** as its font family. Load weights 400, 600, and 700 from Google Fonts.
74
-
75
- **Option A — In your HTML `<head>` (simplest):**
76
-
77
- ```html
78
- <link rel="preconnect" href="https://fonts.googleapis.com" />
79
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
80
- <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap" rel="stylesheet" />
81
- ```
82
-
83
- **Option B — In Next.js with `next/font`:**
84
-
85
- ```tsx
86
- import { Open_Sans } from 'next/font/google';
87
-
88
- const openSans = Open_Sans({
89
- subsets: ['latin'],
90
- weight: ['400', '600', '700'],
91
- variable: '--font-open-sans',
92
- });
93
-
94
- // Apply to <html> or <body>:
95
- <html className={openSans.variable}>
96
- ```
97
-
98
- Then in your CSS, override the font-sans variable:
99
-
100
- ```css
101
- @theme inline {
102
- --font-sans: var(--font-open-sans), 'Open Sans', ui-sans-serif, system-ui, sans-serif;
103
- }
104
- ```
105
-
106
- ### Step 5 — Import and use components
107
-
108
- ```tsx
109
- import { Button, Alert, Checkbox } from '@freightos/freightwind';
110
- import { IconSearch } from '@freightos/freightwind/icons';
111
-
112
- <Button variant="default" size="md">Submit</Button>
113
- <Alert variant="info" message="Shipment updated." />
114
- <Checkbox>Accept terms</Checkbox>
115
- ```
116
-
117
- ### Step 6 — Toast notifications (optional)
118
-
119
- If using the `message` toast API, wrap your app with `MessageProvider`:
120
-
121
- ```tsx
122
- import { MessageProvider, message } from '@freightos/freightwind';
123
-
124
- // In your root layout:
125
- <MessageProvider />
126
-
127
- // Anywhere in your app:
128
- message.success('Saved successfully');
129
- ```
130
-
131
- ## Complete minimal example
132
-
133
- Here is a full working `src/index.css`:
134
-
135
- ```css
136
- @import "tailwindcss";
137
- @import "@freightos/freightwind/tokens.css";
138
-
139
- * {
140
- -webkit-font-smoothing: antialiased;
141
- -moz-osx-font-smoothing: grayscale;
142
- }
143
-
144
- body {
145
- background-color: var(--ground);
146
- color: var(--foreground);
147
- font-family: 'Open Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
148
- font-size: 0.875rem;
149
- line-height: 1.5;
150
- }
151
- ```
152
-
153
- And a full working `src/App.tsx`:
154
-
155
- ```tsx
156
- import { Button, Alert, Chip, Switch, Checkbox } from '@freightos/freightwind';
157
- import { IconSearch } from '@freightos/freightwind/icons';
158
-
159
- function App() {
160
- return (
161
- <div className="p-fds-xl">
162
- <h1 className="text-fds-h3 font-fds-bold leading-fds-title mb-fds-lg">My App</h1>
163
- <Alert variant="info" message="Welcome to the app!" />
164
- <div className="mt-fds-lg flex gap-fds-sm">
165
- <Button variant="default">Primary</Button>
166
- <Button variant="secondary">Secondary</Button>
167
- <Button icon="search" tooltip="Search" />
168
- </div>
169
- <div className="mt-fds-lg flex gap-fds-md items-center">
170
- <Chip variant="success">Active</Chip>
171
- <Switch>Enable notifications</Switch>
172
- <Checkbox>Accept terms</Checkbox>
173
- </div>
174
- </div>
175
- );
176
- }
177
- ```
178
-
179
- ## Troubleshooting
180
-
181
- ### Tailwind utility classes not working (e.g. `bg-fds-purple-2` has no effect)
182
-
183
- This means `tokens.css` is not being processed by Tailwind. Make sure:
184
- 1. `@import "@freightos/freightwind/tokens.css"` is in the SAME CSS file as `@import "tailwindcss"`
185
- 2. It comes AFTER the tailwindcss import
186
- 3. It is NOT loaded via a `<link>` tag — it must be in CSS `@import` so Tailwind processes the `@theme inline` block
187
-
188
- ### Colors like `--ground`, `--foreground`, `--card` are undefined
189
-
190
- These CSS variables are defined in the `:root` block inside `tokens.css`. Make sure `tokens.css` is imported.
191
-
192
- ### Font looks wrong
193
-
194
- Make sure Open Sans is loaded (Step 4) and the body `font-family` is set (Step 3C).
195
-
196
- ### Text rendering looks rough or inconsistent
197
-
198
- Add global font smoothing (Step 3C):
199
- ```css
200
- * {
201
- -webkit-font-smoothing: antialiased;
202
- -moz-osx-font-smoothing: grayscale;
203
- }
204
- ```
205
-
206
- ## Dark mode
207
-
208
- FreightWind supports dark mode via a `.dark` class on a parent element (typically `<html>`). The tokens.css includes dark mode overrides for all semantic colors. To enable dark mode, add `class="dark"` to the `<html>` element.
209
-
210
- ## Available components
211
-
212
- See `overview-components.md` for a full list of components with their props and usage.
213
-
214
- ## Available icons
215
-
216
- See `overview-icons.md` for details on the icon system.
217
-
218
- ## Design tokens
219
-
220
- FreightWind uses a custom token system instead of Tailwind defaults:
221
-
222
- - **Colors**: `design-tokens/colors.md` — semantic color palette (blue, red, green, yellow, gray, purple)
223
- - **Typography**: `design-tokens/typography.md` — font family, sizes, weights, and line heights
224
- - **Spacing**: `design-tokens/spacing.md` — consistent spacing scale
225
-
226
- ## Key conventions
227
-
228
- - Always use FDS tokens (`text-fds-*`, `p-fds-*`, `rounded-fds-*`, `bg-fds-*`) instead of Tailwind defaults
229
- - All components support both controlled and uncontrolled usage patterns
230
- - Components with `icon` props accept kebab-case icon names: `"search"`, `"close"`, `"user"`, `"risk"`, etc.
231
- - Use `cn()` utility (exported from the package) for className merging
232
- - The page canvas background should be `bg-ground` (#f6f6f6), not white
233
- - Cards and content areas use `bg-card` (#ffffff) against the ground
1
+ # FreightWind Design System
2
+
3
+ FreightWind is the Freightos Design System — a React component library styled with Tailwind CSS v4 and FDS (Freightos Design System) tokens.
4
+
5
+ ## Complete Setup
6
+
7
+ Follow ALL steps below to properly set up FreightWind in a React project.
8
+
9
+ ### Step 1 — Install dependencies
10
+
11
+ ```bash
12
+ npm install @freightos/freightwind @freightos/freightwind/icons tailwindcss @tailwindcss/vite
13
+ ```
14
+
15
+ `@freightos/freightwind/icons` is a required peer dependency that provides all iconography. Tailwind CSS v4 is required for component styling.
16
+
17
+ ### Step 2 — Configure Tailwind CSS v4
18
+
19
+ FreightWind requires Tailwind CSS v4. Set it up with your bundler:
20
+
21
+ **Vite** — add the Tailwind plugin to `vite.config.ts`:
22
+
23
+ ```ts
24
+ import tailwindcss from '@tailwindcss/vite';
25
+ import { defineConfig } from 'vite';
26
+ import react from '@vitejs/plugin-react';
27
+
28
+ export default defineConfig({
29
+ plugins: [react(), tailwindcss()],
30
+ });
31
+ ```
32
+
33
+ ### Step 3 — Set up your global CSS file
34
+
35
+ **CRITICAL**: Your main CSS file must import Tailwind AND FreightWind tokens in the correct order. The tokens.css file uses Tailwind v4's `@theme inline` directive to register color utilities (like `bg-fds-blue-30`, `text-fds-gray-80`, etc.) — this ONLY works when imported inside a CSS file that Tailwind processes.
36
+
37
+ Create or update your main CSS file (e.g. `src/index.css` or `src/styles/globals.css`):
38
+
39
+ ```css
40
+ /* Step A: Import Tailwind CSS — this MUST come first */
41
+ @import "tailwindcss";
42
+
43
+ /* Step B: Import FreightWind tokens — MUST be in this same CSS file, AFTER tailwindcss.
44
+ This registers all FDS color utilities (bg-fds-blue-30, text-fds-gray-80, etc.),
45
+ spacing tokens, typography tokens, and custom utilities used by components.
46
+
47
+ DO NOT import this as a <link> tag in HTML — it must be processed by Tailwind's
48
+ CSS engine for @theme inline to work. */
49
+ @import "@freightos/freightwind/tokens.css";
50
+
51
+ /* Step C: Global base styles — REQUIRED for components to render correctly */
52
+ * {
53
+ -webkit-font-smoothing: antialiased;
54
+ -moz-osx-font-smoothing: grayscale;
55
+ }
56
+
57
+ body {
58
+ background-color: var(--ground);
59
+ color: var(--foreground);
60
+ font-family: 'Open Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
61
+ font-size: 0.875rem; /* 14px — FDS base font size */
62
+ line-height: 1.5;
63
+ }
64
+ ```
65
+
66
+ **IMPORTANT NOTES:**
67
+ - `@import "@freightos/freightwind/tokens.css"` MUST be inside the same CSS file as `@import "tailwindcss"` — never in a separate file or `<link>` tag
68
+ - The import order matters: `tailwindcss` first, then `tokens.css`
69
+ - If tokens are imported separately or in the wrong order, Tailwind utility classes like `bg-fds-purple-2`, `bg-fds-gray-20`, `text-fds-blue-30`, etc. will NOT work and components will have missing styles
70
+
71
+ ### Step 4 — Load the Open Sans font
72
+
73
+ FreightWind uses **Open Sans** as its font family. Load weights 400, 600, and 700 from Google Fonts.
74
+
75
+ **Option A — In your HTML `<head>` (simplest):**
76
+
77
+ ```html
78
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
79
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
80
+ <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap" rel="stylesheet" />
81
+ ```
82
+
83
+ **Option B — In Next.js with `next/font`:**
84
+
85
+ ```tsx
86
+ import { Open_Sans } from 'next/font/google';
87
+
88
+ const openSans = Open_Sans({
89
+ subsets: ['latin'],
90
+ weight: ['400', '600', '700'],
91
+ variable: '--font-open-sans',
92
+ });
93
+
94
+ // Apply to <html> or <body>:
95
+ <html className={openSans.variable}>
96
+ ```
97
+
98
+ Then in your CSS, override the font-sans variable:
99
+
100
+ ```css
101
+ @theme inline {
102
+ --font-sans: var(--font-open-sans), 'Open Sans', ui-sans-serif, system-ui, sans-serif;
103
+ }
104
+ ```
105
+
106
+ ### Step 5 — Import and use components
107
+
108
+ ```tsx
109
+ import { Button, Alert, Checkbox } from '@freightos/freightwind';
110
+ import { IconSearch } from '@freightos/freightwind/icons';
111
+
112
+ <Button variant="default" size="md">Submit</Button>
113
+ <Alert variant="info" message="Shipment updated." />
114
+ <Checkbox>Accept terms</Checkbox>
115
+ ```
116
+
117
+ ### Step 6 — Toast notifications (optional)
118
+
119
+ If using the `message` toast API, wrap your app with `MessageProvider`:
120
+
121
+ ```tsx
122
+ import { MessageProvider, message } from '@freightos/freightwind';
123
+
124
+ // In your root layout:
125
+ <MessageProvider />
126
+
127
+ // Anywhere in your app:
128
+ message.success('Saved successfully');
129
+ ```
130
+
131
+ ## Complete minimal example
132
+
133
+ Here is a full working `src/index.css`:
134
+
135
+ ```css
136
+ @import "tailwindcss";
137
+ @import "@freightos/freightwind/tokens.css";
138
+
139
+ * {
140
+ -webkit-font-smoothing: antialiased;
141
+ -moz-osx-font-smoothing: grayscale;
142
+ }
143
+
144
+ body {
145
+ background-color: var(--ground);
146
+ color: var(--foreground);
147
+ font-family: 'Open Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
148
+ font-size: 0.875rem;
149
+ line-height: 1.5;
150
+ }
151
+ ```
152
+
153
+ And a full working `src/App.tsx`:
154
+
155
+ ```tsx
156
+ import { Button, Alert, Chip, Switch, Checkbox } from '@freightos/freightwind';
157
+ import { IconSearch } from '@freightos/freightwind/icons';
158
+
159
+ function App() {
160
+ return (
161
+ <div className="p-fds-xl">
162
+ <h1 className="text-fds-h3 font-fds-bold leading-fds-title mb-fds-lg">My App</h1>
163
+ <Alert variant="info" message="Welcome to the app!" />
164
+ <div className="mt-fds-lg flex gap-fds-sm">
165
+ <Button variant="default">Primary</Button>
166
+ <Button variant="secondary">Secondary</Button>
167
+ <Button icon="search" tooltip="Search" />
168
+ </div>
169
+ <div className="mt-fds-lg flex gap-fds-md items-center">
170
+ <Chip variant="success">Active</Chip>
171
+ <Switch>Enable notifications</Switch>
172
+ <Checkbox>Accept terms</Checkbox>
173
+ </div>
174
+ </div>
175
+ );
176
+ }
177
+ ```
178
+
179
+ ## Troubleshooting
180
+
181
+ ### Tailwind utility classes not working (e.g. `bg-fds-purple-2` has no effect)
182
+
183
+ This means `tokens.css` is not being processed by Tailwind. Make sure:
184
+ 1. `@import "@freightos/freightwind/tokens.css"` is in the SAME CSS file as `@import "tailwindcss"`
185
+ 2. It comes AFTER the tailwindcss import
186
+ 3. It is NOT loaded via a `<link>` tag — it must be in CSS `@import` so Tailwind processes the `@theme inline` block
187
+
188
+ ### Colors like `--ground`, `--foreground`, `--card` are undefined
189
+
190
+ These CSS variables are defined in the `:root` block inside `tokens.css`. Make sure `tokens.css` is imported.
191
+
192
+ ### Font looks wrong
193
+
194
+ Make sure Open Sans is loaded (Step 4) and the body `font-family` is set (Step 3C).
195
+
196
+ ### Text rendering looks rough or inconsistent
197
+
198
+ Add global font smoothing (Step 3C):
199
+ ```css
200
+ * {
201
+ -webkit-font-smoothing: antialiased;
202
+ -moz-osx-font-smoothing: grayscale;
203
+ }
204
+ ```
205
+
206
+ ## Dark mode
207
+
208
+ FreightWind supports dark mode via a `.dark` class on a parent element (typically `<html>`). The tokens.css includes dark mode overrides for all semantic colors. To enable dark mode, add `class="dark"` to the `<html>` element.
209
+
210
+ ## Available components
211
+
212
+ See `overview-components.md` for a full list of components with their props and usage.
213
+
214
+ ## Available icons
215
+
216
+ See `overview-icons.md` for details on the icon system.
217
+
218
+ ## Design tokens
219
+
220
+ FreightWind uses a custom token system instead of Tailwind defaults:
221
+
222
+ - **Colors**: `design-tokens/colors.md` — semantic color palette (blue, red, green, yellow, gray, purple)
223
+ - **Typography**: `design-tokens/typography.md` — font family, sizes, weights, and line heights
224
+ - **Spacing**: `design-tokens/spacing.md` — consistent spacing scale
225
+
226
+ ## Key conventions
227
+
228
+ - Always use FDS tokens (`text-fds-*`, `p-fds-*`, `rounded-fds-*`, `bg-fds-*`) instead of Tailwind defaults
229
+ - All components support both controlled and uncontrolled usage patterns
230
+ - Components with `icon` props accept kebab-case icon names: `"search"`, `"close"`, `"user"`, `"risk"`, etc.
231
+ - Use `cn()` utility (exported from the package) for className merging
232
+ - The page canvas background should be `bg-ground` (#f6f6f6), not white
233
+ - Cards and content areas use `bg-card` (#ffffff) against the ground