UNPKG

@gitlab/ui

Version:
610 lines (603 loc) • 17.9 kB
const { range, round } = require('lodash'); const plugin = require('tailwindcss/plugin'); const { colors, backgroundColor, borderColor, outlineColor, fill, textColor, } = require('./src/tokens/build/tailwind/tokens.cjs'); const gridSize = 0.5; // rem const spacing = { 0: '0', px: '1px', ...Object.fromEntries( Object.entries({ 1: 0.25, 2: 0.5, 3: 1, 4: 1.5, 5: 2, 6: 3, 7: 4, 8: 5, 9: 6, 10: 7, 11: 8, '11-5': 9, 12: 10, 13: 12, 15: 15, 20: 20, 26: 26, 28: 28, 30: 30, 31: 31, 34: 34, 48: 48, 62: 62, 75: 75, 80: 80, 88: 88, }).map(([scale, factor]) => { return [scale, `${factor * gridSize}rem`]; }) ), }; function addCustomDefinitions({ addComponents, addUtilities }) { addComponents({ '.animate-skeleton-loader': { overflow: 'hidden', 'max-width': '32rem', 'background-size': '32rem 100%', 'background-position': '-32rem 0', 'background-color': 'var(--gl-skeleton-loader-background-color)', 'background-image': 'linear-gradient(to right, var(--gl-skeleton-loader-background-color) 0, var(--gl-skeleton-loader-shimmer-color) 23%, var(--gl-skeleton-loader-shimmer-color) 27%, var(--gl-skeleton-loader-background-color) 50%)', 'background-repeat': 'no-repeat', '@media (prefers-reduced-motion: no-preference)': { animation: 'gl-keyframes-skeleton-loader 2.5s linear', 'animation-delay': 'inherit', 'animation-iteration-count': '3', }, '@keyframes gl-keyframes-skeleton-loader': { '0%': { // absolute numbers are required to make the animation width-independent 'background-position-x': '-32rem', }, '100%': { 'background-position-x': '32rem', }, }, }, '.border': { 'border-style': 'solid', 'border-color': 'var(--gl-border-color-default)', }, '.border-t': { 'border-top-style': 'solid', 'border-top-color': 'var(--gl-border-color-default)', }, '.border-r': { 'border-right-style': 'solid', 'border-right-color': 'var(--gl-border-color-default)', }, '.border-b': { 'border-bottom-style': 'solid', 'border-bottom-color': 'var(--gl-border-color-default)', }, '.border-l': { 'border-left-style': 'solid', 'border-left-color': 'var(--gl-border-color-default)', }, '.str-truncated': { display: 'inline-block', overflow: 'hidden', 'text-overflow': 'ellipsis', 'vertical-align': 'top', 'white-space': 'nowrap', 'max-width': '82%', }, '.no-spin[type="number"]': { '&::-webkit-outer-spin-button': { '-webkit-appearance': 'none', margin: '0', }, '&::-webkit-inner-spin-button': { '-webkit-appearance': 'none', margin: '0', }, '-moz-appearance': 'textfield', }, '.heading-6': { 'font-weight': '600', 'margin-top': '0', 'font-size': '0.8125rem', 'letter-spacing': 'inherit', 'line-height': '1.25', 'margin-bottom': '1rem', color: 'var(--gl-text-color-heading)', }, '.heading-6-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '0.8125rem', 'letter-spacing': 'inherit', 'line-height': '1.25', 'margin-bottom': '1rem', color: 'var(--gl-text-color-heading)', }, '.heading-5': { 'font-weight': '600', 'margin-top': '0', 'font-size': '0.875rem', 'letter-spacing': 'inherit', 'line-height': '1.25', 'margin-bottom': '1rem', color: 'var(--gl-text-color-heading)', }, '.heading-5-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '0.875rem', 'letter-spacing': 'inherit', 'line-height': '1.25', 'margin-bottom': '1rem', color: 'var(--gl-text-color-heading)', }, '.heading-4': { 'font-weight': '600', 'margin-top': '0', 'font-size': '1rem', 'letter-spacing': 'inherit', 'line-height': '1.25', 'margin-bottom': '1rem', color: 'var(--gl-text-color-heading)', }, '.heading-4-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '1rem', 'letter-spacing': 'inherit', 'line-height': '1.25', 'margin-bottom': '1rem', color: 'var(--gl-text-color-heading)', }, '.heading-3': { 'font-weight': '600', 'margin-top': '0', 'font-size': 'clamp(1.125rem, 0.9027777778rem + 0.462962963vw, 1.25rem)', 'letter-spacing': 'inherit', 'line-height': '1.25', 'margin-bottom': '1rem', color: 'var(--gl-text-color-heading)', }, '.heading-3-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '1.125rem', 'letter-spacing': 'inherit', 'line-height': '1.25', 'margin-bottom': '1rem', color: 'var(--gl-text-color-heading)', }, '.heading-2': { 'font-weight': '600', 'margin-top': '0', 'font-size': 'clamp(1.3125rem, 0.8680555556rem + 0.9259259259vw, 1.5625rem)', 'letter-spacing': '-0.01em', 'line-height': '1.25', 'margin-bottom': '1rem', color: 'var(--gl-text-color-heading)', }, '.heading-2-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '1.3125rem', 'letter-spacing': '-0.01em', 'line-height': '1.25', 'margin-bottom': '1rem', color: 'var(--gl-text-color-heading)', }, '.heading-1': { 'font-weight': '600', 'margin-top': '0', 'font-size': 'clamp(1.5rem, 0.8333333333rem + 1.3888888889vw, 1.875rem)', 'letter-spacing': '-0.01em', 'line-height': '1.25', 'margin-bottom': '1rem', color: 'var(--gl-text-color-heading)', }, '.heading-1-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '1.5rem', 'letter-spacing': '-0.01em', 'line-height': '1.25', 'margin-bottom': '1rem', color: 'var(--gl-text-color-heading)', }, '.heading-display': { 'font-weight': '600', 'margin-top': '0', 'font-size': 'clamp(1.75rem, 0.8611111111rem + 1.8518518519vw, 2.25rem)', 'letter-spacing': '-0.01em', 'line-height': '1.125', 'margin-bottom': '1.5rem', color: 'var(--gl-text-color-heading)', }, /** * gl-heading-scale classes define default properties for heading typography * based on font-size scale value and default or fixed sizing. * * Note: overrides Bootstrap margin-top, other margin is determined by * individual context. Larger headings have reduced letter spacing. * Display heading (800) has different line height. */ '.heading-scale-100': { 'font-weight': '600', 'margin-top': '0', 'font-size': '0.75rem', 'letter-spacing': 'inherit', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-100-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '0.75rem', 'letter-spacing': 'inherit', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-200': { 'font-weight': '600', 'margin-top': '0', 'font-size': '0.8125rem', 'letter-spacing': 'inherit', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-200-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '0.8125rem', 'letter-spacing': 'inherit', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-300': { 'font-weight': '600', 'margin-top': '0', 'font-size': '0.875rem', 'letter-spacing': 'inherit', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-300-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '0.875rem', 'letter-spacing': 'inherit', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-400': { 'font-weight': '600', 'margin-top': '0', 'font-size': '1rem', 'letter-spacing': 'inherit', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-400-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '1rem', 'letter-spacing': 'inherit', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-500': { 'font-weight': '600', 'margin-top': '0', 'font-size': 'clamp(1.125rem, 0.9027777778rem + 0.462962963vw, 1.25rem)', 'letter-spacing': 'inherit', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-500-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '1.125rem', 'letter-spacing': 'inherit', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-600': { 'font-weight': '600', 'margin-top': '0', 'font-size': 'clamp(1.3125rem, 0.8680555556rem + 0.9259259259vw, 1.5625rem)', 'letter-spacing': '-0.01em', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-600-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '1.3125rem', 'letter-spacing': '-0.01em', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-700': { 'font-weight': '600', 'margin-top': '0', 'font-size': 'clamp(1.5rem, 0.8333333333rem + 1.3888888889vw, 1.875rem)', 'letter-spacing': '-0.01em', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-700-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '1.5rem', 'letter-spacing': '-0.01em', 'line-height': '1.25', color: 'var(--gl-text-color-heading)', }, '.heading-scale-800': { 'font-weight': '600', 'margin-top': '0', 'font-size': 'clamp(1.75rem, 0.8611111111rem + 1.8518518519vw, 2.25rem)', 'letter-spacing': '-0.01em', 'line-height': '1.125', color: 'var(--gl-text-color-heading)', }, '.heading-scale-800-fixed': { 'font-weight': '600', 'margin-top': '0', 'font-size': '1.75rem', 'letter-spacing': '-0.01em', 'line-height': '1.125', color: 'var(--gl-text-color-heading)', }, }); addUtilities({ '.font-monospace': { 'font-family': 'var(--default-mono-font, "GitLab Mono"), "JetBrains Mono", "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace', 'font-variant-ligatures': 'none', }, '.break-anywhere': { 'overflow-wrap': 'anywhere', 'word-break': 'normal', }, '.wrap-anywhere': { 'overflow-wrap': 'anywhere', }, '.border-b-solid': { 'border-bottom-style': 'solid', }, '.border-b-initial': { 'border-bottom-style': 'initial', }, '.border-l-solid': { 'border-left-style': 'solid', }, '.border-r-solid': { 'border-right-style': 'solid', }, '.border-t-solid': { 'border-top-style': 'solid', }, '.clearfix': { '&::after': { display: 'block', clear: 'both', content: '""', }, }, '.focus': { 'box-shadow': '0 0 0 1px var(--gl-focus-ring-inner-color), 0 0 0 3px var(--gl-focus-ring-outer-color)', outline: 'none', }, '.focus-inset': { 'box-shadow': 'inset 0 0 0 2px var(--gl-focus-ring-outer-color), inset 0 0 0 3px var(--gl-focus-ring-inner-color), inset 0 0 0 1px var(--gl-focus-ring-inner-color)', outline: 'none', }, '.text-align-inherit': { 'text-align': 'inherit', }, }); } const widthPercentageScales = [8, 10, 20].reduce((accumulator1, denominator) => { return { ...accumulator1, ...range(1, denominator).reduce((accumulator2, numerator) => { const width = (numerator / denominator) * 100; return { ...accumulator2, [`${numerator}/${denominator}`]: `${round(width, 6)}%`, }; }, {}), }; }, {}); /** @type {import('tailwindcss').Config} */ module.exports = { prefix: 'gl-', corePlugins: { /* * Disable preflight styles so that `@tailwind base` compiles to CSS vars declarations without * any of the resets which we don't need. * More on this at https://tailwindcss.com/docs/preflight. */ preflight: false, ringOffsetColor: false, ringOpacity: false, ringWidth: false, ringColor: false, ringOffsetWidth: false, }, plugins: [plugin(addCustomDefinitions)], theme: { animation: { spin: 'spin 0.6s infinite linear', }, backgroundColor, borderColor, borderRadius: { none: '0', 6: '1.5rem', base: '.25rem', full: '50%', // Tailwind gl-rounded-full is 9999px small: '.125rem', lg: '.5rem', pill: '.75rem', }, boxShadow: { DEFAULT: '0 1px 4px 0 #0000004d', none: 'none', sm: '0 0 2px var(--gl-shadow-color-default, #05050629), 0 1px 4px var(--gl-shadow-color-default, #05050629)', md: '0 0 1px var(--gl-shadow-color-default, #05050629), 0 0 2px var(--gl-shadow-color-default, #05050629), 0 2px 8px var(--gl-shadow-color-default, #05050629)', lg: '0 0 2px var(--gl-shadow-color-default, #05050629), 0 0 2px var(--gl-shadow-color-default, #05050629), 0 4px 12px var(--gl-shadow-color-default, #05050629)', 'inner-1-blue-500': 'inset 0 0 0 1px var(--blue-500, #1f75cb)', 'inner-1-gray-100': 'inset 0 0 0 1px var(--gray-100, #dcdcde)', 'inner-1-border-default': 'inset 0 0 0 1px var(--gl-border-color-default, var(--gl-color-neutral-100, #dcdcde))', 'inner-1-border-subtle': 'inset 0 0 0 1px var(--gl-border-color-subtle, var(--gl-color-neutral-50, #ececef))', 'inner-1-border-strong': 'inset 0 0 0 1px var(--gl-border-color-strong, var(--gl-color-neutral-200, #bfbfc3))', 'inner-1-gray-200': 'inset 0 0 0 1px var(--gray-200, #bfbfc3)', 'inner-1-gray-400': 'inset 0 0 0 1px var(--gray-400, #89888d)', 'inner-1-red-300': 'inset 0 0 0 1px var(--red-300, #f57f6c)', 'inner-1-red-400': 'inset 0 0 0 1px var(--red-400, #ec5941)', 'inner-1-red-500': 'inset 0 0 0 1px var(--red-500, #dd2b0e)', 'inner-2-blue-400': 'inset 0 0 0 2px var(--blue-400, #428fdc)', 'inner-b-1-gray-100': 'inset 0 -1px 0 0 var(--gray-100, #dcdcde)', 'inner-b-1-border-default': 'inset 0 -1px 0 0 var(--gl-border-color-default, var(--gl-color-neutral-100, #dcdcde))', 'inner-b-2-blue-500': 'inset 0 -2px 0 0 var(--blue-500, #1f75cb)', 'inner-b-2-theme-accent': 'inset 0 -2px 0 0 var(--gl-theme-accent, var(--theme-indigo-500, #6666c4))', 'inner-l-3-red-600': 'inset 3px 0 0 0 var(--red-600, #c91c00)', 'inner-l-4-gray-100': 'inset 4px 0 0 0 var(--gray-100, #dcdcde)', 'x0-y0-b3-s1-blue-500': 'inset 0 0 3px 1px var(--blue-500, #1f75cb)', 'x0-y2-b4-s0': '0 2px 4px 0 #0000001a', }, colors, fill, fontFamily: { regular: 'var(--default-regular-font, "GitLab Sans"), -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"', }, fontSize: { xs: '0.625rem', sm: '0.75rem', base: '0.875rem', lg: '1rem', 'size-h-display': '1.75rem', 'size-h1': '1.4375rem', 'size-h2': '1.1875rem', 'size-h1-xl': '2rem', 'size-h2-xl': '1.4375rem', 'size-reset': 'inherit', }, fontWeight: { 100: 100, 300: 300, normal: 400, semibold: 500, bold: 600, }, lineHeight: { reset: 'inherit', 0: '0', 1: '1', normal: '1rem', 20: '1.25rem', 24: '1.5rem', 28: '1.75rem', 32: '2rem', 36: '2.25rem', 42: '2.625rem', }, opacity: { 0: '0', 1: '.1', 2: '.2', 3: '.3', 4: '.4', 5: '.5', 6: '.6', 7: '.7', 8: '.8', 9: '.9', 10: '1', }, outlineColor, screens: { sm: '576px', md: '768px', lg: '992px', xl: '1200px', }, spacing, textColor, transitionDuration: { DEFAULT: '200ms', slow: '400ms', medium: '200ms', fast: '100ms', }, transitionTimingFunction: { DEFAULT: 'ease', ease: 'ease', linear: 'linear', }, zIndex: { 0: '0', 1: '1', 2: '2', 3: '3', 4: '4', 200: '200', 9999: '9999', }, extend: { borderWidth: { 1: '1px', }, flexGrow: { 2: '2', }, gridTemplateRows: { auto: 'auto', }, maxWidth: { ...widthPercentageScales, screen: '100vw', limited: '1006px', '1/2': '50%', }, transitionProperty: { 'box-shadow': 'box-shadow', 'border-color': 'border-color', 'stroke-opacity': 'stroke-opacity', background: 'background', left: 'left', opacity: 'opacity', padding: 'padding', right: 'right', stroke: 'stroke', transform: 'transform', width: 'width', }, width: widthPercentageScales, }, }, };