@tamagui/themes 1.101.7 → 1.102.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/src/v3-themes.ts CHANGED
@@ -106,7 +106,7 @@ const color = {
106
106
  ...postfixObjKeys(darkColors, 'Dark'),
107
107
  }
108
108
 
109
- export const palettes = (() => {
109
+ export const defaultPalettes = (() => {
110
110
  const transparent = (hsl: string, opacity = 0) =>
111
111
  hsl.replace(`%)`, `%, ${opacity})`).replace(`hsl(`, `hsla(`)
112
112
 
@@ -233,180 +233,185 @@ export const palettes = (() => {
233
233
  }
234
234
  })()
235
235
 
236
- export const getTemplates = (scheme: 'dark' | 'light') => {
237
- const isLight = scheme === 'light'
238
-
239
- // our palettes have 4 things padding each end until you get to bg/color:
240
- // [accentBg, transparent1, transparent2, transparent3, transparent4, background, ...]
241
- const bgIndex = 5
242
- const lighten = isLight ? -1 : 1
243
- const darken = -lighten
244
- const borderColor = bgIndex + 3
245
-
246
- // templates use the palette and specify index
247
- // negative goes backwards from end so -1 is the last item
248
- const base = {
249
- accentBackground: 0,
250
- accentColor: -0,
251
-
252
- background0: 1,
253
- background025: 2,
254
- background05: 3,
255
- background075: 4,
256
- color1: bgIndex,
257
- color2: bgIndex + 1,
258
- color3: bgIndex + 2,
259
- color4: bgIndex + 3,
260
- color5: bgIndex + 4,
261
- color6: bgIndex + 5,
262
- color7: bgIndex + 6,
263
- color8: bgIndex + 7,
264
- color9: bgIndex + 8,
265
- color10: bgIndex + 9,
266
- color11: bgIndex + 10,
267
- color12: bgIndex + 11,
268
- color0: -1,
269
- color025: -2,
270
- color05: -3,
271
- color075: -4,
272
- // the background, color, etc keys here work like generics - they make it so you
273
- // can publish components for others to use without mandating a specific color scale
274
- // the @tamagui/button Button component looks for `$background`, so you set the
275
- // dark_red_Button theme to have a stronger background than the dark_red theme.
276
- background: bgIndex,
277
- backgroundHover: bgIndex + lighten, // always lighten on hover no matter the scheme
278
- backgroundPress: bgIndex + darken, // always darken on press no matter the theme
279
- backgroundFocus: bgIndex + darken,
280
- borderColor,
281
- borderColorHover: borderColor + lighten,
282
- borderColorPress: borderColor + darken,
283
- borderColorFocus: borderColor,
284
- color: -bgIndex,
285
- colorHover: -bgIndex - 1,
286
- colorPress: -bgIndex,
287
- colorFocus: -bgIndex - 1,
288
- colorTransparent: -1,
289
- placeholderColor: -bgIndex - 3,
290
- outlineColor: -2,
291
- }
236
+ const getTemplates = () => {
237
+ const getBaseTemplates = (scheme: 'dark' | 'light') => {
238
+ const isLight = scheme === 'light'
239
+
240
+ // our palettes have 4 things padding each end until you get to bg/color:
241
+ // [accentBg, transparent1, transparent2, transparent3, transparent4, background, ...]
242
+ const bgIndex = 5
243
+ const lighten = isLight ? -1 : 1
244
+ const darken = -lighten
245
+ const borderColor = bgIndex + 3
246
+
247
+ // templates use the palette and specify index
248
+ // negative goes backwards from end so -1 is the last item
249
+ const base = {
250
+ accentBackground: 0,
251
+ accentColor: -0,
252
+
253
+ background0: 1,
254
+ background025: 2,
255
+ background05: 3,
256
+ background075: 4,
257
+ color1: bgIndex,
258
+ color2: bgIndex + 1,
259
+ color3: bgIndex + 2,
260
+ color4: bgIndex + 3,
261
+ color5: bgIndex + 4,
262
+ color6: bgIndex + 5,
263
+ color7: bgIndex + 6,
264
+ color8: bgIndex + 7,
265
+ color9: bgIndex + 8,
266
+ color10: bgIndex + 9,
267
+ color11: bgIndex + 10,
268
+ color12: bgIndex + 11,
269
+ color0: -1,
270
+ color025: -2,
271
+ color05: -3,
272
+ color075: -4,
273
+ // the background, color, etc keys here work like generics - they make it so you
274
+ // can publish components for others to use without mandating a specific color scale
275
+ // the @tamagui/button Button component looks for `$background`, so you set the
276
+ // dark_red_Button theme to have a stronger background than the dark_red theme.
277
+ background: bgIndex,
278
+ backgroundHover: bgIndex + lighten, // always lighten on hover no matter the scheme
279
+ backgroundPress: bgIndex + darken, // always darken on press no matter the theme
280
+ backgroundFocus: bgIndex + darken,
281
+ borderColor,
282
+ borderColorHover: borderColor + lighten,
283
+ borderColorPress: borderColor + darken,
284
+ borderColorFocus: borderColor,
285
+ color: -bgIndex,
286
+ colorHover: -bgIndex - 1,
287
+ colorPress: -bgIndex,
288
+ colorFocus: -bgIndex - 1,
289
+ colorTransparent: -1,
290
+ placeholderColor: -bgIndex - 3,
291
+ outlineColor: -2,
292
+ }
292
293
 
293
- const surface1 = {
294
- background: base.background + 1,
295
- backgroundHover: base.backgroundHover + 1,
296
- backgroundPress: base.backgroundPress + 1,
297
- backgroundFocus: base.backgroundFocus + 1,
298
- borderColor: base.borderColor + 1,
299
- borderColorHover: base.borderColorHover + 1,
300
- borderColorFocus: base.borderColorFocus + 1,
301
- borderColorPress: base.borderColorPress + 1,
302
- }
294
+ const surface1 = {
295
+ background: base.background + 1,
296
+ backgroundHover: base.backgroundHover + 1,
297
+ backgroundPress: base.backgroundPress + 1,
298
+ backgroundFocus: base.backgroundFocus + 1,
299
+ borderColor: base.borderColor + 1,
300
+ borderColorHover: base.borderColorHover + 1,
301
+ borderColorFocus: base.borderColorFocus + 1,
302
+ borderColorPress: base.borderColorPress + 1,
303
+ }
303
304
 
304
- const surface2 = {
305
- background: base.background + 2,
306
- backgroundHover: base.backgroundHover + 2,
307
- backgroundPress: base.backgroundPress + 2,
308
- backgroundFocus: base.backgroundFocus + 2,
309
- borderColor: base.borderColor + 2,
310
- borderColorHover: base.borderColorHover + 2,
311
- borderColorFocus: base.borderColorFocus + 2,
312
- borderColorPress: base.borderColorPress + 2,
313
- }
305
+ const surface2 = {
306
+ background: base.background + 2,
307
+ backgroundHover: base.backgroundHover + 2,
308
+ backgroundPress: base.backgroundPress + 2,
309
+ backgroundFocus: base.backgroundFocus + 2,
310
+ borderColor: base.borderColor + 2,
311
+ borderColorHover: base.borderColorHover + 2,
312
+ borderColorFocus: base.borderColorFocus + 2,
313
+ borderColorPress: base.borderColorPress + 2,
314
+ }
314
315
 
315
- const surface3 = {
316
- background: base.background + 3,
317
- backgroundHover: base.backgroundHover + 3,
318
- backgroundPress: base.backgroundPress + 3,
319
- backgroundFocus: base.backgroundFocus + 3,
320
- borderColor: base.borderColor + 3,
321
- borderColorHover: base.borderColorHover + 3,
322
- borderColorFocus: base.borderColorFocus + 3,
323
- borderColorPress: base.borderColorPress + 3,
324
- }
316
+ const surface3 = {
317
+ background: base.background + 3,
318
+ backgroundHover: base.backgroundHover + 3,
319
+ backgroundPress: base.backgroundPress + 3,
320
+ backgroundFocus: base.backgroundFocus + 3,
321
+ borderColor: base.borderColor + 3,
322
+ borderColorHover: base.borderColorHover + 3,
323
+ borderColorFocus: base.borderColorFocus + 3,
324
+ borderColorPress: base.borderColorPress + 3,
325
+ }
325
326
 
326
- const surfaceActiveBg = {
327
- background: base.background + 5,
328
- backgroundHover: base.background + 5,
329
- backgroundPress: base.backgroundPress + 5,
330
- backgroundFocus: base.backgroundFocus + 5,
331
- }
327
+ const surfaceActiveBg = {
328
+ background: base.background + 5,
329
+ backgroundHover: base.background + 5,
330
+ backgroundPress: base.backgroundPress + 5,
331
+ backgroundFocus: base.backgroundFocus + 5,
332
+ }
332
333
 
333
- const surfaceActive = {
334
- ...surfaceActiveBg,
335
- // match border to background when active
336
- borderColor: surfaceActiveBg.background,
337
- borderColorHover: surfaceActiveBg.backgroundHover,
338
- borderColorFocus: surfaceActiveBg.backgroundFocus,
339
- borderColorPress: surfaceActiveBg.backgroundPress,
340
- }
334
+ const surfaceActive = {
335
+ ...surfaceActiveBg,
336
+ // match border to background when active
337
+ borderColor: surfaceActiveBg.background,
338
+ borderColorHover: surfaceActiveBg.backgroundHover,
339
+ borderColorFocus: surfaceActiveBg.backgroundFocus,
340
+ borderColorPress: surfaceActiveBg.backgroundPress,
341
+ }
341
342
 
342
- const inverseSurface1 = {
343
- color: surface1.background,
344
- colorHover: surface1.backgroundHover,
345
- colorPress: surface1.backgroundPress,
346
- colorFocus: surface1.backgroundFocus,
347
- background: base.color,
348
- backgroundHover: base.colorHover,
349
- backgroundPress: base.colorPress,
350
- backgroundFocus: base.colorFocus,
351
- borderColor: base.color - 2,
352
- borderColorHover: base.color - 3,
353
- borderColorFocus: base.color - 4,
354
- borderColorPress: base.color - 5,
355
- }
343
+ const inverseSurface1 = {
344
+ color: surface1.background,
345
+ colorHover: surface1.backgroundHover,
346
+ colorPress: surface1.backgroundPress,
347
+ colorFocus: surface1.backgroundFocus,
348
+ background: base.color,
349
+ backgroundHover: base.colorHover,
350
+ backgroundPress: base.colorPress,
351
+ backgroundFocus: base.colorFocus,
352
+ borderColor: base.color - 2,
353
+ borderColorHover: base.color - 3,
354
+ borderColorFocus: base.color - 4,
355
+ borderColorPress: base.color - 5,
356
+ }
356
357
 
357
- const inverseActive = {
358
- ...inverseSurface1,
359
- background: base.color - 2,
360
- backgroundHover: base.colorHover - 2,
361
- backgroundPress: base.colorPress - 2,
362
- backgroundFocus: base.colorFocus - 2,
363
- borderColor: base.color - 2 - 2,
364
- borderColorHover: base.color - 3 - 2,
365
- borderColorFocus: base.color - 4 - 2,
366
- borderColorPress: base.color - 5 - 2,
367
- }
358
+ const inverseActive = {
359
+ ...inverseSurface1,
360
+ background: base.color - 2,
361
+ backgroundHover: base.colorHover - 2,
362
+ backgroundPress: base.colorPress - 2,
363
+ backgroundFocus: base.colorFocus - 2,
364
+ borderColor: base.color - 2 - 2,
365
+ borderColorHover: base.color - 3 - 2,
366
+ borderColorFocus: base.color - 4 - 2,
367
+ borderColorPress: base.color - 5 - 2,
368
+ }
368
369
 
369
- const alt1 = {
370
- color: base.color - 1,
371
- colorHover: base.colorHover - 1,
372
- colorPress: base.colorPress - 1,
373
- colorFocus: base.colorFocus - 1,
374
- }
370
+ const alt1 = {
371
+ color: base.color - 1,
372
+ colorHover: base.colorHover - 1,
373
+ colorPress: base.colorPress - 1,
374
+ colorFocus: base.colorFocus - 1,
375
+ }
376
+
377
+ const alt2 = {
378
+ color: base.color - 2,
379
+ colorHover: base.colorHover - 2,
380
+ colorPress: base.colorPress - 2,
381
+ colorFocus: base.colorFocus - 2,
382
+ }
375
383
 
376
- const alt2 = {
377
- color: base.color - 2,
378
- colorHover: base.colorHover - 2,
379
- colorPress: base.colorPress - 2,
380
- colorFocus: base.colorFocus - 2,
384
+ return {
385
+ base,
386
+ alt1,
387
+ alt2,
388
+ surface1,
389
+ surface2,
390
+ surface3,
391
+ inverseSurface1,
392
+ inverseActive,
393
+ surfaceActive,
394
+ }
381
395
  }
382
396
 
383
- return {
384
- base,
385
- alt1,
386
- alt2,
387
- surface1,
388
- surface2,
389
- surface3,
390
- inverseSurface1,
391
- inverseActive,
392
- surfaceActive,
397
+ const lightTemplates = getBaseTemplates('light')
398
+ const darkTemplates = getBaseTemplates('dark')
399
+ const templates = {
400
+ ...objectFromEntries(
401
+ objectKeys(lightTemplates).map(
402
+ (name) => [`light_${name}`, lightTemplates[name]] as const
403
+ )
404
+ ),
405
+ ...objectFromEntries(
406
+ objectKeys(darkTemplates).map(
407
+ (name) => [`dark_${name}`, darkTemplates[name]] as const
408
+ )
409
+ ),
393
410
  }
411
+ return templates as Record<keyof typeof templates, typeof lightTemplates.base>
394
412
  }
395
413
 
396
- const lightTemplates = getTemplates('light')
397
- const darkTemplates = getTemplates('dark')
398
- const templates = {
399
- ...objectFromEntries(
400
- objectKeys(lightTemplates).map(
401
- (name) => [`light_${name}`, lightTemplates[name]] as const
402
- )
403
- ),
404
- ...objectFromEntries(
405
- objectKeys(darkTemplates).map(
406
- (name) => [`dark_${name}`, darkTemplates[name]] as const
407
- )
408
- ),
409
- }
414
+ export const defaultTemplates = getTemplates()
410
415
 
411
416
  const shadows = {
412
417
  light: {
@@ -493,11 +498,83 @@ const surface3 = [
493
498
  },
494
499
  ] as any
495
500
 
501
+ /**
502
+ * These are optional themes that serve as defaults for components. They don't
503
+ * change color1 through color12 just "generic" properties like color,
504
+ * background, borderColor.
505
+ *
506
+ * They can be overridden with the theme prop, or left out entirely for
507
+ * "un-themed" components.
508
+
509
+ */
510
+ export const defaultComponentThemes = {
511
+ ListItem: {
512
+ template: 'surface1',
513
+ },
514
+ SelectTrigger: surface1,
515
+ Card: surface1,
516
+ Button: surface3,
517
+ Checkbox: surface2,
518
+ Switch: surface2,
519
+ SwitchThumb: inverseSurface1,
520
+ TooltipContent: surface2,
521
+ Progress: {
522
+ template: 'surface1',
523
+ },
524
+ RadioGroupItem: surface2,
525
+ TooltipArrow: {
526
+ template: 'surface1',
527
+ },
528
+ SliderTrackActive: {
529
+ template: 'surface3',
530
+ },
531
+ SliderTrack: {
532
+ template: 'surface1',
533
+ },
534
+ SliderThumb: inverseSurface1,
535
+ Tooltip: inverseSurface1,
536
+ ProgressIndicator: inverseSurface1,
537
+ SheetOverlay: overlayThemeDefinitions,
538
+ DialogOverlay: overlayThemeDefinitions,
539
+ ModalOverlay: overlayThemeDefinitions,
540
+ Input: surface1,
541
+ TextArea: surface1,
542
+ } as const
543
+
544
+ /**
545
+ * These are useful for states (alt gets more subtle as it goes up) or emphasis
546
+ * (surface gets more contrasted from the background as it goes up)
547
+ */
548
+
549
+ export const defaultSubThemes = {
550
+ alt1: {
551
+ template: 'alt1',
552
+ },
553
+ alt2: {
554
+ template: 'alt2',
555
+ },
556
+ active: {
557
+ template: 'surface3',
558
+ },
559
+ surface1: {
560
+ template: 'surface1',
561
+ },
562
+ surface2: {
563
+ template: 'surface2',
564
+ },
565
+ surface3: {
566
+ template: 'surface3',
567
+ },
568
+ surface4: {
569
+ template: 'surfaceActive',
570
+ },
571
+ } as const
572
+
496
573
  // --- themeBuilder ---
497
574
 
498
575
  const themeBuilder = createThemeBuilder()
499
- .addPalettes(palettes)
500
- .addTemplates(templates)
576
+ .addPalettes(defaultPalettes)
577
+ .addTemplates(defaultTemplates)
501
578
  .addThemes({
502
579
  light: {
503
580
  template: 'base',
@@ -544,81 +621,20 @@ const themeBuilder = createThemeBuilder()
544
621
  template: 'base',
545
622
  },
546
623
  })
547
- .addChildThemes({
548
- alt1: {
549
- template: 'alt1',
550
- },
551
- alt2: {
552
- template: 'alt2',
553
- },
554
- active: {
555
- template: 'surface3',
556
- },
557
- surface1: {
558
- template: 'surface1',
559
- },
560
- surface2: {
561
- template: 'surface2',
562
- },
563
- surface3: {
564
- template: 'surface3',
565
- },
566
- surface4: {
567
- template: 'surfaceActive',
568
- },
624
+ .addChildThemes(defaultSubThemes)
625
+ .addComponentThemes(defaultComponentThemes, {
626
+ avoidNestingWithin: ['alt1', 'alt2', 'surface1', 'surface2', 'surface3', 'surface4'],
569
627
  })
570
- .addComponentThemes(
571
- {
572
- ListItem: {
573
- template: 'surface1',
574
- },
575
- SelectTrigger: surface1,
576
- Card: surface1,
577
- Button: surface3,
578
- Checkbox: surface2,
579
- Switch: surface2,
580
- SwitchThumb: inverseSurface1,
581
- TooltipContent: surface2,
582
- Progress: {
583
- template: 'surface1',
584
- },
585
- RadioGroupItem: surface2,
586
- TooltipArrow: {
587
- template: 'surface1',
588
- },
589
- SliderTrackActive: {
590
- template: 'surface3',
591
- },
592
- SliderTrack: {
593
- template: 'surface1',
594
- },
595
- SliderThumb: inverseSurface1,
596
- Tooltip: inverseSurface1,
597
- ProgressIndicator: inverseSurface1,
598
- SheetOverlay: overlayThemeDefinitions,
599
- DialogOverlay: overlayThemeDefinitions,
600
- ModalOverlay: overlayThemeDefinitions,
601
- Input: surface1,
602
- TextArea: surface1,
603
- },
604
- {
605
- avoidNestingWithin: [
606
- 'alt1',
607
- 'alt2',
608
- 'surface1',
609
- 'surface2',
610
- 'surface3',
611
- 'surface4',
612
- ],
613
- }
614
- )
615
628
 
616
629
  // --- themes ---
617
630
 
618
631
  const themesIn = themeBuilder.build()
619
632
 
620
- export type Theme = Record<keyof typeof lightTemplates.base, string> &
621
- typeof nonInherited.light
633
+ type ThemeKeys =
634
+ | keyof typeof defaultTemplates.light_base
635
+ | keyof typeof nonInherited.light
636
+
637
+ export type Theme = Record<ThemeKeys, string>
622
638
 
623
639
  export type ThemesOut = Record<keyof typeof themesIn, Theme>
624
640