Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/components/__tests__/__snapshots__/ListSection.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,16 @@ exports[`renders list section with custom title style 1`] = `
},
},
"roundness": 4,
"state": {
"opacity": {
"disabled": 0.38,
"dragged": 0.16,
"enabled": 1,
"focused": 0.1,
"hovered": 0.08,
"pressed": 0.1,
},
},
}
}
>
Expand Down Expand Up @@ -730,6 +740,16 @@ exports[`renders list section with subheader 1`] = `
},
},
"roundness": 4,
"state": {
"opacity": {
"disabled": 0.38,
"dragged": 0.16,
"enabled": 1,
"focused": 0.1,
"hovered": 0.08,
"pressed": 0.1,
},
},
}
}
>
Expand Down Expand Up @@ -1270,6 +1290,16 @@ exports[`renders list section without subheader 1`] = `
},
},
"roundness": 4,
"state": {
"opacity": {
"disabled": 0.38,
"dragged": 0.16,
"enabled": 1,
"focused": 0.1,
"hovered": 0.08,
"pressed": 0.1,
},
},
}
}
>
Expand Down
2 changes: 2 additions & 0 deletions src/theme/schemes/DarkTheme.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { baseTheme } from './base';
import { tokens } from '../tokens';
import { buildScheme } from '../tokens/sys/color/roles';
import { defaultState } from '../tokens/sys/state';
import type { Theme } from '../types';

export const DarkTheme: Theme = {
...baseTheme,
dark: true,
mode: 'adaptive',
colors: buildScheme(tokens.md.ref.palette, tokens.md.ref, { mode: 'dark' }),
state: defaultState,
};
3 changes: 3 additions & 0 deletions src/theme/schemes/DynamicTheme.android.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Platform, PlatformColor } from 'react-native';

import { DarkTheme } from './DarkTheme';
import { LightTheme } from './LightTheme';
import { defaultState } from '../tokens/sys/state';
import type { Theme } from '../types';

const isApi34 = (Platform.Version as number) >= 34;
Expand Down Expand Up @@ -494,9 +495,11 @@ const darkColors = {
export const DynamicLightTheme: Theme = {
...LightTheme,
colors: { ...LightTheme.colors, ...lightColors },
state: defaultState,
};

export const DynamicDarkTheme: Theme = {
...DarkTheme,
colors: { ...DarkTheme.colors, ...darkColors },
state: defaultState,
};
2 changes: 2 additions & 0 deletions src/theme/schemes/LightTheme.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { baseTheme } from './base';
import { tokens } from '../tokens';
import { buildScheme } from '../tokens/sys/color/roles';
import { defaultState } from '../tokens/sys/state';
import type { Theme } from '../types';

export const LightTheme: Theme = {
...baseTheme,
dark: false,
colors: buildScheme(tokens.md.ref.palette, tokens.md.ref, { mode: 'light' }),
state: defaultState,
};
4 changes: 2 additions & 2 deletions src/theme/tokens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ const ref = {
stateOpacity: {
dragged: 0.16,
pressed: 0.1,
focus: 0.1,
hover: 0.08,
focused: 0.1,
hovered: 0.08,
disabled: 0.38,
enabled: 1.0,
},
Expand Down
15 changes: 15 additions & 0 deletions src/theme/tokens/sys/state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { ThemeState } from '../../types';
import { tokens } from '../index';

const { stateOpacity } = tokens.md.ref;

export const defaultState: ThemeState = {
opacity: {
hovered: stateOpacity.hovered,
focused: stateOpacity.focused,
pressed: stateOpacity.pressed,
dragged: stateOpacity.dragged,
disabled: stateOpacity.disabled,
enabled: stateOpacity.enabled,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think this makes sense to expose enabled as a public API to customize. There shouldn't be a different opacity for enabled components other than 1.

},
};
179 changes: 0 additions & 179 deletions src/theme/types.ts

This file was deleted.

59 changes: 59 additions & 0 deletions src/theme/types/color.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import type { ElevationColors } from './elevation';

export type ThemeColors = {
primary: string;
primaryContainer: string;
secondary: string;
secondaryContainer: string;
tertiary: string;
tertiaryContainer: string;
surface: string;
surfaceDim: string;
surfaceBright: string;
surfaceContainerLowest: string;
surfaceContainerLow: string;
surfaceContainer: string;
surfaceContainerHigh: string;
surfaceContainerHighest: string;
surfaceVariant: string;
background: string;
error: string;
errorContainer: string;
onPrimary: string;
onPrimaryContainer: string;
onSecondary: string;
onSecondaryContainer: string;
onTertiary: string;
onTertiaryContainer: string;
onSurface: string;
onSurfaceVariant: string;
onError: string;
onErrorContainer: string;
onBackground: string;
outline: string;
outlineVariant: string;
inverseSurface: string;
inverseOnSurface: string;
inversePrimary: string;
primaryFixed: string;
primaryFixedDim: string;
onPrimaryFixed: string;
onPrimaryFixedVariant: string;
secondaryFixed: string;
secondaryFixedDim: string;
onSecondaryFixed: string;
onSecondaryFixedVariant: string;
tertiaryFixed: string;
tertiaryFixedDim: string;
onTertiaryFixed: string;
onTertiaryFixedVariant: string;
shadow: string;
scrim: string;
/** Pre-computed state layer color at press opacity (0.10).
* Used for ripple effects. Avoids runtime alpha manipulation
* which is incompatible with PlatformColor on Android.
* TODO: revisit after https://github.com/facebook/react-native/pull/56395
* @see https://m3.material.io/foundations/interaction/states/state-layers */
stateLayerPressed: string;
elevation: ElevationColors;
};
14 changes: 14 additions & 0 deletions src/theme/types/elevation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export type Elevation = 0 | 1 | 2 | 3 | 4 | 5;

export enum ElevationLevels {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use enums. Use union types.

Treat TypeScript as a linter and avoid TypeScript-specific constructs. This has been the direction TypeScript is also going where the syntax is aligned with JS syntax.

Enums also increase bundle size, more verbose requiring an import where just typing a string will suffice with union types, and don't really provide any advantages.

We should set erasableSyntaxOnly in TS config to enforce this in the future.

'level0',
'level1',
'level2',
'level3',
'level4',
'level5',
}

export type ElevationColors = {
[key in keyof typeof ElevationLevels]: string;
};
Comment on lines +12 to +14
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simpler code would be to do this

Suggested change
export type ElevationColors = {
[key in keyof typeof ElevationLevels]: string;
};
export type ElevationColors = Record<`level${Elevation}`, string>

7 changes: 7 additions & 0 deletions src/theme/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export * from './color';
export * from './elevation';
export * from './navigation';
export * from './state';
export * from './theme';
export * from './typography';
export * from './utils';
11 changes: 11 additions & 0 deletions src/theme/types/navigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export type NavigationTheme = {
dark: boolean;
colors: {
primary: string;
background: string;
card: string;
text: string;
border: string;
notification: string;
};
};
Loading
Loading