fansunited-sports-ui 0.0.1

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 ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Fans United
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.
22
+
package/README.md ADDED
@@ -0,0 +1,269 @@
1
+ # fansunited-sports-ui
2
+
3
+ A comprehensive React component library for building sports websites and applications. Built with **Tailwind CSS v4** for seamless theming integration.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/fansunited-sports-ui)](https://www.npmjs.com/package/fansunited-sports-ui)
6
+ [![license](https://img.shields.io/npm/l/fansunited-sports-ui)](https://github.com/nicklatkovich/fansunited-sports-ui/blob/main/LICENSE)
7
+
8
+ ## Features
9
+
10
+ - 🏟️ **Sports-focused** — Purpose-built for media sites, football clubs, federations, and betting affiliates
11
+ - 🎨 **Tailwind CSS v4** — Uses native Tailwind classes to automatically match your design system
12
+ - 📦 **Three-layer architecture** — Primitives, Components, and Blocks for flexible composition
13
+ - 🎯 **Type-Safe** — Full TypeScript support with comprehensive type definitions
14
+ - 🔧 **Highly Customizable** — Flexible styling system with standardized customization options
15
+ - 📱 **Responsive** — Mobile-first design that works on all screen sizes
16
+ - 🎭 **Theme Support** — Works with Tailwind's theme system and custom color palettes
17
+
18
+ ---
19
+
20
+ ## Installation
21
+
22
+ Install the package via npm:
23
+
24
+ ```bash
25
+ npm install fansunited-sports-ui
26
+ ```
27
+
28
+ ### Peer Dependencies
29
+
30
+ This library requires the following peer dependencies:
31
+
32
+ ```json
33
+ {
34
+ "react": "^18.0.0 || ^19.0.0",
35
+ "react-dom": "^18.0.0 || ^19.0.0",
36
+ "tailwindcss": "^4.0.0",
37
+ "@tailwindcss/postcss": "^4.0.0"
38
+ }
39
+ ```
40
+
41
+ Install them if you haven't already:
42
+
43
+ ```bash
44
+ npm install react react-dom tailwindcss @tailwindcss/postcss
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Setup
50
+
51
+ ### 1. Configure Tailwind CSS
52
+
53
+ Update your Tailwind CSS configuration to scan the component library files. This ensures that all Tailwind classes used by the components are included in your build.
54
+
55
+ **For Tailwind CSS v4 with `@import` in CSS:**
56
+
57
+ In your main CSS file (e.g., `src/index.css` or `app/globals.css`):
58
+
59
+ ```css
60
+ @import "tailwindcss";
61
+
62
+ /* Your custom theme and styles */
63
+ ```
64
+
65
+ **Configure content paths in `tailwind.config.js` (or `tailwind.config.ts`):**
66
+
67
+ ```js
68
+ /** @type {import('tailwindcss').Config} */
69
+ export default {
70
+ content: [
71
+ "./index.html",
72
+ "./src/**/*.{js,ts,jsx,tsx}",
73
+ // Add this line to scan the component library
74
+ "./node_modules/fansunited-sports-ui/dist/**/*.{js,mjs,cjs}",
75
+ ],
76
+ theme: {
77
+ extend: {},
78
+ },
79
+ plugins: [],
80
+ };
81
+ ```
82
+
83
+ **Important:** The component library uses Tailwind's native color classes (e.g., `bg-primary-600`, `from-primary-600`) instead of hardcoded colors. This means the components will automatically match your application's design system and theme.
84
+
85
+ ### 2. Configure PostCSS
86
+
87
+ Ensure your `postcss.config.js` includes the Tailwind CSS PostCSS plugin:
88
+
89
+ ```js
90
+ export default {
91
+ plugins: {
92
+ "@tailwindcss/postcss": {},
93
+ autoprefixer: {},
94
+ },
95
+ };
96
+ ```
97
+
98
+ ### 3. Define Your Theme (Optional)
99
+
100
+ The components use Tailwind's color system. You can customize the primary and secondary colors in your CSS using the `@theme` directive:
101
+
102
+ ```css
103
+ @import "tailwindcss";
104
+
105
+ @theme {
106
+ /* Primary color palette */
107
+ --color-primary-50: oklch(0.97 0.01 250);
108
+ --color-primary-100: oklch(0.93 0.03 250);
109
+ --color-primary-200: oklch(0.85 0.06 250);
110
+ --color-primary-300: oklch(0.75 0.1 250);
111
+ --color-primary-400: oklch(0.65 0.14 250);
112
+ --color-primary-500: oklch(0.57 0.17 250);
113
+ --color-primary-600: oklch(0.5 0.17 250);
114
+ --color-primary-700: oklch(0.43 0.15 250);
115
+ --color-primary-800: oklch(0.35 0.12 250);
116
+ --color-primary-900: oklch(0.27 0.09 250);
117
+ --color-primary-950: oklch(0.18 0.06 250);
118
+
119
+ /* Secondary color palette */
120
+ --color-secondary-50: oklch(0.97 0.02 50);
121
+ --color-secondary-100: oklch(0.94 0.04 50);
122
+ --color-secondary-200: oklch(0.88 0.08 50);
123
+ --color-secondary-300: oklch(0.8 0.12 50);
124
+ --color-secondary-400: oklch(0.72 0.15 50);
125
+ --color-secondary-500: oklch(0.68 0.18 50);
126
+ --color-secondary-600: oklch(0.62 0.18 50);
127
+ --color-secondary-700: oklch(0.54 0.16 50);
128
+ --color-secondary-800: oklch(0.45 0.13 50);
129
+ --color-secondary-900: oklch(0.36 0.1 50);
130
+ --color-secondary-950: oklch(0.25 0.07 50);
131
+ }
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Quick Start
137
+
138
+ ### Basic Usage
139
+
140
+ Import and use the components in your React application:
141
+
142
+ ```tsx
143
+ import { MatchScore, ContentCard } from "fansunited-sports-ui";
144
+
145
+ function App() {
146
+ return (
147
+ <MatchScore
148
+ match={{
149
+ id: "1",
150
+ competitorOne: { id: "1", name: "Arsenal", score: { main: 2 } },
151
+ competitorTwo: { id: "2", name: "Chelsea", score: { main: 1 } },
152
+ status: "final",
153
+ }}
154
+ variant="scoreCard"
155
+ />
156
+ );
157
+ }
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Architecture
163
+
164
+ The library is organized into three layers:
165
+
166
+ ### Layer 1: Primitives
167
+
168
+ Pure UI building blocks with no domain knowledge:
169
+
170
+ | Component | Description |
171
+ | ------------------------ | ---------------------------------- |
172
+ | `Badge` / `BadgeGroup` | Status labels and tags |
173
+ | `CtaButton` / `CtaGroup` | Call-to-action buttons |
174
+ | `EntityDisplay` | Generic entity with image and name |
175
+ | `Countdown` | Timer display |
176
+ | `Pagination` | Page navigation |
177
+ | `Tooltip` | Hover information |
178
+
179
+ ### Layer 2: Components
180
+
181
+ Domain-aware components with single responsibility:
182
+
183
+ | Component | Description |
184
+ | ----------------- | ------------------------------------------------------------------------------------------ |
185
+ | `MatchScore` | Match display with variants: `inline`, `scoreCard`, `scoreLine`, `embedded` |
186
+ | `ContentCard` | Flexible cards with variants: `hero`, `standard`, `standardHorizontal`, `promo`, `minimal` |
187
+ | `BettingOdds` | Odds display with operator branding |
188
+ | `StatsTable` | Tabular statistics (standings, leaderboards) |
189
+ | `StatsGrid` | Grid of stat items |
190
+ | `StatsHeadToHead` | Comparison bars |
191
+ | `FormIndicator` | Win/draw/loss form display |
192
+ | `ProfileHeader` | Entity profile headers |
193
+ | `MatchupHeader` | Two-entity matchup display |
194
+ | `SectionHeader` | Section titles with optional actions |
195
+
196
+ ### Layer 3: Blocks
197
+
198
+ Pre-assembled composites ready for use:
199
+
200
+ | Block | Description |
201
+ | ------------------------ | --------------------------------- |
202
+ | `MatchListBlock` | List of matches with grouping |
203
+ | `ContentListBlock` | Grid/list of content cards |
204
+ | `FeaturedContentBlock` | Hero + supporting content layouts |
205
+ | `HeadToHeadBlock` | Complete H2H comparison |
206
+ | `CompetitorProfileBlock` | Full competitor profile |
207
+ | `SquadBlock` | Team squad display |
208
+
209
+ ---
210
+
211
+ ## Styling
212
+
213
+ Every component accepts a `styles` prop for customization:
214
+
215
+ ```tsx
216
+ <MatchScore
217
+ match={match}
218
+ styles={{
219
+ borderRadius: "lg",
220
+ shadow: "md",
221
+ padding: "lg",
222
+ typography: {
223
+ teamName: "text-lg font-bold",
224
+ score: "text-3xl font-black",
225
+ },
226
+ }}
227
+ />
228
+ ```
229
+
230
+ ### Common Style Options
231
+
232
+ | Option | Values |
233
+ | ------------------------ | ------------------------------------------------------------------ |
234
+ | `borderRadius` | `none` \| `sm` \| `md` \| `lg` \| `xl` \| `2xl` \| `3xl` \| `full` |
235
+ | `shadow` / `hoverShadow` | `none` \| `sm` \| `md` \| `lg` \| `xl` \| `2xl` |
236
+ | `padding` | `none` \| `sm` \| `md` \| `lg` \| `xl` |
237
+ | `typography` | Tailwind classes for text elements |
238
+ | `background` | Custom background classes |
239
+ | `container` | Additional container classes |
240
+
241
+ ---
242
+
243
+ ## TypeScript Support
244
+
245
+ All components are fully typed. Import types as needed:
246
+
247
+ ```tsx
248
+ import type {
249
+ MatchScoreContent,
250
+ MatchScoreProps,
251
+ CardContent,
252
+ CardStyles,
253
+ Competitor,
254
+ MatchSimple,
255
+ } from "fansunited-sports-ui";
256
+ ```
257
+
258
+ ---
259
+
260
+ ## Browser Support
261
+
262
+ - Chrome, Firefox, Safari, Edge (latest 2 versions)
263
+ - React 18.x or 19.x
264
+
265
+ ---
266
+
267
+ ## License
268
+
269
+ MIT © [Fans United](https://fansunited.com)
package/dist/BADGE.md ADDED
@@ -0,0 +1,50 @@
1
+ # Badge
2
+
3
+ A visual badge component for displaying labels, tags, or status indicators.
4
+
5
+ ## Usage
6
+
7
+ ```tsx
8
+ import { Badge } from "@fansunited/tailwind-ui-components";
9
+
10
+ // Primary badge
11
+ <Badge badge={{ text: "NEW", variant: "primary", position: "top-right" }} />
12
+
13
+ // Success badge
14
+ <Badge badge={{ text: "Live", variant: "success", position: "top-left" }} />
15
+
16
+ // Custom styled badge
17
+ <Badge badge={{ text: "VIP", variant: "custom", position: "top-right", styles: { container: "bg-gold text-black" } }} />
18
+ ```
19
+
20
+ ## Props
21
+
22
+ | Prop | Type | Description |
23
+ | ------- | ------------- | -------------------------- |
24
+ | `badge` | `BadgeConfig` | Badge configuration object |
25
+
26
+ ### BadgeConfig
27
+
28
+ | Property | Type | Default | Description |
29
+ | ---------- | --------------------------------------------------------------------------------------------------- | ----------- | ---------------------------------- |
30
+ | `text` | `string` | - | Badge text content |
31
+ | `variant` | `"default" \| "primary" \| "secondary" \| "success" \| "warning" \| "danger" \| "info" \| "custom"` | `"default"` | Visual variant |
32
+ | `position` | `"top-left" \| "top-right" \| "bottom-left" \| "bottom-right"` | - | Position when used in card context |
33
+ | `styles` | `BadgeStyles` | - | Style customization options |
34
+
35
+ ### BadgeStyles
36
+
37
+ | Property | Type | Description |
38
+ | ----------- | -------- | ----------------------------------------------------------- |
39
+ | `container` | `string` | Tailwind classes for the badge (used with "custom" variant) |
40
+
41
+ ## Variants
42
+
43
+ - **default**: Neutral gray background
44
+ - **primary**: Primary color background
45
+ - **secondary**: Secondary color background
46
+ - **success**: Green background
47
+ - **warning**: Yellow background
48
+ - **danger**: Red background
49
+ - **info**: Cyan background
50
+ - **custom**: No default styles - use `styles.container` for full customization
@@ -0,0 +1,43 @@
1
+ # BadgeGroup
2
+
3
+ A component for rendering multiple badges at specific positions within a container.
4
+
5
+ ## Usage
6
+
7
+ ```tsx
8
+ import { BadgeGroup } from "@fansunited/tailwind-ui-components";
9
+
10
+ // Render all badges
11
+ <BadgeGroup badges={content.badges} />
12
+
13
+ // Only render top badges
14
+ <BadgeGroup badges={content.badges} positions={["top-left", "top-right"]} />
15
+
16
+ // With custom container styling
17
+ <BadgeGroup badges={content.badges} styles={{ container: "p-4" }} />
18
+ ```
19
+
20
+ ## Props
21
+
22
+ | Prop | Type | Default | Description |
23
+ | ----------- | --------------------------------------------------------------------- | ------------- | --------------------------- |
24
+ | `badges` | `BadgeConfig[]` | - | Array of badge configs |
25
+ | `positions` | `Array<"top-left" \| "top-right" \| "bottom-left" \| "bottom-right">` | All positions | Filter badges by position |
26
+ | `styles` | `BadgeGroupStyles` | - | Style customization options |
27
+
28
+ ### BadgeGroupStyles
29
+
30
+ | Property | Type | Description |
31
+ | ----------- | -------- | -------------------------------------------------- |
32
+ | `container` | `string` | Tailwind classes for each position group container |
33
+
34
+ ## Positioning
35
+
36
+ Badges are automatically positioned using absolute positioning:
37
+
38
+ - **top-left**: Top left corner with padding
39
+ - **top-right**: Top right corner with padding
40
+ - **bottom-left**: Bottom left corner with padding
41
+ - **bottom-right**: Bottom right corner with padding
42
+
43
+ Multiple badges at the same position are displayed in a flex row with gap.
@@ -0,0 +1,245 @@
1
+ # BettingOdds Component
2
+
3
+ A flexible React component for displaying betting odds with operator branding, change indicators, and multiple display modes.
4
+
5
+ ## Features
6
+
7
+ - **Responsive Layouts**: Automatically switches between horizontal and grid layouts based on the number of odds
8
+ - **Operator Branding**: Display betting operator logos with custom colors
9
+ - **Change Indicators**: Visual arrows showing odds movement (up/down)
10
+ - **Deep Linking**: Support for clickable odds and operator logos
11
+ - **Flash Mode**: Alternating display between operator logo and odds
12
+ - **Customizable Styling**: Configurable padding, typography, and display modes
13
+
14
+ ## Installation
15
+
16
+ ```tsx
17
+ import { BettingOdds } from "@fansunited/tailwind-ui-components";
18
+ import type { BettingOddsProps } from "@fansunited/tailwind-ui-components";
19
+ ```
20
+
21
+ ## Basic Usage
22
+
23
+ ### Simple 1X2 Odds
24
+
25
+ ```tsx
26
+ <BettingOdds
27
+ odds={[
28
+ { label: "1", value: 2.8, change: "up" },
29
+ { label: "X", value: 3.1, change: "none" },
30
+ { label: "2", value: 2.5, change: "down" },
31
+ ]}
32
+ operator={{
33
+ name: "Bet365",
34
+ logo: { url: "https://example.com/bet365-logo.png", alt: "Bet365" },
35
+ url: "https://www.bet365.com",
36
+ backgroundColor: "#037b5b",
37
+ textColor: "#ffffff",
38
+ }}
39
+ />
40
+ ```
41
+
42
+ ### Moneyline (2 Odds)
43
+
44
+ ```tsx
45
+ <BettingOdds
46
+ odds={[
47
+ { label: "Home Win", value: 1.85, url: "https://example.com/home" },
48
+ { label: "Away Win", value: 2.05, url: "https://example.com/away" },
49
+ ]}
50
+ operator={{
51
+ name: "William Hill",
52
+ url: "https://www.williamhill.com",
53
+ }}
54
+ />
55
+ ```
56
+
57
+ ## Layout Behavior
58
+
59
+ The component automatically adjusts its layout based on the number of odds:
60
+
61
+ - **1-3 odds**: Horizontal layout with operator logo (max 110px width) on the left
62
+ - **4+ odds**: Vertical layout with full-width operator logo on top and odds in a 3-column grid
63
+
64
+ ## Props
65
+
66
+ ### `BettingOddsProps`
67
+
68
+ | Prop | Type | Required | Default | Description |
69
+ | ---------- | ------------------- | -------- | ------- | -------------------------------------------- |
70
+ | `odds` | `OddsValue[]` | Yes | - | Array of odds values to display |
71
+ | `operator` | `BettingOperator` | No | - | Betting operator providing the odds |
72
+ | `label` | `string` | No | - | Overall label for odds section (e.g., "1X2") |
73
+ | `styles` | `BettingOddsStyles` | No | `{}` | Style configuration |
74
+
75
+ ### `OddsValue`
76
+
77
+ | Property | Type | Required | Description |
78
+ | ------------- | -------------------------- | -------- | --------------------------------------------------- |
79
+ | `label` | `string` | Yes | Label for the odd (e.g., "1", "X", "2", "Over 2.5") |
80
+ | `value` | `number \| string` | Yes | Odds value (e.g., 2.8, "1") |
81
+ | `url` | `string` | No | Deep link URL for this specific odd |
82
+ | `change` | `"up" \| "down" \| "none"` | No | Change indicator (default: "none") |
83
+ | `onClick` | `(odd: OddsValue) => void` | No | Click handler (suppresses default navigation) |
84
+ | `eventId` | `string` | No | Optional event ID for platform integration |
85
+ | `selectionId` | `string` | No | Optional selection ID for platform integration |
86
+
87
+ ### `BettingOperator`
88
+
89
+ | Property | Type | Required | Description |
90
+ | ----------------- | ------------------------------------- | -------- | --------------------------------------------- |
91
+ | `name` | `string` | Yes | Operator name (e.g., "Bet365") |
92
+ | `url` | `string` | Yes | Deep link URL to the betting page |
93
+ | `logo` | `ImageWithVariations` | No | Operator logo |
94
+ | `backgroundColor` | `string` | No | Custom background color (e.g., "#1e3a8a") |
95
+ | `textColor` | `string` | No | Custom text color (e.g., "#ffffff") |
96
+ | `onClick` | `(operator: BettingOperator) => void` | No | Click handler (suppresses default navigation) |
97
+
98
+ ### `BettingOddsStyles`
99
+
100
+ | Property | Type | Default | Description |
101
+ | --------------- | -------------------------------- | ----------- | ----------------------------------- |
102
+ | `padding` | `"none" \| "sm" \| "md" \| "lg"` | `"md"` | Padding size |
103
+ | `typography` | `"sm" \| "md" \| "lg"` | `"md"` | Typography size |
104
+ | `mode` | `"default" \| "flash"` | `"default"` | Display mode |
105
+ | `flashInterval` | `number` | `3000` | Flash mode interval in milliseconds |
106
+
107
+ ## Advanced Examples
108
+
109
+ ### Flash Mode
110
+
111
+ Flash mode alternates between showing the operator logo and the odds at a configurable interval:
112
+
113
+ ```tsx
114
+ <BettingOdds
115
+ odds={[
116
+ { label: "1", value: 2.8 },
117
+ { label: "X", value: 3.1 },
118
+ { label: "2", value: 2.5 },
119
+ ]}
120
+ operator={{
121
+ name: "Bet365",
122
+ logo: { url: "https://example.com/bet365-logo.png", alt: "Bet365" },
123
+ url: "https://www.bet365.com",
124
+ backgroundColor: "#037b5b",
125
+ }}
126
+ styles={{
127
+ mode: "flash",
128
+ flashInterval: 3000, // Switch every 3 seconds
129
+ }}
130
+ />
131
+ ```
132
+
133
+ ### Multiple Odds (Grid Layout)
134
+
135
+ When displaying 4 or more odds, the component automatically uses a grid layout with 3 odds per row:
136
+
137
+ ```tsx
138
+ <BettingOdds
139
+ odds={[
140
+ { label: "1-0", value: 8.5, change: "up" },
141
+ { label: "2-0", value: 12.0 },
142
+ { label: "2-1", value: 9.0, change: "down" },
143
+ { label: "0-0", value: 11.0 },
144
+ { label: "1-1", value: 6.5, change: "up" },
145
+ ]}
146
+ operator={{
147
+ name: "Bet365",
148
+ url: "https://www.bet365.com",
149
+ }}
150
+ label="Correct Score"
151
+ />
152
+ ```
153
+
154
+ ### Custom Styling
155
+
156
+ ```tsx
157
+ <BettingOdds
158
+ odds={[
159
+ { label: "Over 2.5", value: 1.85 },
160
+ { label: "Under 2.5", value: 2.05 },
161
+ ]}
162
+ operator={{
163
+ name: "Betfair",
164
+ url: "https://www.betfair.com",
165
+ }}
166
+ styles={{
167
+ padding: "lg",
168
+ typography: "lg",
169
+ }}
170
+ />
171
+ ```
172
+
173
+ ### Custom Click Handlers
174
+
175
+ You can provide custom click handlers to intercept clicks on odds or the operator logo. When provided, these handlers suppress the default navigation behavior:
176
+
177
+ ```tsx
178
+ <BettingOdds
179
+ odds={[
180
+ {
181
+ label: "1",
182
+ value: 2.8,
183
+ url: "https://www.bet365.com/home-win",
184
+ onClick: (odd) => {
185
+ // Custom tracking or navigation logic
186
+ console.log("Clicked odd:", odd.label, odd.value);
187
+ // Navigate programmatically or trigger analytics
188
+ trackBetClick(odd);
189
+ },
190
+ },
191
+ {
192
+ label: "X",
193
+ value: 3.1,
194
+ url: "https://www.bet365.com/draw",
195
+ onClick: (odd) => {
196
+ trackBetClick(odd);
197
+ },
198
+ },
199
+ {
200
+ label: "2",
201
+ value: 2.5,
202
+ url: "https://www.bet365.com/away-win",
203
+ onClick: (odd) => {
204
+ trackBetClick(odd);
205
+ },
206
+ },
207
+ ]}
208
+ operator={{
209
+ name: "Bet365",
210
+ url: "https://www.bet365.com",
211
+ onClick: (operator) => {
212
+ // Custom operator click handling
213
+ console.log("Clicked operator:", operator.name);
214
+ trackOperatorClick(operator);
215
+ },
216
+ }}
217
+ />
218
+ ```
219
+
220
+ This is useful for:
221
+
222
+ - Analytics tracking before navigation
223
+ - Custom navigation logic (e.g., opening modals, in-app browsers)
224
+ - Integration with state management
225
+ - Platform-specific deep linking
226
+
227
+ ## Styling
228
+
229
+ The component uses Tailwind CSS utility classes and respects your application's theme configuration. Key design tokens used:
230
+
231
+ - `bg-muted` / `bg-muted/50` - Background colors
232
+ - `text-foreground` / `text-muted-foreground` - Text colors
233
+ - `text-green-500` / `text-red-500` - Change indicators
234
+ - Custom colors via `backgroundColor` and `textColor` props
235
+
236
+ ## Accessibility
237
+
238
+ - All clickable odds and operator logos are properly linked with `<a>` tags
239
+ - External links include `target="_blank"` and `rel="noopener noreferrer"`
240
+ - Click events include `stopPropagation()` to prevent unwanted bubbling
241
+ - Operator logos include proper `alt` text
242
+
243
+ ## Examples
244
+
245
+ For complete working examples, see `src/examples/BettingOddsExamples.tsx` in the repository.