Build: split CSS/SCSS webpack rules + generate CSS custom properties - Split webpack css rule into separate .css and .scss rules so pure CSS files skip sass-loader (Phase 1) - Generate properties.css for dark/light/contrast themes with all pre-calculated color values as CSS custom properties (Phase 2) - Add extract-colors.js helper script for color value generation
6 files changed, 1071 insertions(+), 16 deletions(-) A app/javascript/flavours/glitch/styles/properties-contrast.css A app/javascript/flavours/glitch/styles/properties-light.css A app/javascript/flavours/glitch/styles/properties.css M config/webpack/rules/css.js M config/webpack/shared.js A scripts/extract-colors.js
A app/javascript/flavours/glitch/styles/properties-contrast.css => app/javascript/flavours/glitch/styles/properties-contrast.css +236 -0
@@ 0,0 1,236 @@ :root { --black: #000000; --white: #ffffff; --red-600: #b7253d; --red-500: #df405a; --blurple-600: #563acc; --blurple-500: #6364ff; --blurple-300: #858afa; --grey-600: #4e4c5a; --grey-100: #dadaf3; --success-green: #79bd9a; --error-red: #df405a; --warning-red: #ff5050; --gold-star: #ca8f04; --red-bookmark: #ff5050; --classic-base-color: #282c37; --classic-primary-color: #9baec8; --classic-secondary-color: #d9e1e8; --classic-highlight-color: #6364ff; --base-shadow-color: #000000; --base-overlay-background: #000000; --base-border-color: #ffffff; --simple-background-color: #ffffff; --valid-value-color: #79bd9a; --error-value-color: #df405a; --ui-base-color: #282c37; --ui-base-lighter-color: #606984; --ui-primary-color: #9baec8; --ui-secondary-color: #d9e1e8; --ui-highlight-color: #6364ff; --ui-button-color: #ffffff; --ui-button-background-color: #6364ff; --ui-button-focus-background-color: #563acc; --ui-button-secondary-color: #dadaf3; --ui-button-secondary-border-color: #dadaf3; --ui-button-secondary-focus-background-color: #4e4c5a; --ui-button-secondary-focus-color: #ffffff; --ui-button-tertiary-color: #858afa; --ui-button-tertiary-border-color: #858afa; --ui-button-tertiary-focus-background-color: #563acc; --ui-button-tertiary-focus-color: #ffffff; --ui-button-destructive-background-color: #df405a; --ui-button-destructive-focus-background-color: #b7253d; --primary-text-color: #ffffff; --darker-text-color: #dde3ec; --dark-text-color: #c2cede; --secondary-text-color: #ecf0f4; --highlight-text-color: #9697ff; --action-button-color: #a2a9bc; --action-button-focus-color: #687390; --passive-text-color: #ca8f04; --active-passive-text-color: #79bd9a; --inverted-text-color: #000000; --lighter-text-color: #1b1e25; --light-text-color: #364861; --action-button-color-lighten-7: #b7bccb; --action-button-color-lighten-13: #c9cdd8; --darker-text-color-lighten-4: #eaeef3; --darker-text-color-lighten-7: #f4f6f9; --darker-text-color-lighten-8: #f7f9fb; --darker-text-color-lighten-10: #fefefe; --dark-text-color-lighten-4: #d0d9e5; --dark-text-color-lighten-7: #dae1ea; --error-red-lighten-4: #e25169; --error-red-lighten-12: #e87487; --error-value-color-lighten-12: #e87487; --gold-star-lighten-6: #e8a405; --gold-star-lighten-16: #fbbb25; --highlight-text-color-lighten-4: #aaabff; --highlight-text-color-lighten-6: #b5b5ff; --highlight-text-color-lighten-8: #bfbfff; --highlight-text-color-lighten-13: #d8d9ff; --inverted-text-color-lighten-4: #0a0a0a; --inverted-text-color-lighten-10: #1a1a1a; --inverted-text-color-lighten-15: #262626; --inverted-text-color-lighten-16: #292929; --lighter-text-color-lighten-7: #2a2e3a; --lighter-text-color-lighten-20: #464d60; --secondary-text-color-lighten-4: #f9fafb; --secondary-text-color-lighten-7: #ffffff; --secondary-text-color-lighten-8: #ffffff; --ui-base-color-lighten-2: #2c313d; --ui-base-color-lighten-3: #2e3340; --ui-base-color-lighten-4: #313543; --ui-base-color-lighten-5: #333846; --ui-base-color-lighten-6: #353a49; --ui-base-color-lighten-8: #393f4f; --ui-base-color-lighten-11: #404657; --ui-base-color-lighten-12: #42485a; --ui-base-color-lighten-13: #444b5d; --ui-base-color-lighten-14: #464d60; --ui-base-color-lighten-16: #4a5266; --ui-base-color-lighten-20: #535b72; --ui-base-color-lighten-26: #606984; --ui-base-color-lighten-27: #626c87; --ui-base-color-lighten-29: #66718d; --ui-base-color-lighten-30: #687390; --ui-base-color-lighten-33: #707b97; --ui-base-color-lighten-34: #737d99; --ui-base-color-lighten-50: #a2a9bc; --ui-base-lighter-color-lighten-4: #687390; --ui-base-lighter-color-lighten-7: #707b97; --ui-highlight-color-lighten-4: #7778ff; --ui-highlight-color-lighten-8: #8c8dff; --ui-highlight-color-lighten-10: #9697ff; --ui-highlight-color-lighten-12: #a0a1ff; --ui-primary-color-lighten-8: #b5c3d6; --ui-primary-color-lighten-12: #c2cede; --ui-primary-color-lighten-20: #dde3ec; --ui-secondary-color-lighten-6: #ecf0f4; --ui-secondary-color-lighten-8: #f2f5f7; --valid-value-color-lighten-8: #94caaf; --valid-value-color-lighten-15: #acd6c1; --warning-red-lighten-12: #ff8d8d; --white-lighten-4: #ffffff; --white-lighten-7: #ffffff; --action-button-color-darken-13: #7c86a0; --darker-text-color-darken-13: #b2c1d5; --highlight-text-color-darken-4: #8282ff; --lighter-text-color-darken-4: #131419; --lighter-text-color-darken-7: #0c0d11; --simple-background-color-darken-2: #fafafa; --simple-background-color-darken-8: #ebebeb; --simple-background-color-darken-14: #dbdbdb; --simple-background-color-darken-24: #c2c2c2; --ui-base-color-darken-2: #242731; --ui-base-color-darken-4: #1f232b; --ui-base-color-darken-5: #1d2028; --ui-base-color-darken-6: #1b1e25; --ui-base-color-darken-7: #191b22; --ui-base-color-darken-8: #17191f; --ui-base-color-darken-10: #131419; --ui-base-color-darken-12: #0e1014; --ui-base-color-darken-13: #0c0d11; --ui-base-color-darken-14: #0a0b0e; --ui-base-color-darken-20: #000000; --ui-highlight-color-darken-2: #595aff; --ui-highlight-color-darken-3: #5455ff; --ui-highlight-color-darken-5: #4a4bff; --ui-highlight-color-darken-8: #3a3bff; --ui-primary-color-darken-5: #8ba1bf; --ui-primary-color-darken-14: #6d89af; --ui-primary-color-darken-40: #364861; --ui-secondary-color-darken-8: #c0cdd9; --ui-secondary-color-darken-10: #b9c8d5; --ui-secondary-color-darken-16: #a6b9c9; --ui-secondary-color-darken-18: #a0b4c5; --ui-secondary-color-darken-24: #8da5ba; --action-button-color-a15: #a2a9bc26; --action-button-color-a30: #a2a9bc4d; --base-overlay-background-a0: #00000000; --base-overlay-background-a10: #0000001a; --base-overlay-background-a30: #0000004d; --base-overlay-background-a50: #00000080; --base-overlay-background-a60: #00000099; --base-overlay-background-a70: #000000b3; --base-overlay-background-a80: #000000cc; --base-overlay-background-a90: #000000e6; --base-shadow-color-a10: #0000001a; --base-shadow-color-a20: #00000033; --base-shadow-color-a25: #00000040; --base-shadow-color-a30: #0000004d; --base-shadow-color-a35: #00000059; --base-shadow-color-a40: #00000066; --base-shadow-color-a45: #00000073; --base-shadow-color-a60: #00000099; --base-shadow-color-a65: #000000a6; --base-shadow-color-a75: #000000bf; --base-shadow-color-a80: #000000cc; --base-shadow-color-a85: #000000d9; --black-a45: #00000073; --black-a65: #000000a6; --black-a85: #000000d9; --black-a90: #000000e6; --darker-text-color-a15: #dde3ec26; --darker-text-color-a30: #dde3ec4d; --dark-text-color-a10: #c2cede1a; --error-red-a50: #df405a80; --error-value-color-a10: #df405a1a; --error-value-color-a50: #df405a80; --gold-star-a15: #ca8f0426; --gold-star-a25: #ca8f0440; --gold-star-a30: #ca8f044d; --gold-star-a50: #ca8f0480; --highlight-text-color-a15: #9697ff26; --highlight-text-color-a25: #9697ff40; --highlight-text-color-a30: #9697ff4d; --highlight-text-color-a40: #9697ff66; --lighter-text-color-a15: #1b1e2526; --lighter-text-color-a30: #1b1e254d; --primary-text-color-a70: #ffffffb3; --primary-text-color-a80: #ffffffcc; --success-green-a10: #79bd9a1a; --success-green-a50: #79bd9a80; --ui-base-color-a0: #282c3700; --ui-base-color-a15: #282c3726; --ui-base-color-a25: #282c3740; --ui-base-color-a30: #282c374d; --ui-base-color-a85: #282c37d9; --ui-base-color-a100: #282c37; --ui-base-lighter-color-a60: #60698499; --ui-highlight-color-a0: #6364ff00; --ui-highlight-color-a10: #6364ff1a; --ui-highlight-color-a15: #6364ff26; --ui-highlight-color-a23: #6364ff3b; --ui-highlight-color-a40: #6364ff66; --ui-highlight-color-a50: #6364ff80; --ui-secondary-color-a10: #d9e1e81a; --ui-secondary-color-a30: #d9e1e84d; --ui-secondary-color-a40: #d9e1e866; --ui-secondary-color-a50: #d9e1e880; --ui-secondary-color-a70: #d9e1e8b3; --valid-value-color-a25: #79bd9a40; --valid-value-color-a50: #79bd9a80; --warning-red-a15: #ff505026; --white-a15: #ffffff26; --white-a20: #ffffff33; --white-a30: #ffffff4d; --white-a35: #ffffff59; --white-a70: #ffffffb3; --white-a75: #ffffffbf; --white-a80: #ffffffcc; --mix-ui-base-highlight-95: #2b2f41; --mix-white-highlight-80: #e0e0ff; --mix-ui-base-lighten4-highlight-95: #33384c; --mix-ui-base-lighten8-highlight-95: #3b4157; --mix-ui-base-lighten12-highlight-80: #484e7b; --font-sans-serif: 'mastodon-font-sans-serif'; --font-display: 'mastodon-font-display'; --font-monospace: 'mastodon-font-monospace'; --no-gap-breakpoint: 1175px; --media-modal-media-max-width: 100%; --media-modal-media-max-height: 80%; --ui-avatar-border-size: 8%; --dismiss-overlay-width: 4rem; }
A app/javascript/flavours/glitch/styles/properties-light.css => app/javascript/flavours/glitch/styles/properties-light.css +236 -0
@@ 0,0 1,236 @@ :root { --black: #000000; --white: #ffffff; --red-600: #b7253d; --red-500: #df405a; --blurple-600: #563acc; --blurple-500: #6364ff; --blurple-300: #858afa; --grey-600: #4e4c5a; --grey-100: #dadaf3; --success-green: #4a905f; --error-red: #df405a; --warning-red: #ff5050; --gold-star: #ca8f04; --red-bookmark: #ff5050; --classic-base-color: #282c37; --classic-primary-color: #9baec8; --classic-secondary-color: #d9e1e8; --classic-highlight-color: #6364ff; --base-shadow-color: #000000; --base-overlay-background: #ffffff; --base-border-color: #ffffff; --simple-background-color: #ffffff; --valid-value-color: #4a905f; --error-value-color: #df405a; --ui-base-color: #d9e1e8; --ui-base-lighter-color: #b0c0cf; --ui-primary-color: #9bcbed; --ui-secondary-color: #282c37; --ui-highlight-color: #6364ff; --ui-button-color: #ffffff; --ui-button-background-color: #6364ff; --ui-button-focus-background-color: #563acc; --ui-button-secondary-color: #4e4c5a; --ui-button-secondary-border-color: #4e4c5a; --ui-button-secondary-focus-background-color: #4e4c5a; --ui-button-secondary-focus-color: #ffffff; --ui-button-tertiary-color: #6364ff; --ui-button-tertiary-border-color: #6364ff; --ui-button-tertiary-focus-background-color: #563acc; --ui-button-tertiary-focus-color: #ffffff; --ui-button-destructive-background-color: #df405a; --ui-button-destructive-focus-background-color: #b7253d; --primary-text-color: #000000; --darker-text-color: #282c37; --dark-text-color: #444b5d; --secondary-text-color: #282c37; --highlight-text-color: #3a3bff; --action-button-color: #606984; --action-button-focus-color: #a3b6c7; --passive-text-color: #ca8f04; --active-passive-text-color: #4a905f; --inverted-text-color: #000000; --lighter-text-color: #282c37; --light-text-color: #444b5d; --action-button-color-lighten-7: #51596f; --action-button-color-lighten-13: #444a5e; --darker-text-color-lighten-4: #1f232b; --darker-text-color-lighten-7: #191b22; --darker-text-color-lighten-8: #17191f; --darker-text-color-lighten-10: #131419; --dark-text-color-lighten-4: #3b4151; --dark-text-color-lighten-7: #353a48; --error-red-lighten-4: #dc2f4b; --error-red-lighten-12: #c1203b; --error-value-color-lighten-12: #c1203b; --gold-star-lighten-6: #ac7a03; --gold-star-lighten-16: #7a5602; --highlight-text-color-lighten-4: #2627ff; --highlight-text-color-lighten-6: #1c1dff; --highlight-text-color-lighten-8: #1113ff; --highlight-text-color-lighten-13: #0002f7; --inverted-text-color-lighten-4: #000000; --inverted-text-color-lighten-10: #000000; --inverted-text-color-lighten-15: #000000; --inverted-text-color-lighten-16: #000000; --lighter-text-color-lighten-7: #191b22; --lighter-text-color-lighten-20: #000000; --secondary-text-color-lighten-4: #1f232b; --secondary-text-color-lighten-7: #191b22; --secondary-text-color-lighten-8: #17191f; --ui-base-color-lighten-2: #d3dce4; --ui-base-color-lighten-3: #cfd9e2; --ui-base-color-lighten-4: #ccd7e0; --ui-base-color-lighten-5: #c9d4de; --ui-base-color-lighten-6: #c6d2dc; --ui-base-color-lighten-8: #c0cdd9; --ui-base-color-lighten-11: #b6c5d3; --ui-base-color-lighten-12: #b3c3d1; --ui-base-color-lighten-13: #b0c0cf; --ui-base-color-lighten-14: #adbecd; --ui-base-color-lighten-16: #a6b9c9; --ui-base-color-lighten-20: #99afc2; --ui-base-color-lighten-26: #86a0b6; --ui-base-color-lighten-27: #839db4; --ui-base-color-lighten-29: #7d98b0; --ui-base-color-lighten-30: #7a96ae; --ui-base-color-lighten-33: #708ea9; --ui-base-color-lighten-34: #6d8ca7; --ui-base-color-lighten-50: #496379; --ui-base-lighter-color-lighten-4: #a3b6c7; --ui-base-lighter-color-lighten-7: #9aaec2; --ui-highlight-color-lighten-4: #4f50ff; --ui-highlight-color-lighten-8: #3a3bff; --ui-highlight-color-lighten-10: #3031ff; --ui-highlight-color-lighten-12: #2627ff; --ui-primary-color-lighten-8: #78b9e7; --ui-primary-color-lighten-12: #67b0e4; --ui-primary-color-lighten-20: #459edd; --ui-secondary-color-lighten-6: #1b1e25; --ui-secondary-color-lighten-8: #17191f; --valid-value-color-lighten-8: #3c754d; --valid-value-color-lighten-15: #305d3d; --warning-red-lighten-12: #ff1313; --white-lighten-4: #f5f5f5; --white-lighten-7: #ededed; --action-button-color-darken-13: #828ba4; --darker-text-color-darken-13: #444b5d; --highlight-text-color-darken-4: #4f50ff; --lighter-text-color-darken-4: #313543; --lighter-text-color-darken-7: #373d4c; --simple-background-color-darken-2: #ffffff; --simple-background-color-darken-8: #ffffff; --simple-background-color-darken-14: #ffffff; --simple-background-color-darken-24: #ffffff; --ui-base-color-darken-2: #dfe6ec; --ui-base-color-darken-4: #e6ebf0; --ui-base-color-darken-5: #e9eef2; --ui-base-color-darken-6: #ecf0f4; --ui-base-color-darken-7: #eff3f5; --ui-base-color-darken-8: #f2f5f7; --ui-base-color-darken-10: #f9fafb; --ui-base-color-darken-12: #ffffff; --ui-base-color-darken-13: #ffffff; --ui-base-color-darken-14: #ffffff; --ui-base-color-darken-20: #ffffff; --ui-highlight-color-darken-2: #6d6eff; --ui-highlight-color-darken-3: #7273ff; --ui-highlight-color-darken-5: #7d7dff; --ui-highlight-color-darken-8: #8c8dff; --ui-primary-color-darken-5: #b1d6f1; --ui-primary-color-darken-14: #d8eaf8; --ui-primary-color-darken-40: #ffffff; --ui-secondary-color-darken-8: #393f4f; --ui-secondary-color-darken-10: #3d4455; --ui-secondary-color-darken-16: #4a5266; --ui-secondary-color-darken-18: #4f576c; --ui-secondary-color-darken-24: #5c657e; --action-button-color-a15: #60698426; --action-button-color-a30: #6069844d; --base-overlay-background-a0: #ffffff00; --base-overlay-background-a10: #ffffff1a; --base-overlay-background-a30: #ffffff4d; --base-overlay-background-a50: #ffffff80; --base-overlay-background-a60: #ffffff99; --base-overlay-background-a70: #ffffffb3; --base-overlay-background-a80: #ffffffcc; --base-overlay-background-a90: #ffffffe6; --base-shadow-color-a10: #0000001a; --base-shadow-color-a20: #00000033; --base-shadow-color-a25: #00000040; --base-shadow-color-a30: #0000004d; --base-shadow-color-a35: #00000059; --base-shadow-color-a40: #00000066; --base-shadow-color-a45: #00000073; --base-shadow-color-a60: #00000099; --base-shadow-color-a65: #000000a6; --base-shadow-color-a75: #000000bf; --base-shadow-color-a80: #000000cc; --base-shadow-color-a85: #000000d9; --black-a45: #00000073; --black-a65: #000000a6; --black-a85: #000000d9; --black-a90: #000000e6; --darker-text-color-a15: #282c3726; --darker-text-color-a30: #282c374d; --dark-text-color-a10: #444b5d1a; --error-red-a50: #df405a80; --error-value-color-a10: #df405a1a; --error-value-color-a50: #df405a80; --gold-star-a15: #ca8f0426; --gold-star-a25: #ca8f0440; --gold-star-a30: #ca8f044d; --gold-star-a50: #ca8f0480; --highlight-text-color-a15: #3a3bff26; --highlight-text-color-a25: #3a3bff40; --highlight-text-color-a30: #3a3bff4d; --highlight-text-color-a40: #3a3bff66; --lighter-text-color-a15: #282c3726; --lighter-text-color-a30: #282c374d; --primary-text-color-a70: #000000b3; --primary-text-color-a80: #000000cc; --success-green-a10: #4a905f1a; --success-green-a50: #4a905f80; --ui-base-color-a0: #d9e1e800; --ui-base-color-a15: #d9e1e826; --ui-base-color-a25: #d9e1e840; --ui-base-color-a30: #d9e1e84d; --ui-base-color-a85: #d9e1e8d9; --ui-base-color-a100: #d9e1e8; --ui-base-lighter-color-a60: #b0c0cf99; --ui-highlight-color-a0: #6364ff00; --ui-highlight-color-a10: #6364ff1a; --ui-highlight-color-a15: #6364ff26; --ui-highlight-color-a23: #6364ff3b; --ui-highlight-color-a40: #6364ff66; --ui-highlight-color-a50: #6364ff80; --ui-secondary-color-a10: #282c371a; --ui-secondary-color-a30: #282c374d; --ui-secondary-color-a40: #282c3766; --ui-secondary-color-a50: #282c3780; --ui-secondary-color-a70: #282c37b3; --valid-value-color-a25: #4a905f40; --valid-value-color-a50: #4a905f80; --warning-red-a15: #ff505026; --white-a15: #ffffff26; --white-a20: #ffffff33; --white-a30: #ffffff4d; --white-a35: #ffffff59; --white-a70: #ffffffb3; --white-a75: #ffffffbf; --white-a80: #ffffffcc; --mix-ui-base-highlight-95: #d3dbe9; --mix-white-highlight-80: #e0e0ff; --mix-ui-base-lighten4-highlight-95: #c7d1e2; --mix-ui-base-lighten8-highlight-95: #bbc8db; --mix-ui-base-lighten12-highlight-80: #a3b0da; --font-sans-serif: 'mastodon-font-sans-serif'; --font-display: 'mastodon-font-display'; --font-monospace: 'mastodon-font-monospace'; --no-gap-breakpoint: 1175px; --media-modal-media-max-width: 100%; --media-modal-media-max-height: 80%; --ui-avatar-border-size: 8%; --dismiss-overlay-width: 4rem; }
A app/javascript/flavours/glitch/styles/properties.css => app/javascript/flavours/glitch/styles/properties.css +236 -0
@@ 0,0 1,236 @@ :root { --black: #000000; --white: #ffffff; --red-600: #b7253d; --red-500: #df405a; --blurple-600: #563acc; --blurple-500: #6364ff; --blurple-300: #858afa; --grey-600: #4e4c5a; --grey-100: #dadaf3; --success-green: #79bd9a; --error-red: #df405a; --warning-red: #ff5050; --gold-star: #ca8f04; --red-bookmark: #ff5050; --classic-base-color: #282c37; --classic-primary-color: #9baec8; --classic-secondary-color: #d9e1e8; --classic-highlight-color: #6364ff; --base-shadow-color: #000000; --base-overlay-background: #000000; --base-border-color: #ffffff; --simple-background-color: #ffffff; --valid-value-color: #79bd9a; --error-value-color: #df405a; --ui-base-color: #282c37; --ui-base-lighter-color: #606984; --ui-primary-color: #9baec8; --ui-secondary-color: #d9e1e8; --ui-highlight-color: #6364ff; --ui-button-color: #ffffff; --ui-button-background-color: #6364ff; --ui-button-focus-background-color: #563acc; --ui-button-secondary-color: #dadaf3; --ui-button-secondary-border-color: #dadaf3; --ui-button-secondary-focus-background-color: #4e4c5a; --ui-button-secondary-focus-color: #ffffff; --ui-button-tertiary-color: #858afa; --ui-button-tertiary-border-color: #858afa; --ui-button-tertiary-focus-background-color: #563acc; --ui-button-tertiary-focus-color: #ffffff; --ui-button-destructive-background-color: #df405a; --ui-button-destructive-focus-background-color: #b7253d; --primary-text-color: #ffffff; --darker-text-color: #9baec8; --dark-text-color: #606984; --secondary-text-color: #d9e1e8; --highlight-text-color: #8c8dff; --action-button-color: #606984; --action-button-focus-color: #687390; --passive-text-color: #ca8f04; --active-passive-text-color: #79bd9a; --inverted-text-color: #282c37; --lighter-text-color: #606984; --light-text-color: #9baec8; --action-button-color-lighten-7: #707b97; --action-button-color-lighten-13: #828ba4; --darker-text-color-lighten-4: #a8b9cf; --darker-text-color-lighten-7: #b2c1d5; --darker-text-color-lighten-8: #b5c3d6; --darker-text-color-lighten-10: #bcc9da; --dark-text-color-lighten-4: #687390; --dark-text-color-lighten-7: #707b97; --error-red-lighten-4: #e25169; --error-red-lighten-12: #e87487; --error-value-color-lighten-12: #e87487; --gold-star-lighten-6: #e8a405; --gold-star-lighten-16: #fbbb25; --highlight-text-color-lighten-4: #a0a1ff; --highlight-text-color-lighten-6: #aaabff; --highlight-text-color-lighten-8: #b5b5ff; --highlight-text-color-lighten-13: #ceceff; --inverted-text-color-lighten-4: #313543; --inverted-text-color-lighten-10: #3d4455; --inverted-text-color-lighten-15: #484f63; --inverted-text-color-lighten-16: #4a5266; --lighter-text-color-lighten-7: #707b97; --lighter-text-color-lighten-20: #979eb3; --secondary-text-color-lighten-4: #e6ebf0; --secondary-text-color-lighten-7: #eff3f5; --secondary-text-color-lighten-8: #f2f5f7; --ui-base-color-lighten-2: #2c313d; --ui-base-color-lighten-3: #2e3340; --ui-base-color-lighten-4: #313543; --ui-base-color-lighten-5: #333846; --ui-base-color-lighten-6: #353a49; --ui-base-color-lighten-8: #393f4f; --ui-base-color-lighten-11: #404657; --ui-base-color-lighten-12: #42485a; --ui-base-color-lighten-13: #444b5d; --ui-base-color-lighten-14: #464d60; --ui-base-color-lighten-16: #4a5266; --ui-base-color-lighten-20: #535b72; --ui-base-color-lighten-26: #606984; --ui-base-color-lighten-27: #626c87; --ui-base-color-lighten-29: #66718d; --ui-base-color-lighten-30: #687390; --ui-base-color-lighten-33: #707b97; --ui-base-color-lighten-34: #737d99; --ui-base-color-lighten-50: #a2a9bc; --ui-base-lighter-color-lighten-4: #687390; --ui-base-lighter-color-lighten-7: #707b97; --ui-highlight-color-lighten-4: #7778ff; --ui-highlight-color-lighten-8: #8c8dff; --ui-highlight-color-lighten-10: #9697ff; --ui-highlight-color-lighten-12: #a0a1ff; --ui-primary-color-lighten-8: #b5c3d6; --ui-primary-color-lighten-12: #c2cede; --ui-primary-color-lighten-20: #dde3ec; --ui-secondary-color-lighten-6: #ecf0f4; --ui-secondary-color-lighten-8: #f2f5f7; --valid-value-color-lighten-8: #94caaf; --valid-value-color-lighten-15: #acd6c1; --warning-red-lighten-12: #ff8d8d; --white-lighten-4: #ffffff; --white-lighten-7: #ffffff; --action-button-color-darken-13: #444b5d; --darker-text-color-darken-13: #708bb0; --highlight-text-color-darken-4: #7778ff; --lighter-text-color-darken-4: #576078; --lighter-text-color-darken-7: #51596f; --simple-background-color-darken-2: #fafafa; --simple-background-color-darken-8: #ebebeb; --simple-background-color-darken-14: #dbdbdb; --simple-background-color-darken-24: #c2c2c2; --ui-base-color-darken-2: #242731; --ui-base-color-darken-4: #1f232b; --ui-base-color-darken-5: #1d2028; --ui-base-color-darken-6: #1b1e25; --ui-base-color-darken-7: #191b22; --ui-base-color-darken-8: #17191f; --ui-base-color-darken-10: #131419; --ui-base-color-darken-12: #0e1014; --ui-base-color-darken-13: #0c0d11; --ui-base-color-darken-14: #0a0b0e; --ui-base-color-darken-20: #000000; --ui-highlight-color-darken-2: #595aff; --ui-highlight-color-darken-3: #5455ff; --ui-highlight-color-darken-5: #4a4bff; --ui-highlight-color-darken-8: #3a3bff; --ui-primary-color-darken-5: #8ba1bf; --ui-primary-color-darken-14: #6d89af; --ui-primary-color-darken-40: #364861; --ui-secondary-color-darken-8: #c0cdd9; --ui-secondary-color-darken-10: #b9c8d5; --ui-secondary-color-darken-16: #a6b9c9; --ui-secondary-color-darken-18: #a0b4c5; --ui-secondary-color-darken-24: #8da5ba; --action-button-color-a15: #60698426; --action-button-color-a30: #6069844d; --base-overlay-background-a0: #00000000; --base-overlay-background-a10: #0000001a; --base-overlay-background-a30: #0000004d; --base-overlay-background-a50: #00000080; --base-overlay-background-a60: #00000099; --base-overlay-background-a70: #000000b3; --base-overlay-background-a80: #000000cc; --base-overlay-background-a90: #000000e6; --base-shadow-color-a10: #0000001a; --base-shadow-color-a20: #00000033; --base-shadow-color-a25: #00000040; --base-shadow-color-a30: #0000004d; --base-shadow-color-a35: #00000059; --base-shadow-color-a40: #00000066; --base-shadow-color-a45: #00000073; --base-shadow-color-a60: #00000099; --base-shadow-color-a65: #000000a6; --base-shadow-color-a75: #000000bf; --base-shadow-color-a80: #000000cc; --base-shadow-color-a85: #000000d9; --black-a45: #00000073; --black-a65: #000000a6; --black-a85: #000000d9; --black-a90: #000000e6; --darker-text-color-a15: #9baec826; --darker-text-color-a30: #9baec84d; --dark-text-color-a10: #6069841a; --error-red-a50: #df405a80; --error-value-color-a10: #df405a1a; --error-value-color-a50: #df405a80; --gold-star-a15: #ca8f0426; --gold-star-a25: #ca8f0440; --gold-star-a30: #ca8f044d; --gold-star-a50: #ca8f0480; --highlight-text-color-a15: #8c8dff26; --highlight-text-color-a25: #8c8dff40; --highlight-text-color-a30: #8c8dff4d; --highlight-text-color-a40: #8c8dff66; --lighter-text-color-a15: #60698426; --lighter-text-color-a30: #6069844d; --primary-text-color-a70: #ffffffb3; --primary-text-color-a80: #ffffffcc; --success-green-a10: #79bd9a1a; --success-green-a50: #79bd9a80; --ui-base-color-a0: #282c3700; --ui-base-color-a15: #282c3726; --ui-base-color-a25: #282c3740; --ui-base-color-a30: #282c374d; --ui-base-color-a85: #282c37d9; --ui-base-color-a100: #282c37; --ui-base-lighter-color-a60: #60698499; --ui-highlight-color-a0: #6364ff00; --ui-highlight-color-a10: #6364ff1a; --ui-highlight-color-a15: #6364ff26; --ui-highlight-color-a23: #6364ff3b; --ui-highlight-color-a40: #6364ff66; --ui-highlight-color-a50: #6364ff80; --ui-secondary-color-a10: #d9e1e81a; --ui-secondary-color-a30: #d9e1e84d; --ui-secondary-color-a40: #d9e1e866; --ui-secondary-color-a50: #d9e1e880; --ui-secondary-color-a70: #d9e1e8b3; --valid-value-color-a25: #79bd9a40; --valid-value-color-a50: #79bd9a80; --warning-red-a15: #ff505026; --white-a15: #ffffff26; --white-a20: #ffffff33; --white-a30: #ffffff4d; --white-a35: #ffffff59; --white-a70: #ffffffb3; --white-a75: #ffffffbf; --white-a80: #ffffffcc; --mix-ui-base-highlight-95: #2b2f41; --mix-white-highlight-80: #e0e0ff; --mix-ui-base-lighten4-highlight-95: #33384c; --mix-ui-base-lighten8-highlight-95: #3b4157; --mix-ui-base-lighten12-highlight-80: #484e7b; --font-sans-serif: 'mastodon-font-sans-serif'; --font-display: 'mastodon-font-display'; --font-monospace: 'mastodon-font-monospace'; --no-gap-breakpoint: 1175px; --media-modal-media-max-width: 100%; --media-modal-media-max-height: 80%; --ui-avatar-border-size: 8%; --dismiss-overlay-width: 4rem; }
M config/webpack/rules/css.js => config/webpack/rules/css.js +28 -15
@@ 1,22 1,33 @@ const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { test: /\.s?css$/i, use: [ MiniCssExtractPlugin.loader, { loader: "css-loader", options: { sourceMap: true, importLoaders: 2, }, const cssLoaders = [ MiniCssExtractPlugin.loader, { loader: "css-loader", options: { sourceMap: true, importLoaders: 2, }, { loader: "postcss-loader", options: { sourceMap: true, }, }, { loader: "postcss-loader", options: { sourceMap: true, }, }, ]; // Pure CSS files: skip sass-loader const cssRule = { test: /\.css$/i, use: cssLoaders, }; // SCSS files: include sass-loader const scssRule = { test: /\.scss$/i, use: [ ...cssLoaders, { loader: "sass-loader", options: { @@ 29,3 40,5 @@ module.exports = { }, ], }; module.exports = [cssRule, scssRule];
M config/webpack/shared.js => config/webpack/shared.js +1 -1
@@ 100,7 100,7 @@ module.exports = { }, module: { rules: Object.keys(rules).map(key => rules[key]), rules: Object.keys(rules).flatMap(key => rules[key]), strictExportPresence: true, },
A scripts/extract-colors.js => scripts/extract-colors.js +334 -0
@@ 0,0 1,334 @@ #!/usr/bin/env node /** * Extract all SCSS variable values and derived colors for each theme. * Outputs JSON with pre-calculated hex values for CSS custom properties. */ const sass = require("sass"); const path = require("path"); const stylesDir = path.resolve(__dirname, "../app/javascript/flavours/glitch/styles"); // All SCSS variables we need to extract const baseVars = [ "black", "white", "red-600", "red-500", "blurple-600", "blurple-500", "blurple-300", "grey-600", "grey-100", "success-green", "error-red", "warning-red", "gold-star", "red-bookmark", "classic-base-color", "classic-primary-color", "classic-secondary-color", "classic-highlight-color", "base-shadow-color", "base-overlay-background", "base-border-color", "simple-background-color", "valid-value-color", "error-value-color", "ui-base-color", "ui-base-lighter-color", "ui-primary-color", "ui-secondary-color", "ui-highlight-color", "ui-button-color", "ui-button-background-color", "ui-button-focus-background-color", "ui-button-secondary-color", "ui-button-secondary-border-color", "ui-button-secondary-focus-background-color", "ui-button-secondary-focus-color", "ui-button-tertiary-color", "ui-button-tertiary-border-color", "ui-button-tertiary-focus-background-color", "ui-button-tertiary-focus-color", "ui-button-destructive-background-color", "ui-button-destructive-focus-background-color", "primary-text-color", "darker-text-color", "dark-text-color", "secondary-text-color", "highlight-text-color", "action-button-color", "action-button-focus-color", "passive-text-color", "active-passive-text-color", "inverted-text-color", "lighter-text-color", "light-text-color", ]; // Derived colors: [variable, function, amount] // ALL unique lighten/darken/rgba calls found across the SCSS codebase const derivedColors = [ // === lighten calls (61 unique) === // action-button-color ["action-button-color", "lighten", 7], ["action-button-color", "lighten", 13], // darker-text-color ["darker-text-color", "lighten", 4], ["darker-text-color", "lighten", 7], ["darker-text-color", "lighten", 8], ["darker-text-color", "lighten", 10], // dark-text-color ["dark-text-color", "lighten", 4], ["dark-text-color", "lighten", 7], // error-red ["error-red", "lighten", 4], ["error-red", "lighten", 12], // error-value-color ["error-value-color", "lighten", 12], // gold-star ["gold-star", "lighten", 6], ["gold-star", "lighten", 16], // highlight-text-color ["highlight-text-color", "lighten", 4], ["highlight-text-color", "lighten", 6], ["highlight-text-color", "lighten", 8], ["highlight-text-color", "lighten", 13], // inverted-text-color ["inverted-text-color", "lighten", 4], ["inverted-text-color", "lighten", 10], ["inverted-text-color", "lighten", 15], ["inverted-text-color", "lighten", 16], // lighter-text-color ["lighter-text-color", "lighten", 7], ["lighter-text-color", "lighten", 20], // secondary-text-color ["secondary-text-color", "lighten", 4], ["secondary-text-color", "lighten", 7], ["secondary-text-color", "lighten", 8], // ui-base-color ["ui-base-color", "lighten", 2], ["ui-base-color", "lighten", 3], ["ui-base-color", "lighten", 4], ["ui-base-color", "lighten", 5], ["ui-base-color", "lighten", 6], ["ui-base-color", "lighten", 8], ["ui-base-color", "lighten", 11], ["ui-base-color", "lighten", 12], ["ui-base-color", "lighten", 13], ["ui-base-color", "lighten", 14], ["ui-base-color", "lighten", 16], ["ui-base-color", "lighten", 20], ["ui-base-color", "lighten", 26], ["ui-base-color", "lighten", 27], ["ui-base-color", "lighten", 29], ["ui-base-color", "lighten", 30], ["ui-base-color", "lighten", 33], ["ui-base-color", "lighten", 34], ["ui-base-color", "lighten", 50], // ui-base-lighter-color ["ui-base-lighter-color", "lighten", 4], ["ui-base-lighter-color", "lighten", 7], // ui-highlight-color ["ui-highlight-color", "lighten", 4], ["ui-highlight-color", "lighten", 8], ["ui-highlight-color", "lighten", 10], ["ui-highlight-color", "lighten", 12], // ui-primary-color ["ui-primary-color", "lighten", 8], ["ui-primary-color", "lighten", 12], ["ui-primary-color", "lighten", 20], // ui-secondary-color ["ui-secondary-color", "lighten", 6], ["ui-secondary-color", "lighten", 8], // valid-value-color ["valid-value-color", "lighten", 8], ["valid-value-color", "lighten", 15], // warning-red ["warning-red", "lighten", 12], // white ["white", "lighten", 4], ["white", "lighten", 7], // === darken calls (33 unique) === // action-button-color ["action-button-color", "darken", 13], // darker-text-color ["darker-text-color", "darken", 13], // highlight-text-color ["highlight-text-color", "darken", 4], // lighter-text-color ["lighter-text-color", "darken", 4], ["lighter-text-color", "darken", 7], // simple-background-color ["simple-background-color", "darken", 2], ["simple-background-color", "darken", 8], ["simple-background-color", "darken", 14], ["simple-background-color", "darken", 24], // ui-base-color ["ui-base-color", "darken", 2], ["ui-base-color", "darken", 4], ["ui-base-color", "darken", 5], ["ui-base-color", "darken", 6], ["ui-base-color", "darken", 7], ["ui-base-color", "darken", 8], ["ui-base-color", "darken", 10], ["ui-base-color", "darken", 12], ["ui-base-color", "darken", 13], ["ui-base-color", "darken", 14], ["ui-base-color", "darken", 20], // ui-highlight-color ["ui-highlight-color", "darken", 2], ["ui-highlight-color", "darken", 3], ["ui-highlight-color", "darken", 5], ["ui-highlight-color", "darken", 8], // ui-primary-color ["ui-primary-color", "darken", 5], ["ui-primary-color", "darken", 14], ["ui-primary-color", "darken", 40], // ui-secondary-color ["ui-secondary-color", "darken", 8], ["ui-secondary-color", "darken", 10], ["ui-secondary-color", "darken", 16], ["ui-secondary-color", "darken", 18], ["ui-secondary-color", "darken", 24], // === rgba calls (74 unique) === // action-button-color ["action-button-color", "rgba", 0.15], ["action-button-color", "rgba", 0.3], // base-overlay-background ["base-overlay-background", "rgba", 0], ["base-overlay-background", "rgba", 0.1], ["base-overlay-background", "rgba", 0.3], ["base-overlay-background", "rgba", 0.5], ["base-overlay-background", "rgba", 0.6], ["base-overlay-background", "rgba", 0.7], ["base-overlay-background", "rgba", 0.8], ["base-overlay-background", "rgba", 0.9], // base-shadow-color ["base-shadow-color", "rgba", 0.1], ["base-shadow-color", "rgba", 0.2], ["base-shadow-color", "rgba", 0.25], ["base-shadow-color", "rgba", 0.3], ["base-shadow-color", "rgba", 0.35], ["base-shadow-color", "rgba", 0.4], ["base-shadow-color", "rgba", 0.45], ["base-shadow-color", "rgba", 0.6], ["base-shadow-color", "rgba", 0.65], ["base-shadow-color", "rgba", 0.75], ["base-shadow-color", "rgba", 0.8], ["base-shadow-color", "rgba", 0.85], // black ["black", "rgba", 0.45], ["black", "rgba", 0.65], ["black", "rgba", 0.85], ["black", "rgba", 0.9], // darker-text-color ["darker-text-color", "rgba", 0.15], ["darker-text-color", "rgba", 0.3], // dark-text-color ["dark-text-color", "rgba", 0.1], // error-red ["error-red", "rgba", 0.5], // error-value-color ["error-value-color", "rgba", 0.1], ["error-value-color", "rgba", 0.5], // gold-star ["gold-star", "rgba", 0.15], ["gold-star", "rgba", 0.25], ["gold-star", "rgba", 0.3], ["gold-star", "rgba", 0.5], // highlight-text-color ["highlight-text-color", "rgba", 0.15], ["highlight-text-color", "rgba", 0.25], ["highlight-text-color", "rgba", 0.3], ["highlight-text-color", "rgba", 0.4], // lighter-text-color ["lighter-text-color", "rgba", 0.15], ["lighter-text-color", "rgba", 0.3], // primary-text-color ["primary-text-color", "rgba", 0.7], ["primary-text-color", "rgba", 0.8], // success-green ["success-green", "rgba", 0.1], ["success-green", "rgba", 0.5], // ui-base-color ["ui-base-color", "rgba", 0], ["ui-base-color", "rgba", 0.15], ["ui-base-color", "rgba", 0.25], ["ui-base-color", "rgba", 0.3], ["ui-base-color", "rgba", 0.85], ["ui-base-color", "rgba", 1], // ui-base-lighter-color ["ui-base-lighter-color", "rgba", 0.6], // ui-highlight-color ["ui-highlight-color", "rgba", 0], ["ui-highlight-color", "rgba", 0.1], ["ui-highlight-color", "rgba", 0.15], ["ui-highlight-color", "rgba", 0.23], ["ui-highlight-color", "rgba", 0.4], ["ui-highlight-color", "rgba", 0.5], // ui-secondary-color ["ui-secondary-color", "rgba", 0.1], ["ui-secondary-color", "rgba", 0.3], ["ui-secondary-color", "rgba", 0.4], ["ui-secondary-color", "rgba", 0.5], ["ui-secondary-color", "rgba", 0.7], // valid-value-color ["valid-value-color", "rgba", 0.25], ["valid-value-color", "rgba", 0.5], // warning-red ["warning-red", "rgba", 0.15], // white ["white", "rgba", 0.15], ["white", "rgba", 0.2], ["white", "rgba", 0.3], ["white", "rgba", 0.35], ["white", "rgba", 0.7], ["white", "rgba", 0.75], ["white", "rgba", 0.8], ]; // Mix calls: [name, scssExpression] const mixColors = [ ["mix-ui-base-highlight-95", "mix($ui-base-color, $ui-highlight-color, 95%)"], ["mix-white-highlight-80", "mix($white, $ui-highlight-color, 80%)"], ["mix-ui-base-lighten4-highlight-95", "mix(lighten($ui-base-color, 4%), $ui-highlight-color, 95%)"], ["mix-ui-base-lighten8-highlight-95", "mix(lighten($ui-base-color, 8%), $ui-highlight-color, 95%)"], ["mix-ui-base-lighten12-highlight-80", "mix(lighten($ui-base-color, 12%), $ui-highlight-color, 80%)"], ]; function generateScss(themeImport) { let scss = ""; if (themeImport) { scss += `@import '${themeImport}';\n`; } scss += `@import 'variables';\n\n`; // Output base variables scss += `:root {\n`; for (const v of baseVars) { scss += ` --extract-${v}: #{$${v}};\n`; } // Output derived colors for (const [varName, fn, amount] of derivedColors) { if (fn === "lighten") { scss += ` --extract-${varName}-lighten-${amount}: #{lighten($${varName}, ${amount}%)};\n`; } else if (fn === "darken") { scss += ` --extract-${varName}-darken-${amount}: #{darken($${varName}, ${amount}%)};\n`; } else if (fn === "rgba") { scss += ` --extract-${varName}-a${Math.round(amount * 100)}: #{rgba($${varName}, ${amount})};\n`; } } // Output mix colors for (const [name, expr] of mixColors) { scss += ` --extract-${name}: #{${expr}};\n`; } scss += `}\n`; return scss; } function extractValues(css) { const values = {}; const regex = /--extract-([\w-]+):\s*([^;]+);/g; let match; while ((match = regex.exec(css)) !== null) { values[match[1]] = match[2].trim(); } return values; } const themes = { dark: null, light: "mastodon-light/variables", contrast: "contrast/variables", }; const results = {}; for (const [name, themeImport] of Object.entries(themes)) { const scss = generateScss(themeImport); try { const result = sass.compileString(scss, { loadPaths: [stylesDir, path.resolve(__dirname, "../app/javascript")], }); results[name] = extractValues(result.css); } catch (err) { console.error(`Error compiling ${name} theme:`, err.message); results[name] = { error: err.message }; } } console.log(JSON.stringify(results, null, 2));