You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Tabs.tsx 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import React, { useCallback } from 'react';
  2. import { makeStyles } from 'tss-react/mui';
  3. import { isMobileBrowser } from '../../../environment/utils';
  4. import { withPixelLineHeight } from '../../../styles/functions.web';
  5. interface ITabProps {
  6. accessibilityLabel: string;
  7. onChange: (id: string) => void;
  8. selected: string;
  9. tabs: Array<{
  10. accessibilityLabel: string;
  11. countBadge?: number;
  12. disabled?: boolean;
  13. id: string;
  14. label: string;
  15. }>;
  16. }
  17. const useStyles = makeStyles()(theme => {
  18. return {
  19. container: {
  20. display: 'flex'
  21. },
  22. tab: {
  23. ...withPixelLineHeight(theme.typography.bodyShortBold),
  24. color: theme.palette.text02,
  25. flex: 1,
  26. padding: '14px',
  27. background: 'none',
  28. border: 0,
  29. appearance: 'none',
  30. borderBottom: `2px solid ${theme.palette.ui05}`,
  31. transition: 'color, border-color 0.2s',
  32. display: 'flex',
  33. alignItems: 'center',
  34. justifyContent: 'center',
  35. borderRadius: 0,
  36. '&:hover': {
  37. color: theme.palette.text01,
  38. borderColor: theme.palette.ui10
  39. },
  40. '&:focus': {
  41. outline: 0,
  42. boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`,
  43. border: 0,
  44. color: theme.palette.text01
  45. },
  46. '&.selected': {
  47. color: theme.palette.text01,
  48. borderColor: theme.palette.action01
  49. },
  50. '&:disabled': {
  51. color: theme.palette.text03,
  52. borderColor: theme.palette.ui05
  53. },
  54. '&.is-mobile': {
  55. ...withPixelLineHeight(theme.typography.bodyShortBoldLarge)
  56. }
  57. },
  58. badge: {
  59. ...withPixelLineHeight(theme.typography.labelBold),
  60. color: theme.palette.text04,
  61. padding: `0 ${theme.spacing(1)}`,
  62. borderRadius: '100%',
  63. backgroundColor: theme.palette.warning01,
  64. marginLeft: theme.spacing(2)
  65. }
  66. };
  67. });
  68. const Tabs = ({
  69. tabs,
  70. onChange,
  71. selected,
  72. accessibilityLabel
  73. }: ITabProps) => {
  74. const { classes, cx } = useStyles();
  75. const isMobile = isMobileBrowser();
  76. const handleChange = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
  77. onChange(e.currentTarget.id);
  78. }, []);
  79. return (
  80. <div
  81. aria-label = { accessibilityLabel }
  82. className = { classes.container }
  83. role = 'tablist'>
  84. {tabs.map(tab => (
  85. <button
  86. aria-label = { tab.accessibilityLabel }
  87. aria-selected = { selected === tab.id }
  88. className = { cx(classes.tab, selected === tab.id && 'selected', isMobile && 'is-mobile') }
  89. disabled = { tab.disabled }
  90. id = { tab.id }
  91. key = { tab.id }
  92. onClick = { handleChange }
  93. role = 'tab'>
  94. {tab.label}
  95. {tab.countBadge && <span className = { classes.badge }>{tab.countBadge}</span>}
  96. </button>
  97. ))}
  98. </div>
  99. );
  100. };
  101. export default Tabs;