@titan-design/react-ui 0.9.1 → 0.9.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@titan-design/react-ui",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "Cross-platform design system built on Gluestack UI",
5
5
  "author": "Henry Jewkes",
6
6
  "license": "MIT",
@@ -10,7 +10,8 @@ export interface ExerciseHeadingProps {
10
10
  /** Prescription line values (sets × reps @ load). */
11
11
  sets: number
12
12
  reps: number | string
13
- load: number
13
+ /** Load value; a string (e.g. "—") passes through verbatim for an unset/discovery load. */
14
+ load: number | string
14
15
  unit?: 'lbs' | 'kg'
15
16
  /** Tempo tuple [eccentric, pauseBottom, concentric, pauseTop]; hidden when absent. */
16
17
  tempo?: [number, number, number, number]
@@ -26,10 +27,11 @@ function headingLabel(
26
27
  name: string,
27
28
  sets: number,
28
29
  reps: number | string,
29
- load: number,
30
+ load: number | string,
30
31
  unit: string
31
32
  ) {
32
- return `${name}, ${sets}×${reps} @ ${roundWeight(load)} ${unit}`
33
+ const loadLabel = typeof load === 'number' ? roundWeight(load) : load
34
+ return `${name}, ${sets}×${reps} @ ${loadLabel} ${unit}`
33
35
  }
34
36
 
35
37
  /**
@@ -1,6 +1,5 @@
1
1
  // Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
2
2
  import { View, Text, type ViewProps } from 'react-native'
3
- import { primitiveColors } from '../../../theme/tokens/primitives'
4
3
  import { getSemanticColors } from '../../../theme/tokens/semantic'
5
4
  import { Typography } from '../Typography'
6
5
  import { TimerReadout } from '../TimerReadout'
@@ -11,9 +10,11 @@ import { paceTone, paceToneColor } from './paceTone'
11
10
 
12
11
  const t = getSemanticColors('dark')
13
12
 
14
- // The raised charcoal heading plane (charcoal 400) reads as one flat surface with
15
- // the nav; depth lives on the sunk list below it, not here.
16
- const RAISED = primitiveColors.charcoal[400] // #1F1F1F
13
+ // The header shares the SideNav's `background-base` (charcoal 900, #101010) so the nav and
14
+ // the rail header read as ONE continuous dark plane on the left the sunk exercise list
15
+ // (charcoal 800) sits raised off it. Previously charcoal 400 (#1F1F1F), which made the header
16
+ // the lightest rail surface and let it blend with the rows instead of anchoring to the nav.
17
+ const HEADER_BG = t['background-base'] // #101010 — matches SideNav bg-background-base
17
18
 
18
19
  // The chunked pace bar matches the SetStrip language but sits tighter than the default
19
20
  // SetStrip gap (5) — the locked design uses a 3px gap and a 9px track.
@@ -86,7 +87,7 @@ export function SessionHeader({
86
87
  className={className}
87
88
  style={[
88
89
  {
89
- backgroundColor: RAISED,
90
+ backgroundColor: HEADER_BG,
90
91
  paddingTop: 11,
91
92
  paddingRight: 12,
92
93
  paddingBottom: 12,
@@ -8,11 +8,14 @@ import type { MetricTileData } from './MetricTiles'
8
8
  import type { SetStripSet } from './SetStrip'
9
9
  import type { ExerciseIndicatorKind } from './ExerciseIndicator'
10
10
 
11
- // Charcoal-ramp surfaces (the locked S3 shell shades): the nav + the heading plane
12
- // read as ONE flat raised surface; the exercise list is sunk. Depth comes only from
13
- // the list's subtle inset shadow (top cast by the heading, faint left edge by the nav).
14
- const INSET = primitiveColors.charcoal[800] // #131313 sunk exercise list
15
- const DIVIDER = primitiveColors.charcoal[500] // #1C1C1C row divider
11
+ // Charcoal-ramp surfaces (the locked S3 shell shades): the nav + the heading plane read as
12
+ // ONE dark plane (charcoal 900, #101010, set in SessionHeader). The exercise list is a
13
+ // LIGHTER inset panel (charcoal 600) recessed via its inner shadow yet paler than the
14
+ // header, so the transparent exercise headings on it never blend into the header plane.
15
+ // (Band-aid: the list is picked to clear the components; the durable fix is a `<Surface>`
16
+ // primitive whose cards own their own raised background — see the rail's PR notes.)
17
+ const INSET = primitiveColors.charcoal[600] // #191919 — lighter sunk exercise-list panel
18
+ const DIVIDER = primitiveColors.charcoal[300] // #2C2C2C — row divider (raised to read on #191919)
16
19
 
17
20
  const DEFAULT_WIDTH = 246
18
21
 
@@ -20,7 +23,15 @@ export interface SessionRailExercise {
20
23
  /** Stable key + press payload. Falls back to list index when absent. */
21
24
  id?: string
22
25
  name: string
23
- summary: { sets: number; reps: number | string; weight: number; unit: 'lbs' | 'kg' }
26
+ /** `weight` accepts a string (e.g. "—") for an unset/discovery load never a faked 0. */
27
+ summary: { sets: number; reps: number | string; weight: number | string; unit: 'lbs' | 'kg' }
28
+ /**
29
+ * Prescribed set count for the header total + pace-bar segment width. Distinct from
30
+ * `summary.sets`, which is the row's live DONE count (0 for the active exercise before
31
+ * its first set) — using that for the total under-counts by the active exercise's
32
+ * remaining sets. Falls back to `summary.sets` when absent.
33
+ */
34
+ plannedSets?: number
24
35
  tempo?: [number, number, number, number]
25
36
  indicator?: ExerciseIndicatorKind
26
37
  /** Per-set performance data driving the heading strip. */
@@ -84,7 +95,7 @@ export function SessionRail({
84
95
  >
85
96
  <SessionHeader
86
97
  title={title}
87
- plan={exercises.map((ex) => ({ name: ex.name, sets: ex.summary.sets }))}
98
+ plan={exercises.map((ex) => ({ name: ex.name, sets: ex.plannedSets ?? ex.summary.sets }))}
88
99
  setsDone={setsDone}
89
100
  elapsedMs={elapsedMs}
90
101
  budgetMs={budgetMs}
@@ -11,7 +11,8 @@ const AT = '@'
11
11
  export interface SetsRepsLoadProps extends ViewProps {
12
12
  sets: number
13
13
  reps: number | string
14
- load: number
14
+ /** Load value; a string (e.g. "—") passes through verbatim for an unset/discovery load. */
15
+ load: number | string
15
16
  /** Displayed load unit label (e.g. "lb", "kg"). */
16
17
  unit?: string
17
18
  /** Cell font size (px). Default 11 — the compact rail/card scale. Raise for a wall read-out. */
@@ -58,15 +58,13 @@ export function DashboardShell({
58
58
  className,
59
59
  }: DashboardShellProps) {
60
60
  return (
61
- <View className={cn('flex-1 flex-row bg-surface-base', className)}>
62
- <SideNav activeKey={activeKey} items={navItems} liveKey={liveKey} onNavigate={onNavigate} />
63
- <View className="flex-1">
64
- <TopBar
65
- state={state}
66
- devices={devices}
67
- subtitle={subtitle}
68
- onSelectDevice={onSelectDevice}
69
- />
61
+ // Column: the TopBar spans the FULL width across the top, and the SideNav sits BELOW it
62
+ // in the content row (not a full-height left rail). This keeps the brand/status band
63
+ // unbroken edge-to-edge and lets the nav align under it.
64
+ <View className={cn('flex-1 bg-surface-base', className)}>
65
+ <TopBar state={state} devices={devices} subtitle={subtitle} onSelectDevice={onSelectDevice} />
66
+ <View className="flex-1 flex-row">
67
+ <SideNav activeKey={activeKey} items={navItems} liveKey={liveKey} onNavigate={onNavigate} />
70
68
  <View className="flex-1">{children ?? <ContentPlaceholder />}</View>
71
69
  </View>
72
70
  </View>
@@ -65,7 +65,12 @@ export function NavItem({
65
65
  <Typography
66
66
  variant="button"
67
67
  color="inherit"
68
- className={cn('text-[8.5px] font-bold uppercase tracking-[0.4px]', labelColor)}
68
+ // fontSize inline, not `text-[8.5px]`: the `button` variant's `text-sm` (14px) and the
69
+ // arbitrary `text-[8.5px]` are a same-property class conflict that the consumer's
70
+ // Tailwind build resolved the wrong way (labels rendered ~14px on the wall). Inline
71
+ // size wins unambiguously; className keeps weight/case/tracking.
72
+ style={{ fontSize: 8.5, lineHeight: 11 }}
73
+ className={cn('font-bold uppercase tracking-[0.4px]', labelColor)}
69
74
  >
70
75
  {label}
71
76
  </Typography>