diff --git a/.changeset/eleven-news-report.md b/.changeset/eleven-news-report.md new file mode 100644 index 0000000000..505b8284b5 --- /dev/null +++ b/.changeset/eleven-news-report.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/fuselage-tokens": minor +"@rocket.chat/fuselage": minor +--- + +feat(fuselage): new `PaletteStyleTag` component diff --git a/packages/fuselage-tokens/build.js b/packages/fuselage-tokens/build.js index 8206957cef..8afbe0204a 100644 --- a/packages/fuselage-tokens/build.js +++ b/packages/fuselage-tokens/build.js @@ -118,11 +118,15 @@ StyleDictionary.registerFormat({ const exp = /[a-z]+\/([a-z]+)\/[a-z]+.json/i; const [, group] = dictionary.allTokens[0].filePath.match(exp); const newPaletteGroup = [ + 'badge', 'background', 'surface', 'stroke', + 'shadow', 'button', - 'text', + 'font', + 'status', + 'statusBullet', ]; if (newPaletteGroup.includes(group)) { diff --git a/packages/fuselage-tokens/config.js b/packages/fuselage-tokens/config.js index 788d934010..009c25eecd 100644 --- a/packages/fuselage-tokens/config.js +++ b/packages/fuselage-tokens/config.js @@ -23,7 +23,9 @@ module.exports = { tokenCategory === 'breakpoints' || tokenCategory === 'colors' ? customFormat : 'json/nested', - filter: (token) => token.filePath.includes(tokenCategory), + filter: (token) => + // console.log(token.filePath.includes(tokenCategory), tokenCategory); + token.filePath.includes(tokenCategory), }; }), }, diff --git a/packages/fuselage-tokens/src/badge/base.json b/packages/fuselage-tokens/src/badge/base.json new file mode 100644 index 0000000000..c00c8990e8 --- /dev/null +++ b/packages/fuselage-tokens/src/badge/base.json @@ -0,0 +1,25 @@ +{ + "badge": { + "light": { + "level-0": { "value": "{colors.n400}" }, + "level-1": { "value": "{colors.n700}" }, + "level-2": { "value": "{colors.b500}" }, + "level-3": { "value": "{colors.o500}" }, + "level-4": { "value": "{colors.r500}" } + }, + "high-contrast": { + "level-0": { "value": "{colors.n400}" }, + "level-1": { "value": "{colors.n800}" }, + "level-2": { "value": "{colors.b700}" }, + "level-3": { "value": "{colors.o900}" }, + "level-4": { "value": "{colors.r800}" } + }, + "dark": { + "level-0": { "value": "#404754" }, + "level-1": { "value": "#484C51" }, + "level-2": { "value": "#2C65BA" }, + "level-3": { "value": "#955828" }, + "level-4": { "value": "#B43C4C" } + } + } +} diff --git a/packages/fuselage-tokens/src/button/base.json b/packages/fuselage-tokens/src/button/base.json index 52b662c513..fd1e2c66fa 100644 --- a/packages/fuselage-tokens/src/button/base.json +++ b/packages/fuselage-tokens/src/button/base.json @@ -1,77 +1,142 @@ { "button": { - "backgroundPrimaryDefault": { "value": "{colors.b500}" }, - "backgroundPrimaryHover": { "value": "{colors.b600}" }, - "backgroundPrimaryPress": { "value": "{colors.b700}" }, - "backgroundPrimaryFocus": { "value": "{colors.b500}" }, - "backgroundPrimaryKeyfocus": { "value": "{colors.b500}" }, - "backgroundPrimaryDisabled": { "value": "{colors.b200}" }, - "fontOnPrimary": { "value": "{colors.white}" }, - "fontOnPrimaryDisabled": { "value": "{colors.white}" }, + "light": { + "backgroundPrimaryDefault": { "value": "{colors.b500}" }, + "backgroundPrimaryHover": { "value": "{colors.b600}" }, + "backgroundPrimaryPress": { "value": "{colors.b700}" }, + "backgroundPrimaryFocus": { "value": "{colors.b500}" }, + "backgroundPrimaryKeyfocus": { "value": "{colors.b500}" }, + "backgroundPrimaryDisabled": { "value": "{colors.b200}" }, + "fontOnPrimary": { "value": "{colors.white}" }, + "fontOnPrimaryDisabled": { "value": "{colors.white}" }, - "backgroundSecondaryDefault": { "value": "{colors.n400}" }, - "backgroundSecondaryHover": { "value": "{colors.n500}" }, - "backgroundSecondaryPress": { "value": "{colors.n600}" }, - "backgroundSecondaryFocus": { "value": "{colors.n400}" }, - "backgroundSecondaryKeyfocus": { "value": "{colors.n400}" }, - "backgroundSecondaryDisabled": { "value": "{colors.n300}" }, - "fontOnSecondary": { "value": "{colors.n900}" }, - "fontOnSecondaryDisabled": { "value": "{colors.n500}" }, + "backgroundSecondaryDefault": { "value": "{colors.n400}" }, + "backgroundSecondaryHover": { "value": "{colors.n500}" }, + "backgroundSecondaryPress": { "value": "{colors.n600}" }, + "backgroundSecondaryFocus": { "value": "{colors.n400}" }, + "backgroundSecondaryKeyfocus": { "value": "{colors.n400}" }, + "backgroundSecondaryDisabled": { "value": "{colors.n300}" }, + "fontOnSecondary": { "value": "{colors.n900}" }, + "fontOnSecondaryDisabled": { "value": "{colors.n500}" }, - "backgroundSecondaryDangerDefault": { "value": "{colors.n400}" }, - "backgroundSecondaryDangerHover": { "value": "{colors.n500}" }, - "backgroundSecondaryDangerPress": { "value": "{colors.n600}" }, - "backgroundSecondaryDangerFocus": { "value": "{colors.n400}" }, - "backgroundSecondaryDangerKeyfocus": { "value": "{colors.n400}" }, - "backgroundSecondaryDangerDisabled": { "value": "{colors.n300}" }, - "fontOnSecondaryDanger": { "value": "{colors.r700}" }, - "onSecondaryDangerDisabled": { "value": "{colors.r300}" }, + "backgroundSecondaryDangerDefault": { "value": "{colors.n400}" }, + "backgroundSecondaryDangerHover": { "value": "{colors.n500}" }, + "backgroundSecondaryDangerPress": { "value": "{colors.n600}" }, + "backgroundSecondaryDangerFocus": { "value": "{colors.n400}" }, + "backgroundSecondaryDangerKeyfocus": { "value": "{colors.n400}" }, + "backgroundSecondaryDangerDisabled": { "value": "{colors.n300}" }, + "fontOnSecondaryDanger": { "value": "{colors.r700}" }, + "onSecondaryDangerDisabled": { "value": "{colors.r300}" }, - "backgroundDangerDefault": { "value": "{colors.r500}" }, - "backgroundDangerHover": { "value": "{colors.r600}" }, - "backgroundDangerPress": { "value": "{colors.r700}" }, - "backgroundDangerFocus": { "value": "{colors.r500}" }, - "backgroundDangerKeyfocus": { "value": "{colors.r500}" }, - "backgroundDangerDisabled": { "value": "{colors.r200}" }, - "fontOnDanger": { "value": "{colors.white}" }, - "fontOnDangerDisabled": { "value": "{colors.white}" }, + "backgroundDangerDefault": { "value": "{colors.r500}" }, + "backgroundDangerHover": { "value": "{colors.r600}" }, + "backgroundDangerPress": { "value": "{colors.r700}" }, + "backgroundDangerFocus": { "value": "{colors.r500}" }, + "backgroundDangerKeyfocus": { "value": "{colors.r500}" }, + "backgroundDangerDisabled": { "value": "{colors.r200}" }, + "fontOnDanger": { "value": "{colors.white}" }, + "fontOnDangerDisabled": { "value": "{colors.white}" }, - "backgroundWarningDefault": { "value": "{colors.y400}" }, - "backgroundWarningHover": { "value": "{colors.y500}" }, - "backgroundWarningPress": { "value": "{colors.y600}" }, - "backgroundWarningFocus": { "value": "{colors.y400}" }, - "backgroundWarningKeyfocus": { "value": "{colors.y400}" }, - "backgroundWarningDisabled": { "value": "{colors.y200}" }, - "fontOnWarning": { "value": "{colors.n900}" }, - "fontOnWarningDisabled": { "value": "{colors.n600}" }, + "backgroundSuccessDefault": { "value": "{colors.g500}" }, + "backgroundSuccessHover": { "value": "{colors.g600}" }, + "backgroundSuccessPress": { "value": "{colors.g700}" }, + "backgroundSuccessFocus": { "value": "{colors.g500}" }, + "backgroundSuccessKeyfocus": { "value": "{colors.g500}" }, + "backgroundSuccessDisabled": { "value": "{colors.g200}" }, + "fontOnSuccess": { "value": "{colors.n900}" }, + "fontOnSuccessDisabled": { "value": "{colors.white}" } + }, + "high-contrast": { + "backgroundPrimaryDefault": { "value": "{colors.b700}" }, + "backgroundPrimaryHover": { "value": "{colors.b800}" }, + "backgroundPrimaryPress": { "value": "{colors.b900}" }, + "backgroundPrimaryFocus": { "value": "{colors.b700}" }, + "backgroundPrimaryKeyfocus": { "value": "{colors.b700}" }, + "backgroundPrimaryDisabled": { "value": "{colors.b200}" }, + "fontOnPrimary": { "value": "{colors.white}" }, + "fontOnPrimaryDisabled": { "value": "{colors.white}" }, - "backgroundSecondaryWarningDefault": { "value": "{colors.n400}" }, - "backgroundSecondaryWarningHover": { "value": "{colors.n500}" }, - "backgroundSecondaryWarningPress": { "value": "{colors.n600}" }, - "backgroundSecondaryWarningFocus": { "value": "{colors.n400}" }, - "backgroundSecondaryWarningKeyfocus": { "value": "{colors.n400}" }, - "backgroundSecondaryWarningDisabled": { "value": "{colors.n300}" }, - "fontOnSecondaryWarning": { "value": "{colors.y900}" }, - "fontOnSecondaryWarningDisabled": { "value": "{colors.y600}" }, + "backgroundSecondaryDefault": { "value": "{colors.n400}" }, + "backgroundSecondaryHover": { "value": "{colors.n500}" }, + "backgroundSecondaryPress": { "value": "{colors.n600}" }, + "backgroundSecondaryFocus": { "value": "{colors.n400}" }, + "backgroundSecondaryKeyfocus": { "value": "{colors.n400}" }, + "backgroundSecondaryDisabled": { "value": "{colors.n300}" }, + "fontOnSecondary": { "value": "{colors.n900}" }, + "fontOnSecondaryDisabled": { "value": "{colors.n500}" }, - "backgroundSuccessDefault": { "value": "{colors.g500}" }, - "backgroundSuccessHover": { "value": "{colors.g600}" }, - "backgroundSuccessPress": { "value": "{colors.g700}" }, - "backgroundSuccessFocus": { "value": "{colors.g500}" }, - "backgroundSuccessKeyfocus": { "value": "{colors.g500}" }, - "backgroundSuccessDisabled": { "value": "{colors.g200}" }, - "fontOnSuccess": { "value": "{colors.n900}" }, - "fontOnSuccessDisabled": { "value": "{colors.white}" }, + "backgroundSecondaryDangerDefault": { "value": "{colors.n400}" }, + "backgroundSecondaryDangerHover": { "value": "{colors.n500}" }, + "backgroundSecondaryDangerPress": { "value": "{colors.n600}" }, + "backgroundSecondaryDangerFocus": { "value": "{colors.n400}" }, + "backgroundSecondaryDangerKeyfocus": { "value": "{colors.n400}" }, + "backgroundSecondaryDangerDisabled": { "value": "{colors.n300}" }, + "fontOnSecondaryDanger": { "value": "{colors.r900}" }, + "onSecondaryDangerDisabled": { "value": "{colors.r300}" }, - "backgroundSecondarySuccessDefault": { "value": "{colors.n400}" }, - "backgroundSecondarySuccessHover": { "value": "{colors.n500}" }, - "backgroundSecondarySuccessPress": { "value": "{colors.n600}" }, - "backgroundSecondarySuccessFocus": { "value": "{colors.n400}" }, - "backgroundSecondarySuccessKeyfocus": { "value": "{colors.n400}" }, - "backgroundSecondarySuccessDisabled": { "value": "{colors.n300}" }, - "fontOnSecondarySuccess": { "value": "{colors.g900}" }, - "fontOnSecondarySuccessDisabled": { "value": "{colors.g400}" }, + "backgroundDangerDefault": { "value": "{colors.r800}" }, + "backgroundDangerHover": { "value": "{colors.r900}" }, + "backgroundDangerPress": { "value": "{colors.r900}" }, + "backgroundDangerFocus": { "value": "{colors.r800}" }, + "backgroundDangerKeyfocus": { "value": "{colors.r800}" }, + "backgroundDangerDisabled": { "value": "{colors.r200}" }, + "fontOnDanger": { "value": "{colors.white}" }, + "fontOnDangerDisabled": { "value": "{colors.white}" }, - "onDisabled": { "value": "{colors.n600}" } + "backgroundSuccessDefault": { "value": "{colors.g500}" }, + "backgroundSuccessHover": { "value": "{colors.g600}" }, + "backgroundSuccessPress": { "value": "{colors.g700}" }, + "backgroundSuccessFocus": { "value": "{colors.g500}" }, + "backgroundSuccessKeyfocus": { "value": "{colors.g500}" }, + "backgroundSuccessDisabled": { "value": "{colors.g200}" }, + "fontOnSuccess": { "value": "{colors.n900}" }, + "fontOnSuccessDisabled": { "value": "{colors.white}" } + }, + "dark": { + "backgroundPrimaryDefault": { "value": "#095AD2" }, + "backgroundPrimaryHover": { "value": "#10529E" }, + "backgroundPrimaryPress": { "value": "#01336B" }, + "backgroundPrimaryFocus": { "value": "#095AD2" }, + "backgroundPrimaryKeyfocus": { "value": "#095AD2" }, + "backgroundPrimaryDisabled": { "value": "#012247" }, + "fontOnPrimary": { "value": "#FFFFFF" }, + "fontOnPrimaryDisabled": { "value": "#6C727A" }, + + "backgroundSecondaryDefault": { "value": "#353B45" }, + "backgroundSecondaryHover": { "value": "#404754" }, + "backgroundSecondaryPress": { "value": "#4C5362" }, + "backgroundSecondaryFocus": { "value": "#353B45" }, + "backgroundSecondaryKeyfocus": { "value": "#353B45" }, + "backgroundSecondaryDisabled": { "value": "#353B45" }, + "fontOnSecondary": { "value": "#E4E7EA" }, + "fontOnSecondaryDisabled": { "value": "#6C727A" }, + + "backgroundSecondaryDangerDefault": { "value": "#353B45" }, + "backgroundSecondaryDangerHover": { "value": "#404754" }, + "backgroundSecondaryDangerPress": { "value": "#4C5362" }, + "backgroundSecondaryDangerFocus": { "value": "#353B45" }, + "backgroundSecondaryDangerKeyfocus": { "value": "#353B45" }, + "backgroundSecondaryDangerDisabled": { "value": "#353B45" }, + "fontOnSecondaryDanger": { "value": "#FFC1C9" }, + "onSecondaryDangerDisabled": { "value": "#6B0513" }, + + "backgroundDangerDefault": { "value": "#BB3E4E" }, + "backgroundDangerHover": { "value": "#95323F" }, + "backgroundDangerPress": { "value": "#822C37" }, + "backgroundDangerFocus": { "value": "#BB3E4E" }, + "backgroundDangerKeyfocus": { "value": "#BB3E4E" }, + "backgroundDangerDisabled": { "value": "#3D2126" }, + "fontOnDanger": { "value": "#FFFFFF" }, + "fontOnDangerDisabled": { "value": "#757575" }, + + "backgroundSuccessDefault": { "value": "#1D7256" }, + "backgroundSuccessHover": { "value": "#175943" }, + "backgroundSuccessPress": { "value": "#134937" }, + "backgroundSuccessFocus": { "value": "#1D7256" }, + "backgroundSuccessKeyfocus": { "value": "#1D7256" }, + "backgroundSuccessDisabled": { "value": "#1E4B40" }, + "fontOnSuccess": { "value": "#FFFFFF" }, + "fontOnSuccessDisabled": { "value": "#757575" } + } } } diff --git a/packages/fuselage-tokens/src/font/base.json b/packages/fuselage-tokens/src/font/base.json index 02b401b191..098d21009d 100644 --- a/packages/fuselage-tokens/src/font/base.json +++ b/packages/fuselage-tokens/src/font/base.json @@ -1,15 +1,43 @@ { "font": { - "white": { "value": "{colors.white}" }, - "disabled": { "value": "{colors.n500}" }, - "annotation": { "value": "{colors.n600}" }, - "hint": { "value": "{colors.n700}" }, - "secondaryInfo": { "value": "{colors.n700}" }, - "default": { "value": "{colors.n800}" }, - "titlesLabels": { "value": "{colors.n900}" }, - "info": { "value": "{colors.b600}" }, - "danger": { "value": "{colors.r600}" }, - "pure-white": { "value": "{colors.white}" }, - "pure-black": { "value": "{colors.n800}" } + "light": { + "white": { "value": "{colors.white}" }, + "disabled": { "value": "{colors.n500}" }, + "annotation": { "value": "{colors.n600}" }, + "hint": { "value": "{colors.n700}" }, + "secondaryInfo": { "value": "{colors.n700}" }, + "default": { "value": "{colors.n800}" }, + "titlesLabels": { "value": "{colors.n900}" }, + "info": { "value": "{colors.b600}" }, + "danger": { "value": "{colors.r600}" }, + "pureWhite": { "value": "{colors.white}" }, + "pureBlack": { "value": "{colors.n800}" } + }, + "high-contrast": { + "white": { "value": "{colors.white}" }, + "disabled": { "value": "{colors.n500}" }, + "annotation": { "value": "{colors.n900}" }, + "hint": { "value": "{colors.n900}" }, + "secondaryInfo": { "value": "{colors.n900}" }, + "default": { "value": "{colors.n900}" }, + "titlesLabels": { "value": "{colors.n900}" }, + "info": { "value": "{colors.b800}" }, + "danger": { "value": "{colors.r800}" }, + "pureWhite": { "value": "{colors.white}" }, + "pureBlack": { "value": "{colors.n900}" } + }, + "dark": { + "white": { "value": "#2F343D" }, + "disabled": { "value": "#60646C" }, + "annotation": { "value": "#9EA2A8" }, + "hint": { "value": "#9EA2A8" }, + "secondaryInfo": { "value": "#9EA2A8" }, + "default": { "value": "#C1C7D0" }, + "titlesLabels": { "value": "#F2F3F5" }, + "info": { "value": "#739EDE" }, + "danger": { "value": "#D88892" }, + "pureWhite": { "value": "{colors.white}" }, + "pureBlack": { "value": "{colors.n900}" } + } } } diff --git a/packages/fuselage-tokens/src/shadow/base.json b/packages/fuselage-tokens/src/shadow/base.json new file mode 100644 index 0000000000..3d3123032f --- /dev/null +++ b/packages/fuselage-tokens/src/shadow/base.json @@ -0,0 +1,28 @@ +{ + "shadow": { + "light": { + "highlight": { "value": "{colors.b200}" }, + "danger": { "value": "{colors.r100}" }, + "elevation-border": { "value": "{colors.n250}" }, + "elevation-1": { "value": "rgba(47, 52, 61, 0.1)" }, + "elevation-2x": { "value": "rgba(47, 52, 61, 0.08)" }, + "elevation-2y": { "value": "rgba(47, 52, 61, 0.12)" } + }, + "high-contrast": { + "highlight": { "value": "{colors.b200}" }, + "danger": { "value": "{colors.r100}" }, + "elevation-border": { "value": "{colors.n250}" }, + "elevation-1": { "value": "rgba(47, 52, 61, 0.1)" }, + "elevation-2x": { "value": "rgba(47, 52, 61, 0.08)" }, + "elevation-2y": { "value": "rgba(47, 52, 61, 0.12)" } + }, + "dark": { + "highlight": { "value": "{colors.b200}" }, + "danger": { "value": "{colors.r100}" }, + "elevation-border": { "value": "#2F343D" }, + "elevation-1": { "value": "rgba(9, 9, 9, 0.35)" }, + "elevation-2x": { "value": "rgba(9, 9, 9, 0.3)" }, + "elevation-2y": { "value": "rgba(9, 9, 9, 0.45)" } + } + } +} diff --git a/packages/fuselage-tokens/src/status/base.json b/packages/fuselage-tokens/src/status/base.json index 0453d196e5..900736e2ae 100644 --- a/packages/fuselage-tokens/src/status/base.json +++ b/packages/fuselage-tokens/src/status/base.json @@ -1,16 +1,58 @@ { "status": { - "info": { "value": "{colors.b200}" }, - "font-on-info": { "value": "{colors.b600}" }, - "success": { "value": "{colors.g200}" }, - "font-on-success": { "value": "{colors.g800}" }, - "danger": { "value": "{colors.r200}" }, - "font-on-danger": { "value": "{colors.r800}" }, - "warning": { "value": "{colors.y200}" }, - "font-on-warning": { "value": "{colors.y900}" }, - "service-1": { "value": "{colors.o200}" }, - "font-on-service-1": { "value": "{colors.o800}" }, - "service-2": { "value": "{colors.p200}" }, - "font-on-service-2": { "value": "{colors.p600}" } + "light": { + "info": { "value": "{colors.b200}" }, + "font-on-info": { "value": "{colors.b600}" }, + "success": { "value": "{colors.g200}" }, + "font-on-success": { "value": "{colors.g800}" }, + "danger": { "value": "{colors.r200}" }, + "font-on-danger": { "value": "{colors.r800}" }, + "warning": { "value": "{colors.y200}" }, + "font-on-warning": { "value": "{colors.y900}" }, + "warning-2": { "value": "{colors.y100}" }, + "font-on-warning-2": { "value": "{colors.n800}" }, + "service-1": { "value": "{colors.o200}" }, + "font-on-service-1": { "value": "{colors.o800}" }, + "service-2": { "value": "{colors.p200}" }, + "font-on-service-2": { "value": "{colors.p600}" }, + "service-3": { "value": "{colors.p700}" }, + "font-on-service-3": { "value": "{colors.white}" } + }, + "high-contrast": { + "info": { "value": "{colors.b200}" }, + "font-on-info": { "value": "{colors.b700}" }, + "success": { "value": "{colors.g200}" }, + "font-on-success": { "value": "{colors.g1000}" }, + "danger": { "value": "{colors.r200}" }, + "font-on-danger": { "value": "{colors.r1000}" }, + "warning": { "value": "{colors.y200}" }, + "font-on-warning": { "value": "{colors.y1000}" }, + "warning-2": { "value": "{colors.y100}" }, + "font-on-warning-2": { "value": "{colors.n800}" }, + "service-1": { "value": "{colors.o200}" }, + "font-on-service-1": { "value": "{colors.o1000}" }, + "service-2": { "value": "{colors.p200}" }, + "font-on-service-2": { "value": "{colors.p600}" }, + "service-3": { "value": "{colors.p700}" }, + "font-on-service-3": { "value": "{colors.white}" } + }, + "dark": { + "info": { "value": "#A8C3EB" }, + "font-on-info": { "value": "#739EDE" }, + "success": { "value": "#C1EBDD" }, + "font-on-success": { "value": "#58AD90" }, + "danger": { "value": "#F7CFD4" }, + "font-on-danger": { "value": "#D88892" }, + "warning": { "value": "#FEEFBE" }, + "font-on-warning": { "value": "#C7AA66" }, + "warning-2": { "value": "#3C3625" }, + "font-on-warning-2": { "value": "#FFFFFF" }, + "service-1": { "value": "#FCE3CF" }, + "font-on-service-1": { "value": "#CA9163" }, + "service-2": { "value": "#EDD0F7" }, + "font-on-service-2": { "value": "#C393D2" }, + "service-3": { "value": "#5F1477" }, + "font-on-service-3": { "value": "#FFFFFF" } + } } } diff --git a/packages/fuselage-tokens/src/statusBullet/base.json b/packages/fuselage-tokens/src/statusBullet/base.json new file mode 100644 index 0000000000..1ccce4b9c9 --- /dev/null +++ b/packages/fuselage-tokens/src/statusBullet/base.json @@ -0,0 +1,28 @@ +{ + "statusBullet": { + "light": { + "online": { "value": "{colors.g800}" }, + "away": { "value": "{colors.y800}" }, + "busy": { "value": "{colors.r600}" }, + "disabled": { "value": "{colors.o500}" }, + "offline": { "value": "{colors.n700}" }, + "loading": { "value": "{colors.n700}" } + }, + "high-contrast": { + "online": { "value": "{colors.g1000}" }, + "away": { "value": "{colors.y800}" }, + "busy": { "value": "{colors.r1000}" }, + "disabled": { "value": "{colors.o700}" }, + "offline": { "value": "{colors.n900}" }, + "loading": { "value": "{colors.n900}" } + }, + "dark": { + "online": { "value": "#1CBF89" }, + "away": { "value": "#B08C30" }, + "busy": { "value": "#C75765" }, + "disabled": { "value": "#CC7F42" }, + "offline": { "value": "#8B9098" }, + "loading": { "value": "#8B9098" } + } + } +} diff --git a/packages/fuselage-tokens/src/stroke/base.json b/packages/fuselage-tokens/src/stroke/base.json index 6322aeccc6..8ebe254455 100644 --- a/packages/fuselage-tokens/src/stroke/base.json +++ b/packages/fuselage-tokens/src/stroke/base.json @@ -1,13 +1,37 @@ { "stroke": { - "extraLight": { "value": "{colors.n250}" }, - "light": { "value": "{colors.n500}" }, - "medium": { "value": "{colors.n600}" }, - "dark": { "value": "{colors.n700}" }, - "extraDark": { "value": "{colors.n800}" }, - "extraLightHighlight": { "value": "{colors.b200}" }, - "highlight": { "value": "{colors.b500}" }, - "extraLightError": { "value": "{colors.r200}" }, - "error": { "value": "{colors.r500}" } + "light": { + "extraLight": { "value": "{colors.n250}" }, + "light": { "value": "{colors.n500}" }, + "medium": { "value": "{colors.n600}" }, + "dark": { "value": "{colors.n700}" }, + "extraDark": { "value": "{colors.n800}" }, + "extraLightHighlight": { "value": "{colors.b200}" }, + "highlight": { "value": "{colors.b500}" }, + "extraLightError": { "value": "{colors.r200}" }, + "error": { "value": "{colors.r500}" } + }, + "high-contrast": { + "extraLight": { "value": "{colors.n250}" }, + "light": { "value": "{colors.n500}" }, + "medium": { "value": "{colors.n600}" }, + "dark": { "value": "{colors.n700}" }, + "extraDark": { "value": "{colors.n800}" }, + "extraLightHighlight": { "value": "{colors.b200}" }, + "highlight": { "value": "{colors.b500}" }, + "extraLightError": { "value": "{colors.r200}" }, + "error": { "value": "{colors.r500}" } + }, + "dark": { + "extraLight": { "value": "#333842" }, + "light": { "value": "#404754" }, + "medium": { "value": "#4B5362" }, + "dark": { "value": "#9EA2A8" }, + "extraDark": { "value": "#CBCED1" }, + "extraLightHighlight": { "value": "#D1EBFE" }, + "highlight": { "value": "#6292DA" }, + "extraLightError": { "value": "#F49AA6" }, + "error": { "value": "#BB3E4E" } + } } } diff --git a/packages/fuselage-tokens/src/surface/base.json b/packages/fuselage-tokens/src/surface/base.json index 704426641a..275d3bc947 100644 --- a/packages/fuselage-tokens/src/surface/base.json +++ b/packages/fuselage-tokens/src/surface/base.json @@ -1,14 +1,46 @@ { "surface": { - "light": { "value": "{colors.white}" }, - "tint": { "value": "{colors.n100}" }, - "room": { "value": "{colors.white}" }, - "neutral": { "value": "{colors.n400}" }, - "disabled": { "value": "{colors.n100}" }, - "hover": { "value": "{colors.n200}" }, - "selected": { "value": "{colors.n450}" }, - "dark": { "value": "{colors.n900}" }, - "featured": { "value": "{colors.p700}" }, - "featured-hover": { "value": "{colors.p800}" } + "light": { + "light": { "value": "{colors.white}" }, + "tint": { "value": "{colors.n100}" }, + "room": { "value": "{colors.white}" }, + "neutral": { "value": "{colors.n400}" }, + "disabled": { "value": "{colors.n100}" }, + "hover": { "value": "{colors.n200}" }, + "selected": { "value": "{colors.n450}" }, + "dark": { "value": "{colors.n900}" }, + "featured": { "value": "{colors.p700}" }, + "featuredHover": { "value": "{colors.p800}" }, + "sidebar": { "value": "{colors.n400}" }, + "overlay": { "value": "rgba(47, 52, 61, 0.5)" } + }, + "high-contrast": { + "light": { "value": "{colors.white}" }, + "tint": { "value": "{colors.n100}" }, + "room": { "value": "{colors.white}" }, + "neutral": { "value": "{colors.n400}" }, + "disabled": { "value": "{colors.n100}" }, + "hover": { "value": "{colors.n200}" }, + "selected": { "value": "{colors.n450}" }, + "dark": { "value": "{colors.n900}" }, + "featured": { "value": "{colors.p700}" }, + "featuredHover": { "value": "{colors.p800}" }, + "sidebar": { "value": "{colors.n400}" }, + "overlay": { "value": "rgba(47, 52, 61, 0.5)" } + }, + "dark": { + "light": { "value": "#262931" }, + "tint": { "value": "#1F2329" }, + "room": { "value": "#1F2329" }, + "neutral": { "value": "#2D3039" }, + "disabled": { "value": "#24272E" }, + "hover": { "value": "#1A1E23" }, + "selected": { "value": "#4C5362" }, + "dark": { "value": "#E4E7EA" }, + "featured": { "value": "#5F1477" }, + "featuredHover": { "value": "#4A105D" }, + "sidebar": { "value": "#2F343D" }, + "overlay": { "value": "rgba(0, 0, 0, 0.6)" } + } } } diff --git a/packages/fuselage/.storybook/DocsContainer.tsx b/packages/fuselage/.storybook/DocsContainer.tsx new file mode 100644 index 0000000000..34a38804a5 --- /dev/null +++ b/packages/fuselage/.storybook/DocsContainer.tsx @@ -0,0 +1,43 @@ +import { DocsContainer as BaseContainer } from '@storybook/addon-docs/blocks'; +import { themes } from '@storybook/theming'; +import type { ComponentProps } from 'react'; +import React from 'react'; +import { useDarkMode } from 'storybook-dark-mode'; + +import { surface } from './helpers'; + +export const DocsContainer = ({ + children, + context, +}: ComponentProps) => { + const dark = useDarkMode(); + + return ( + { + const storyContext = context.storyById(id); + return { + ...storyContext, + parameters: { + ...storyContext?.parameters, + docs: { + ...storyContext?.parameters?.docs, + theme: dark + ? { + ...themes.dark, + appContentBg: surface.main, + barBg: surface.main, + } + : themes.light, + }, + }, + }; + }, + }} + > + {children} + + ); +}; diff --git a/packages/fuselage/.storybook/helpers.tsx b/packages/fuselage/.storybook/helpers.tsx index de0ff88efb..b90254fb7c 100644 --- a/packages/fuselage/.storybook/helpers.tsx +++ b/packages/fuselage/.storybook/helpers.tsx @@ -2,6 +2,7 @@ import type { ComponentProps, ComponentType } from 'react'; import React from 'react'; import { Box, Icon } from '../src'; +import { dark } from '../src/components/PaletteStyleTag/lib/themePalettes'; type PropsVariationSectionProps> = { component: TComponent; @@ -143,3 +144,8 @@ export const menuOptions = { action: () => console.log('[...] no longer exists'), }, }; + +export const surface = { + sidebar: dark['surface-sidebar'], + main: dark['surface-light'], +}; diff --git a/packages/fuselage/.storybook/preview.ts b/packages/fuselage/.storybook/preview.tsx similarity index 70% rename from packages/fuselage/.storybook/preview.ts rename to packages/fuselage/.storybook/preview.tsx index 65c44abd21..5071b1bb93 100644 --- a/packages/fuselage/.storybook/preview.ts +++ b/packages/fuselage/.storybook/preview.tsx @@ -1,9 +1,15 @@ import breakpointTokens from '@rocket.chat/fuselage-tokens/breakpoints.json'; -import { DocsPage, DocsContainer } from '@storybook/addon-docs'; +import { DocsPage } from '@storybook/addon-docs'; import type { Parameters } from '@storybook/addons'; +import type { DecoratorFn } from '@storybook/react'; import { themes } from '@storybook/theming'; +import React from 'react'; +import { useDarkMode } from 'storybook-dark-mode'; import manifest from '../package.json'; +import { PaletteStyleTag } from '../src'; +import { DocsContainer } from './DocsContainer'; +import { surface } from './helpers'; import logo from './logo.svg'; import 'normalize.css/normalize.css'; @@ -56,6 +62,9 @@ export const parameters: Parameters = { darkMode: { dark: { ...themes.dark, + appBg: surface.sidebar, + appContentBg: surface.main, + barBg: surface.main, brandTitle: manifest.name, brandImage: logo, brandUrl: manifest.homepage, @@ -68,3 +77,16 @@ export const parameters: Parameters = { }, }, }; + +export const decorators: DecoratorFn[] = [ + (Story) => { + const dark = useDarkMode(); + + return ( + <> + + + + ); + }, +]; diff --git a/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.spec.tsx b/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.spec.tsx new file mode 100644 index 0000000000..b5a5d28746 --- /dev/null +++ b/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.spec.tsx @@ -0,0 +1,39 @@ +import { render } from '@testing-library/react'; +import React from 'react'; + +import PaletteStyleTag from './PaletteStyleTag'; +import { dark, light } from './lib/themePalettes'; + +describe('[PaletteStyleTag colors]', () => { + it('creates the Light theme style tag', () => { + render(); + const style = document.querySelector('#main-palette'); + expect(style?.innerHTML).toContain( + `surface-light: ${light['surface-light']}` + ); + }); + it('creates the Dark theme style tag', () => { + render(); + const style = document.querySelector('#main-palette'); + expect(style?.innerHTML).toContain( + `surface-light: ${dark['surface-light']}` + ); + }); + it('creates tag with the given id', () => { + render(); + const style = document.querySelector('#test-palette'); + expect(style).not.toBeNull(); + }); + it('creates tag with the given prefix', () => { + render(); + const style = document.querySelector('#main-palette'); + expect(style?.innerHTML).toContain( + `--test-surface-light: ${light['surface-light']}` + ); + }); + it('creates tag with the given selector', () => { + render(); + const style = document.querySelector('#main-palette'); + expect(style?.innerHTML).toContain('.test {'); + }); +}); diff --git a/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.stories.tsx b/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.stories.tsx new file mode 100644 index 0000000000..fe1df9d366 --- /dev/null +++ b/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.stories.tsx @@ -0,0 +1,94 @@ +import { + Title, + Subtitle, + Description, + Primary as PrimaryStory, + ArgsTable, + Stories, + PRIMARY_STORY, +} from '@storybook/addon-docs'; +import type { ComponentStory, ComponentMeta } from '@storybook/react'; +import React from 'react'; + +import { + Box, + Button, + PaletteStyleTag, + Card, + CardHeader, + FramedIcon, + CardTitle, + CardBody, + CardControls, + Divider, + ProgressBar, + CardCol, +} from '../..'; + +export default { + title: 'Layout/PaletteStyleTag', + component: PaletteStyleTag, + parameters: { + layout: 'centered', + docs: { + description: { + component: + "Style tag to handle the theme of the application.
Import `PaletteStyleTag` and use it on the application informing the desired theme.
Toggle the theme on Storybook's Control panel to see the color changes.", + }, + page: () => ( + <> + + <Subtitle /> + <Description /> + <PrimaryStory /> + <Stories title={''} /> + <ArgsTable story={PRIMARY_STORY} /> + </> + ), + }, + }, +} as ComponentMeta<typeof PaletteStyleTag>; + +export const _PaletteStyleTag: ComponentStory<typeof PaletteStyleTag> = ( + args +) => ( + <Box bg='neutral' p={24}> + <PaletteStyleTag {...args} /> + <Card> + <CardHeader> + <FramedIcon icon='address-book' /> + <CardTitle variant='h3'>{args.theme} theme</CardTitle> + </CardHeader> + <CardBody> + <CardCol> + Toggle the theme on Control panel to see the color changes. + <Divider /> + <ProgressBar percentage={10} variant='danger' /> + <ProgressBar percentage={30} variant='warning' /> + <ProgressBar percentage={75} /> + <ProgressBar percentage={100} variant='success' /> + </CardCol> + </CardBody> + <CardControls> + <Button medium>Default</Button> + <Button medium primary> + Primary + </Button> + <Button medium danger> + Danger + </Button> + </CardControls> + </Card> + </Box> +); + +// export const _PaletteStyleTag: ComponentStory<typeof PaletteStyleTag> = +// Template.bind({}); + +_PaletteStyleTag.parameters = { + docs: { + description: { + story: 'Another description on the story, overriding the comments', + }, + }, +}; diff --git a/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.tsx b/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.tsx new file mode 100644 index 0000000000..689af2f017 --- /dev/null +++ b/packages/fuselage/src/components/PaletteStyleTag/PaletteStyleTag.tsx @@ -0,0 +1,48 @@ +import React, { memo } from 'react'; +import { createPortal } from 'react-dom'; + +import { convertToCss } from './helpers/convertToCss'; +import { useCreateStyleContainer } from './hooks/useCreateStyleContainer'; +import { codeBlock } from './lib/codeBlockStyles'; +import { dark, highContrast, light } from './lib/themePalettes'; +import type { Themes } from './types/themes'; + +const themes = { + light, + dark, + 'high-contrast': highContrast, +}; + +export const PaletteStyleTag = memo(function PaletteStyleTag({ + theme = 'light', + tagId = 'main-palette', + prefix = '--rcx-color', + selector, +}: { + theme?: Themes; + /** + * Default is `main-palette`. + */ + tagId?: string; + /** + * Token prefix. Default is `--rcx-color`. + */ + prefix?: string; + /** + * Default is `:root`. + */ + selector?: string; +}) { + const palette = convertToCss(themes[theme], prefix, selector); + + return ( + <> + {createPortal( + theme === 'dark' ? palette + codeBlock : palette, + useCreateStyleContainer(tagId) + )} + </> + ); +}); + +export default PaletteStyleTag; diff --git a/packages/fuselage/src/components/PaletteStyleTag/helpers/convertToCss.ts b/packages/fuselage/src/components/PaletteStyleTag/helpers/convertToCss.ts new file mode 100644 index 0000000000..9f9be0e486 --- /dev/null +++ b/packages/fuselage/src/components/PaletteStyleTag/helpers/convertToCss.ts @@ -0,0 +1,8 @@ +export const convertToCss = ( + values: Record<string, string>, + prefix: string, + selector = ':root' +) => + `${selector} {\n${Object.entries(values) + .map(([name, color]) => `${prefix}-${name}: ${color};`) + .join('\n')}\n}`; diff --git a/packages/fuselage/src/components/PaletteStyleTag/helpers/getPalette.ts b/packages/fuselage/src/components/PaletteStyleTag/helpers/getPalette.ts new file mode 100644 index 0000000000..3cc4332444 --- /dev/null +++ b/packages/fuselage/src/components/PaletteStyleTag/helpers/getPalette.ts @@ -0,0 +1,373 @@ +import { badge } from '@rocket.chat/fuselage-tokens/dist/badge.json'; +import { button } from '@rocket.chat/fuselage-tokens/dist/button.json'; +import { font } from '@rocket.chat/fuselage-tokens/dist/font.json'; +import { shadow } from '@rocket.chat/fuselage-tokens/dist/shadow.json'; +import { status } from '@rocket.chat/fuselage-tokens/dist/status.json'; +import { statusBullet } from '@rocket.chat/fuselage-tokens/dist/statusBullet.json'; +import { stroke } from '@rocket.chat/fuselage-tokens/dist/stroke.json'; +import { surface } from '@rocket.chat/fuselage-tokens/dist/surface.json'; + +import type { Themes } from '../types/themes'; + +export const getTokens = (theme: Themes) => { + const tokens = { + badge: badge[theme], + button: button[theme], + font: font[theme], + shadow: shadow[theme], + status: status[theme], + statusBullet: statusBullet[theme], + stroke: stroke[theme], + surface: surface[theme], + }; + + return tokens; +}; + +export const getThemePalette = (theme: Themes) => { + const { badge, button, font, shadow, status, statusBullet, stroke, surface } = + getTokens(theme); + + const palette = [ + { + category: 'Stroke', + description: "Use as component's outline, stroke, dividers", + list: [ + { name: 'stroke-extra-light', color: stroke.extraLight }, + { name: 'stroke-light', color: stroke.light }, + { name: 'stroke-medium', color: stroke.medium }, + { name: 'stroke-dark', color: stroke.dark }, + { name: 'stroke-extra-dark', color: stroke.extraDark }, + { + name: 'stroke-extra-light-highlight', + color: stroke.extraLightHighlight, + }, + { name: 'stroke-highlight', color: stroke.highlight }, + { name: 'stroke-extra-light-error', color: stroke.extraLightError }, + { name: 'stroke-error', color: stroke.error }, + ], + }, + { + category: 'Surface', + description: 'Use as a container on top of the background', + list: [ + { name: 'surface-light', color: surface.light }, + { name: 'surface-tint', color: surface.tint }, + { name: 'surface-room', color: surface.room }, + { name: 'surface-neutral', color: surface.neutral }, + { name: 'surface-disabled', color: surface.disabled }, + { name: 'surface-hover', color: surface.hover }, + { name: 'surface-selected', color: surface.selected }, + { name: 'surface-dark', color: surface.dark }, + { name: 'surface-featured', color: surface.featured }, + { name: 'surface-featured-hover', color: surface.featuredHover }, + { name: 'surface-overlay', color: surface.overlay }, + { name: 'surface-sidebar', color: surface.sidebar }, + ], + }, + { + category: 'Shadow', + description: 'Use as a shadow color', + list: [ + { name: 'shadow-highlight', color: shadow.highlight }, + { name: 'shadow-danger', color: shadow.danger }, + { name: 'shadow-elevation-border', color: shadow['elevation-border'] }, + { name: 'shadow-elevation-1', color: shadow['elevation-1'] }, + { + name: 'shadow-elevation-2x', + color: shadow['elevation-2x'], + }, + { + name: 'shadow-elevation-2y', + color: shadow['elevation-2y'], + }, + ], + }, + { + category: 'Font', + description: 'These should be applied according to surfaces', + list: [ + { name: 'font-white', color: font.white }, + { name: 'font-disabled', color: font.disabled }, + { name: 'font-annotation', color: font.annotation }, + { name: 'font-hint', color: font.hint }, + { name: 'font-secondary-info', color: font.secondaryInfo }, + { name: 'font-default', color: font.default }, + { name: 'font-titles-labels', color: font.titlesLabels }, + { name: 'font-info', color: font.info }, + { name: 'font-danger', color: font.danger }, + { name: 'font-pure-black', color: font.pureBlack }, + { name: 'font-pure-white', color: font.pureWhite }, + ], + }, + { + category: 'Status', + description: 'Status Background', + list: [ + { name: 'status-background-info', color: status.info }, + { name: 'status-background-success', color: status.success }, + { name: 'status-background-danger', color: status.danger }, + { name: 'status-background-warning', color: status.warning }, + { name: 'status-background-warning-2', color: status['warning-2'] }, + { + name: 'status-background-service-1', + color: status['service-1'], + }, + { + name: 'status-background-service-2', + color: status['service-2'], + }, + { + name: 'status-background-service-3', + color: status['service-3'], + }, + ], + }, + { + description: 'Status Font', + list: [ + { name: 'status-font-on-info', color: status['font-on-info'] }, + { name: 'status-font-on-success', color: status['font-on-success'] }, + { name: 'status-font-on-danger', color: status['font-on-danger'] }, + { name: 'status-font-on-warning', color: status['font-on-warning'] }, + { + name: 'status-font-on-warning-2', + color: status['font-on-warning-2'], + }, + { + name: 'status-font-on-service-1', + color: status['font-on-service-1'], + }, + { + name: 'status-font-on-service-2 ', + color: status['font-on-service-2'], + }, + { + name: 'status-font-on-service-3 ', + color: status['font-on-service-3'], + }, + ], + }, + { + category: 'Badge', + description: 'Badge Background', + list: [ + { name: 'badge-background-level-0', color: badge['level-0'] }, + { name: 'badge-background-level-1', color: badge['level-1'] }, + { name: 'badge-background-level-2', color: badge['level-2'] }, + { name: 'badge-background-level-3', color: badge['level-3'] }, + { name: 'badge-background-level-4', color: badge['level-4'] }, + ], + }, + { + category: 'Status Bullet', + description: 'Used to show user status', + list: [ + { name: 'status-bullet-online', color: statusBullet.online }, + { name: 'status-bullet-away', color: statusBullet.away }, + { name: 'status-bullet-busy', color: statusBullet.busy }, + { name: 'status-bullet-disabled', color: statusBullet.disabled }, + { name: 'status-bullet-offline', color: statusBullet.offline }, + { name: 'status-bullet-loading', color: statusBullet.loading }, + ], + }, + { + category: 'Button', + description: 'Primary Background', + list: [ + { + name: 'button-background-primary-default', + color: button.backgroundPrimaryDefault, + }, + { + name: 'button-background-primary-hover', + color: button.backgroundPrimaryHover, + }, + { + name: 'button-background-primary-press', + color: button.backgroundPrimaryPress, + }, + { + name: 'button-background-primary-focus', + color: button.backgroundPrimaryFocus, + }, + { + name: 'button-background-primary-keyfocus', + color: button.backgroundPrimaryKeyfocus, + }, + { + name: 'button-background-primary-disabled', + color: button.backgroundPrimaryDisabled, + }, + ], + }, + { + description: 'Secondary Background', + list: [ + { + name: 'button-background-secondary-default', + color: button.backgroundSecondaryDefault, + }, + { + name: 'button-background-secondary-hover', + color: button.backgroundSecondaryHover, + }, + { + name: 'button-background-secondary-press', + color: button.backgroundSecondaryPress, + }, + { + name: 'button-background-secondary-focus', + color: button.backgroundSecondaryFocus, + }, + { + name: 'button-background-secondary-keyfocus', + color: button.backgroundSecondaryKeyfocus, + }, + { + name: 'button-background-secondary-disabled', + color: button.backgroundSecondaryDisabled, + }, + ], + }, + { + description: 'Secondary Danger Background', + list: [ + { + name: 'button-background-secondary-danger-default', + color: button.backgroundSecondaryDangerDefault, + }, + { + name: 'button-background-secondary-danger-hover', + color: button.backgroundSecondaryDangerHover, + }, + { + name: 'button-background-secondary-danger-press', + color: button.backgroundSecondaryDangerPress, + }, + { + name: 'button-background-secondary-danger-focus', + color: button.backgroundSecondaryDangerFocus, + }, + { + name: 'button-background-secondary-danger-keyfocus', + color: button.backgroundSecondaryDangerKeyfocus, + }, + { + name: 'button-background-secondary-danger-disabled', + color: button.backgroundDangerDisabled, + }, + ], + }, + { + description: 'Danger Background', + list: [ + { + name: 'button-background-danger-default', + color: button.backgroundDangerDefault, + }, + { + name: 'button-background-danger-hover', + color: button.backgroundDangerHover, + }, + { + name: 'button-background-danger-press', + color: button.backgroundDangerPress, + }, + { + name: 'button-background-danger-focus', + color: button.backgroundDangerFocus, + }, + { + name: 'button-background-danger-keyfocus', + color: button.backgroundDangerKeyfocus, + }, + { + name: 'button-background-danger-disabled', + color: button.backgroundDangerDisabled, + }, + ], + }, + { + description: 'Success Background', + list: [ + { + name: 'button-background-success-default', + color: button.backgroundSuccessDefault, + }, + { + name: 'button-background-success-hover', + color: button.backgroundSuccessHover, + }, + { + name: 'button-background-success-press', + color: button.backgroundSuccessPress, + }, + { + name: 'button-background-success-focus', + color: button.backgroundSuccessFocus, + }, + { + name: 'button-background-success-keyfocus', + color: button.backgroundSuccessKeyfocus, + }, + { + name: 'button-background-success-disabled', + color: button.backgroundSuccessDisabled, + }, + ], + }, + { + description: 'Font', + list: [ + { name: 'button-font-on-primary', color: button.fontOnPrimary }, + { + name: 'button-font-on-primary-disabled', + color: button.fontOnPrimaryDisabled, + }, + { + name: 'button-font-on-secondary', + color: button.fontOnSecondary, + }, + { + name: 'button-font-on-secondary-disabled', + color: button.fontOnSecondaryDisabled, + }, + { + name: 'button-font-on-secondary-danger', + color: button.fontOnSecondaryDanger, + }, + { + name: 'button-font-on-secondary-danger-disabled', + color: button.onSecondaryDangerDisabled, + }, + { name: 'button-font-on-danger', color: button.fontOnDanger }, + { + name: 'button-font-on-danger-disabled', + color: button.fontOnDangerDisabled, + }, + { name: 'button-font-on-success', color: button.fontOnSuccess }, + { + name: 'button-font-on-success-disabled', + color: button.fontOnSuccessDisabled, + }, + ], + }, + ]; + + return { + ...palette.reduce( + (rec, group) => ({ + ...rec, + ...group.list.reduce( + (rec, item) => ({ + ...rec, + [item.name]: item.color, + }), + {} as Record<string, string> + ), + }), + {} as Record<string, string> + ), + }; +}; diff --git a/packages/fuselage/src/components/PaletteStyleTag/helpers/isHexColor.ts b/packages/fuselage/src/components/PaletteStyleTag/helpers/isHexColor.ts new file mode 100644 index 0000000000..8bc9fcced6 --- /dev/null +++ b/packages/fuselage/src/components/PaletteStyleTag/helpers/isHexColor.ts @@ -0,0 +1,2 @@ +export const isHexColor = (hex: string): boolean => + typeof hex === 'string' && hex.length === 6 && !isNaN(Number(`0x${hex}`)); diff --git a/packages/fuselage/src/components/PaletteStyleTag/helpers/isLightColor.ts b/packages/fuselage/src/components/PaletteStyleTag/helpers/isLightColor.ts new file mode 100644 index 0000000000..2324b75b8d --- /dev/null +++ b/packages/fuselage/src/components/PaletteStyleTag/helpers/isLightColor.ts @@ -0,0 +1,8 @@ +export const isLightColor = (color: string): boolean => { + const hex = color.replace('#', ''); + const r = parseInt(hex.substring(0, 0 + 2), 16); + const g = parseInt(hex.substring(2, 2 + 2), 16); + const b = parseInt(hex.substring(4, 4 + 2), 16); + const brightness = (r * 299 + g * 587 + b * 114) / 1000; + return brightness > 155; +}; diff --git a/packages/fuselage/src/components/PaletteStyleTag/hooks/useCreateStyleContainer.ts b/packages/fuselage/src/components/PaletteStyleTag/hooks/useCreateStyleContainer.ts new file mode 100644 index 0000000000..584c81bd2e --- /dev/null +++ b/packages/fuselage/src/components/PaletteStyleTag/hooks/useCreateStyleContainer.ts @@ -0,0 +1,20 @@ +import { useMemo } from 'react'; + +export const useCreateStyleContainer = (id: string) => + useMemo(() => { + const refElement = + document.getElementById('rcx-styles') || document.head.lastChild; + + const el = document.getElementById(id); + + if (el) { + return el; + } + + const styleElement = document.createElement('style'); + styleElement.setAttribute('id', id); + + document.head.insertBefore(styleElement, refElement); + document.head.appendChild(document.createElement('style')); + return styleElement; + }, [id]); diff --git a/packages/fuselage/src/components/PaletteStyleTag/index.ts b/packages/fuselage/src/components/PaletteStyleTag/index.ts new file mode 100644 index 0000000000..7003031c97 --- /dev/null +++ b/packages/fuselage/src/components/PaletteStyleTag/index.ts @@ -0,0 +1 @@ +export * from './PaletteStyleTag'; diff --git a/packages/fuselage/src/components/PaletteStyleTag/lib/codeBlockStyles.ts b/packages/fuselage/src/components/PaletteStyleTag/lib/codeBlockStyles.ts new file mode 100644 index 0000000000..2c6b4bf33b --- /dev/null +++ b/packages/fuselage/src/components/PaletteStyleTag/lib/codeBlockStyles.ts @@ -0,0 +1,74 @@ +export const codeBlock = `pre code.hljs { + display: block; + overflow-x: auto; + padding: 1em; +} +code.hljs { + padding: 3px 5px; +} +.hljs { + background: #1d1f21; + color: #c5c8c6; +} +.hljs span::selection, +.hljs::selection { + background: #373b41; +} +.hljs span::-moz-selection, +.hljs::-moz-selection { + background: #373b41; +} +.hljs-name, +.hljs-title { + color: #f0c674; +} +.hljs-comment, +.hljs-meta, +.hljs-meta .hljs-keyword { + color: #707880; +} +.hljs-deletion, +.hljs-link, +.hljs-literal, +.hljs-number, +.hljs-symbol { + color: #c66; +} +.hljs-addition, +.hljs-doctag, +.hljs-regexp, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-string { + color: #b5bd68; +} +.hljs-attribute, +.hljs-code, +.hljs-selector-id { + color: #b294bb; +} +.hljs-bullet, +.hljs-keyword, +.hljs-selector-tag, +.hljs-tag { + color: #81a2be; +} +.hljs-subst, +.hljs-template-tag, +.hljs-template-variable, +.hljs-variable { + color: #8abeb7; +} +.hljs-built_in, +.hljs-quote, +.hljs-section, +.hljs-selector-class, +.hljs-type { + color: #de935f; +} +.hljs-emphasis { + font-style: italic; +} +.hljs-strong { + font-weight: 700; +}`; diff --git a/packages/fuselage/src/components/PaletteStyleTag/lib/themePalettes.ts b/packages/fuselage/src/components/PaletteStyleTag/lib/themePalettes.ts new file mode 100644 index 0000000000..a605840042 --- /dev/null +++ b/packages/fuselage/src/components/PaletteStyleTag/lib/themePalettes.ts @@ -0,0 +1,5 @@ +import { getThemePalette } from '../helpers/getPalette'; + +export const light = getThemePalette('light'); +export const highContrast = getThemePalette('high-contrast'); +export const dark = getThemePalette('dark'); diff --git a/packages/fuselage/src/components/PaletteStyleTag/types/themes.ts b/packages/fuselage/src/components/PaletteStyleTag/types/themes.ts new file mode 100644 index 0000000000..2fe98dfbe2 --- /dev/null +++ b/packages/fuselage/src/components/PaletteStyleTag/types/themes.ts @@ -0,0 +1,3 @@ +export type ThemePreference = 'light' | 'dark' | 'auto' | 'high-contrast'; + +export type Themes = 'light' | 'dark' | 'high-contrast'; diff --git a/packages/fuselage/src/components/index.ts b/packages/fuselage/src/components/index.ts index 1ce8f5372d..0681cbb9f5 100644 --- a/packages/fuselage/src/components/index.ts +++ b/packages/fuselage/src/components/index.ts @@ -44,6 +44,7 @@ export * from './Options'; export { default as Option } from './Option'; export * from './Option'; export * from './Pagination'; +export * from './PaletteStyleTag'; export { default as PasswordInput } from './PasswordInput'; export * from './StatusBullet'; export { default as Position } from './Position';