@codecademy/gamut
72.3.072.3.1-alpha.f273fd.0
Chip.tsx+
Chip.tsxNew file+97
Index: Chip.tsx
===================================================================
--- Chip.tsx
+++ Chip.tsx
@@ -0,0 +1,97 @@
+import { css, states } from '@codecademy/gamut-styles';
+import { StyleProps } from '@codecademy/variance';
+import styled from '@emotion/styled';
+import * as React from 'react';
+
+/**
+ * `selected` and `disabled` are independent toggles — either, both, or
+ * neither may be true at the same time. `states()` applies each block's
+ * styles based on its own boolean prop, so the two never clobber each other
+ * the way a `variant()` mode map would.
+ */
+const chipStates = states({
+ base: {
+ alignItems: 'center',
+ bg: 'background',
+ border: 1,
+ borderColor: 'border-primary',
+ borderRadius: 'full',
+ color: 'text',
+ cursor: 'pointer',
+ display: 'inline-flex',
+ fontSize: 14,
+ justifyContent: 'center',
+ lineHeight: 1.5 as any,
+ px: 12,
+ py: 4,
+ transition:
+ 'background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease',
+ '&:hover': {
+ bg: 'background-hover',
+ },
+ '&:focus-visible': {
+ outline: '2px solid currentColor',
+ outlineOffset: '2px',
+ },
+ },
+ selected: {
+ bg: 'background-selected',
+ borderColor: 'primary',
+ color: 'primary',
+ },
+ disabled: {
+ cursor: 'not-allowed',
+ opacity: 0.5,
+ pointerEvents: 'none',
+ '&:hover': {
+ bg: 'background',
+ },
+ },
+});
+
+export type ChipStyleProps = StyleProps<typeof chipStates>;
+
+const ChipBase = styled.button<ChipStyleProps>(
+ css({
+ appearance: 'none',
+ outline: 'none',
+ userSelect: 'none',
+ whiteSpace: 'nowrap',
+ }),
+ chipStates
+);
+
+export type ChipProps = Omit<
+ React.ButtonHTMLAttributes<HTMLButtonElement>,
+ 'disabled'
+> & {
+ /**
+ * Highlights the Chip's border, background, and text to show it is the
+ * active/selected choice. Independent of `disabled` — a Chip can be
+ * selected and disabled at the same time.
+ */
+ selected?: boolean;
+ /**
+ * Dims the Chip and disables pointer interaction. Independent of
+ * `selected` — a Chip can be disabled while still showing as selected.
+ */
+ disabled?: boolean;
+};
+
+export const Chip: React.FC<ChipProps> = ({
+ selected = false,
+ disabled = false,
+ type = 'button',
+ ...rest
+}) => {
+ return (
+ <ChipBase
+ aria-disabled={disabled}
+ aria-selected={selected}
+ disabled={disabled}
+ selected={selected}
+ type={type}
+ {...rest}
+ />
+ );
+};