Button.jsx 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import { h } from 'preact';
  2. const ButtonColors = {
  3. blue: {
  4. contained: 'bg-blue-500 focus:bg-blue-400 active:bg-blue-600 ring-blue-300',
  5. outlined:
  6. 'text-blue-500 border-2 border-blue-500 hover:bg-blue-500 hover:bg-opacity-20 focus:bg-blue-500 focus:bg-opacity-40 active:bg-blue-500 active:bg-opacity-40',
  7. text:
  8. 'text-blue-500 hover:bg-blue-500 hover:bg-opacity-20 focus:bg-blue-500 focus:bg-opacity-40 active:bg-blue-500 active:bg-opacity-40',
  9. },
  10. red: {
  11. contained: 'bg-red-500 focus:bg-red-400 active:bg-red-600 ring-red-300',
  12. outlined:
  13. 'text-red-500 border-2 border-red-500 hover:bg-red-500 hover:bg-opacity-20 focus:bg-red-500 focus:bg-opacity-40 active:bg-red-500 active:bg-opacity-40',
  14. text:
  15. 'text-red-500 hover:bg-red-500 hover:bg-opacity-20 focus:bg-red-500 focus:bg-opacity-40 active:bg-red-500 active:bg-opacity-40',
  16. },
  17. green: {
  18. contained: 'bg-green-500 focus:bg-green-400 active:bg-green-600 ring-green-300',
  19. outlined:
  20. 'text-green-500 border-2 border-green-500 hover:bg-green-500 hover:bg-opacity-20 focus:bg-green-500 focus:bg-opacity-40 active:bg-green-500 active:bg-opacity-40',
  21. text:
  22. 'text-green-500 hover:bg-green-500 hover:bg-opacity-20 focus:bg-green-500 focus:bg-opacity-40 active:bg-green-500 active:bg-opacity-40',
  23. },
  24. disabled: {
  25. contained: 'bg-gray-400',
  26. outlined:
  27. 'text-gray-500 border-2 border-gray-500 hover:bg-gray-500 hover:bg-opacity-20 focus:bg-gray-500 focus:bg-opacity-40 active:bg-gray-500 active:bg-opacity-40',
  28. text:
  29. 'text-gray-500 hover:bg-gray-500 hover:bg-opacity-20 focus:bg-gray-500 focus:bg-opacity-40 active:bg-gray-500 active:bg-opacity-40',
  30. },
  31. black: {
  32. contained: '',
  33. outlined: '',
  34. text: 'text-black dark:text-white',
  35. },
  36. };
  37. const ButtonTypes = {
  38. contained: 'text-white shadow focus:shadow-xl hover:shadow-md',
  39. outlined: '',
  40. text: 'transition-opacity',
  41. };
  42. export default function Button({
  43. children,
  44. className = '',
  45. color = 'blue',
  46. disabled = false,
  47. href,
  48. size,
  49. type = 'contained',
  50. ...attrs
  51. }) {
  52. let classes = `whitespace-nowrap flex items-center space-x-1 ${className} ${ButtonTypes[type]} ${
  53. ButtonColors[disabled ? 'disabled' : color][type]
  54. } font-sans inline-flex font-bold uppercase text-xs px-2 py-2 rounded outline-none focus:outline-none ring-opacity-50 transition-shadow transition-colors ${
  55. disabled ? 'cursor-not-allowed' : 'focus:ring-2 cursor-pointer'
  56. }`;
  57. if (disabled) {
  58. classes = classes.replace(/(?:focus|active|hover):[^ ]+/g, '');
  59. }
  60. const Element = href ? 'a' : 'div';
  61. return (
  62. <Element
  63. role="button"
  64. aria-disabled={disabled ? 'true' : 'false'}
  65. tabindex="0"
  66. className={classes}
  67. href={href}
  68. {...attrs}
  69. >
  70. {children}
  71. </Element>
  72. );
  73. }