@furystack/shades-common-components
Version:
Common UI components for FuryStack Shades
132 lines • 6.11 kB
JavaScript
import { Shade, createComponent } from '@furystack/shades';
import { buildTransition, cssVariableTheme } from '../services/css-variable-theme.js';
import { paletteMainColors } from '../services/palette-css-vars.js';
import { Icon } from './icons/icon.js';
import { checkCircle, close as closeIcon, errorCircle, info as infoIcon, warning as warningIcon, } from './icons/icon-definitions.js';
const severityColorMap = {
error: { ...paletteMainColors.error, light: cssVariableTheme.palette.error.light },
warning: { ...paletteMainColors.warning, light: cssVariableTheme.palette.warning.light },
info: { ...paletteMainColors.info, light: cssVariableTheme.palette.info.light },
success: { ...paletteMainColors.success, light: cssVariableTheme.palette.success.light },
};
const defaultIconDefs = {
error: errorCircle,
warning: warningIcon,
info: infoIcon,
success: checkCircle,
};
const getDefaultIcon = (severity) => createComponent(Icon, { icon: defaultIconDefs[severity], size: "small" });
export const Alert = Shade({
customElementName: 'shade-alert',
css: {
display: 'flex',
alignItems: 'flex-start',
gap: cssVariableTheme.spacing.md,
padding: `${cssVariableTheme.spacing.md} ${cssVariableTheme.spacing.lg}`,
fontFamily: cssVariableTheme.typography.fontFamily,
fontSize: cssVariableTheme.typography.fontSize.sm,
lineHeight: '1.5',
borderRadius: cssVariableTheme.shape.borderRadius.md,
boxSizing: 'border-box',
transition: buildTransition(['background', cssVariableTheme.transitions.duration.fast, cssVariableTheme.transitions.easing.default], ['color', cssVariableTheme.transitions.duration.fast, cssVariableTheme.transitions.easing.default], ['box-shadow', cssVariableTheme.transitions.duration.fast, cssVariableTheme.transitions.easing.default]),
// ==========================================
// STANDARD VARIANT (default)
// ==========================================
'&:not([data-variant]), &[data-variant="standard"]': {
background: 'color-mix(in srgb, var(--alert-color-main) 12%, transparent)',
color: 'var(--alert-color-main)',
},
// ==========================================
// FILLED VARIANT
// ==========================================
'&[data-variant="filled"]': {
background: 'var(--alert-color-main)',
color: 'var(--alert-color-main-contrast)',
},
// ==========================================
// OUTLINED VARIANT
// ==========================================
'&[data-variant="outlined"]': {
background: 'transparent',
color: 'var(--alert-color-main)',
boxShadow: '0px 0px 0px 1px var(--alert-color-main)',
},
// ==========================================
// ICON
// ==========================================
'& .alert-icon': {
display: 'flex',
alignItems: 'center',
fontSize: '20px',
lineHeight: '1',
flexShrink: '0',
paddingTop: '1px',
},
// ==========================================
// CONTENT
// ==========================================
'& .alert-content': {
flex: '1',
minWidth: '0',
},
'& .alert-title': {
fontWeight: cssVariableTheme.typography.fontWeight.semibold,
marginBottom: cssVariableTheme.spacing.xs,
},
'& .alert-message': {
opacity: '0.9',
},
// ==========================================
// CLOSE BUTTON
// ==========================================
'& .alert-close': {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
cursor: 'pointer',
borderRadius: cssVariableTheme.shape.borderRadius.full,
border: 'none',
background: 'transparent',
color: 'inherit',
padding: '4px',
marginTop: '-2px',
marginRight: `-${cssVariableTheme.spacing.sm}`,
fontSize: '14px',
lineHeight: '1',
opacity: '0.7',
flexShrink: '0',
transition: buildTransition(['opacity', cssVariableTheme.transitions.duration.fast, cssVariableTheme.transitions.easing.default], ['background', cssVariableTheme.transitions.duration.fast, cssVariableTheme.transitions.easing.default]),
},
'& .alert-close:hover': {
opacity: '1',
background: 'color-mix(in srgb, currentColor 15%, transparent)',
},
},
render: ({ props, children, useHostProps }) => {
const { severity = 'info', variant, title, onClose, icon, style } = props;
const colors = severityColorMap[severity];
useHostProps({
'data-variant': variant || undefined,
'data-severity': severity,
role: 'alert',
style: {
'--alert-color-main': colors.main,
'--alert-color-main-contrast': colors.mainContrast,
'--alert-color-light': colors.light,
...style,
},
});
const displayIcon = icon ?? getDefaultIcon(severity);
return (createComponent(createComponent, null,
createComponent("span", { className: "alert-icon" }, displayIcon),
createComponent("div", { className: "alert-content" },
title ? createComponent("div", { className: "alert-title" }, title) : null,
createComponent("div", { className: "alert-message" }, children)),
onClose ? (createComponent("span", { className: "alert-close", role: "button", onclick: (ev) => {
ev.stopPropagation();
onClose(ev);
} },
createComponent(Icon, { icon: closeIcon, size: "small" }))) : null));
},
});
//# sourceMappingURL=alert.js.map