From eecf02d1458b70de1ed26cd6cba629698bf7ee7a Mon Sep 17 00:00:00 2001 From: faga Date: Wed, 19 Oct 2022 14:56:07 +0800 Subject: [PATCH 01/12] feat: backgroundPresets add contrast color --- packages/histoire-app/src/app/App.vue | 6 ++++++ packages/histoire-app/src/app/util/contrastColor.ts | 7 +++++++ packages/histoire-shared/src/types/config.ts | 1 + packages/histoire/src/node/config.ts | 5 +++++ 4 files changed, 19 insertions(+) create mode 100644 packages/histoire-app/src/app/util/contrastColor.ts diff --git a/packages/histoire-app/src/app/App.vue b/packages/histoire-app/src/app/App.vue index 50778627..95ff51c4 100644 --- a/packages/histoire-app/src/app/App.vue +++ b/packages/histoire-app/src/app/App.vue @@ -22,6 +22,8 @@ import Breadcrumb from './components/app/Breadcrumb.vue' import SearchModal from './components/search/SearchModal.vue' import InitialLoading from './components/app/InitialLoading.vue' import GenericMountStory from './components/story/GenericMountStory.vue' +import { usePreviewSettingsStore } from './stores/preview-settings' +import { setContrastColor } from './util/contrastColor' const files = ref(rawFiles.map(file => mapFile(file))) const tree = ref(rawTree) @@ -40,6 +42,10 @@ const stories = computed(() => files.value.reduce((acc, file) => { return acc }, [])) +// contrast color +const settings = usePreviewSettingsStore().currentSettings +watch(settings, () => setContrastColor(settings), { immediate: true }) + // Store const storyStore = useStoryStore() diff --git a/packages/histoire-app/src/app/util/contrastColor.ts b/packages/histoire-app/src/app/util/contrastColor.ts new file mode 100644 index 00000000..09861816 --- /dev/null +++ b/packages/histoire-app/src/app/util/contrastColor.ts @@ -0,0 +1,7 @@ +import { histoireConfig } from './config' +import type { PreviewSettings } from '../types' + +export function setContrastColor (setting: PreviewSettings) { + const contrastColor = histoireConfig.backgroundPresets.find(preset => preset.color === setting.backgroundColor)?.contrastColor + document.documentElement.style.setProperty('--contrast-text-color', contrastColor) +} diff --git a/packages/histoire-shared/src/types/config.ts b/packages/histoire-shared/src/types/config.ts index 3661bf34..6d52eaed 100644 --- a/packages/histoire-shared/src/types/config.ts +++ b/packages/histoire-shared/src/types/config.ts @@ -25,6 +25,7 @@ export interface ResponsivePreset { export interface BackgroundPreset { label: string color: string + contrastColor?: string } export interface TreeGroupConfig { diff --git a/packages/histoire/src/node/config.ts b/packages/histoire/src/node/config.ts index 8546ffbb..74f148ff 100644 --- a/packages/histoire/src/node/config.ts +++ b/packages/histoire/src/node/config.ts @@ -93,22 +93,27 @@ export function getDefaultConfig (): HistoireConfig { { label: 'Transparent', color: 'transparent', + contrastColor: '#333', }, { label: 'White', color: '#fff', + contrastColor: '#333', }, { label: 'Light gray', color: '#aaa', + contrastColor: '#eee', }, { label: 'Dark gray', color: '#333', + contrastColor: '#ccc', }, { label: 'Black', color: '#000', + contrastColor: '#fff', }, ], sandboxDarkClass: 'dark', From 62a6520491e013633a14ee946adc6473e3fd3510 Mon Sep 17 00:00:00 2001 From: faga Date: Wed, 19 Oct 2022 19:49:50 +0800 Subject: [PATCH 02/12] docs: update docs --- docs/reference/config.md | 7 +++++++ packages/histoire-app/src/app/util/contrastColor.ts | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/reference/config.md b/docs/reference/config.md index 6dc3fe41..34fcc5a3 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -252,6 +252,7 @@ Each object in the array is a preset with the following properties: - `label: string`: Label for the preset. - `color: string`: Color of the preset. +- `contrastColor?: string`: Contrast color of preset Default values are shown in the example below: @@ -261,26 +262,32 @@ export default defineConfig({ { label: 'Transparent', color: 'transparent', + contrastColor: '#333' }, { label: 'White', color: '#fff', + contrastColor: '#333' }, { label: 'Light gray', color: '#aaa', + contrastColor: '#eee' }, { label: 'Dark gray', color: '#333', + contrastColor: '#ccc' }, { label: 'Black', color: '#000', + contrastColor: '#fff' }, ], }) ``` +You can use current contrast color via the css variable `--contrast-color`. ## `sandboxDarkClass` diff --git a/packages/histoire-app/src/app/util/contrastColor.ts b/packages/histoire-app/src/app/util/contrastColor.ts index 09861816..bdaeb8da 100644 --- a/packages/histoire-app/src/app/util/contrastColor.ts +++ b/packages/histoire-app/src/app/util/contrastColor.ts @@ -3,5 +3,5 @@ import type { PreviewSettings } from '../types' export function setContrastColor (setting: PreviewSettings) { const contrastColor = histoireConfig.backgroundPresets.find(preset => preset.color === setting.backgroundColor)?.contrastColor - document.documentElement.style.setProperty('--contrast-text-color', contrastColor) + document.documentElement.style.setProperty('--contrast-color', contrastColor) } From 9f015a2b6db21a20e5de9d0528b2f0213d9f2417 Mon Sep 17 00:00:00 2001 From: faga Date: Wed, 19 Oct 2022 22:29:09 +0800 Subject: [PATCH 03/12] chore: add examples --- examples/vue3/src/components/ComplexParameter.vue | 6 ++++++ .../vue3/src/components/ContrastColor.story.vue | 14 ++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 examples/vue3/src/components/ContrastColor.story.vue diff --git a/examples/vue3/src/components/ComplexParameter.vue b/examples/vue3/src/components/ComplexParameter.vue index e261054b..dc0330a2 100644 --- a/examples/vue3/src/components/ComplexParameter.vue +++ b/examples/vue3/src/components/ComplexParameter.vue @@ -18,3 +18,9 @@ const props = defineProps<{ {{ recursiveParameter.name }} + + diff --git a/examples/vue3/src/components/ContrastColor.story.vue b/examples/vue3/src/components/ContrastColor.story.vue new file mode 100644 index 00000000..b032bf0a --- /dev/null +++ b/examples/vue3/src/components/ContrastColor.story.vue @@ -0,0 +1,14 @@ + + + + + From 4261f32e0c90d7281de52ea1b274e446203d9743 Mon Sep 17 00:00:00 2001 From: faga Date: Wed, 19 Oct 2022 22:29:46 +0800 Subject: [PATCH 04/12] feat: contrast color support iframe --- packages/histoire-app/src/app/App.vue | 6 ++---- .../story/StoryVariantSinglePreviewRemote.vue | 3 ++- .../histoire-app/src/app/util/contrastColor.ts | 17 ++++++++++++++--- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/histoire-app/src/app/App.vue b/packages/histoire-app/src/app/App.vue index 95ff51c4..f0271a40 100644 --- a/packages/histoire-app/src/app/App.vue +++ b/packages/histoire-app/src/app/App.vue @@ -22,8 +22,7 @@ import Breadcrumb from './components/app/Breadcrumb.vue' import SearchModal from './components/search/SearchModal.vue' import InitialLoading from './components/app/InitialLoading.vue' import GenericMountStory from './components/story/GenericMountStory.vue' -import { usePreviewSettingsStore } from './stores/preview-settings' -import { setContrastColor } from './util/contrastColor' +import { useContrastColor } from './util/contrastColor' const files = ref(rawFiles.map(file => mapFile(file))) const tree = ref(rawTree) @@ -43,8 +42,7 @@ const stories = computed(() => files.value.reduce((acc, file) => { }, [])) // contrast color -const settings = usePreviewSettingsStore().currentSettings -watch(settings, () => setContrastColor(settings), { immediate: true }) +useContrastColor(document.documentElement) // Store diff --git a/packages/histoire-app/src/app/components/story/StoryVariantSinglePreviewRemote.vue b/packages/histoire-app/src/app/components/story/StoryVariantSinglePreviewRemote.vue index 91cb22d0..46837a1f 100644 --- a/packages/histoire-app/src/app/components/story/StoryVariantSinglePreviewRemote.vue +++ b/packages/histoire-app/src/app/components/story/StoryVariantSinglePreviewRemote.vue @@ -9,6 +9,7 @@ import { usePreviewSettingsStore } from '../../stores/preview-settings' import { HstEvent, useEventsStore } from '../../stores/events' import StoryResponsivePreview from './StoryResponsivePreview.vue' import { toRawDeep } from '../../util/state' +import { useContrastColor } from '../../util/contrastColor' const props = defineProps<{ story: Story @@ -29,7 +30,6 @@ function syncState () { }) } } - let synced = false watch(() => props.variant.state, () => { @@ -114,6 +114,7 @@ function onIframeLoad () { isIframeLoaded.value = true syncState() syncSettings() + useContrastColor(iframe.value.contentDocument.documentElement) } diff --git a/packages/histoire-app/src/app/util/contrastColor.ts b/packages/histoire-app/src/app/util/contrastColor.ts index bdaeb8da..14d1a35b 100644 --- a/packages/histoire-app/src/app/util/contrastColor.ts +++ b/packages/histoire-app/src/app/util/contrastColor.ts @@ -1,7 +1,18 @@ import { histoireConfig } from './config' +import { usePreviewSettingsStore } from '../stores/preview-settings' +import { watch } from 'vue' import type { PreviewSettings } from '../types' -export function setContrastColor (setting: PreviewSettings) { - const contrastColor = histoireConfig.backgroundPresets.find(preset => preset.color === setting.backgroundColor)?.contrastColor - document.documentElement.style.setProperty('--contrast-color', contrastColor) +export function useContrastColor (element: HTMLElement) { + const setting = usePreviewSettingsStore().currentSettings + watch(setting, () => setContrastColor(setting, element), { immediate: true }) +} + +function setContrastColor (setting: PreviewSettings, element: HTMLElement) { + const contrastColor = getContrastColor(setting) + element.style.setProperty('--contrast-color', contrastColor) +} + +function getContrastColor (setting: PreviewSettings) { + return histoireConfig.backgroundPresets.find(preset => preset.color === setting.backgroundColor)?.contrastColor } From 06643068eb419f27fd6a38e2c8ee6b5af3b85a02 Mon Sep 17 00:00:00 2001 From: faga Date: Thu, 20 Oct 2022 14:44:06 +0800 Subject: [PATCH 05/12] test: contrast color cypress test --- .../cypress/integration/contrast-color.js | 36 +++++++++++++++++++ .../vue3/cypress/integration/stories-list.js | 2 +- examples/vue3/histoire.config.ts | 10 +++++- .../components/toolbar/ToolbarBackground.vue | 6 +++- 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 examples/vue3/cypress/integration/contrast-color.js diff --git a/examples/vue3/cypress/integration/contrast-color.js b/examples/vue3/cypress/integration/contrast-color.js new file mode 100644 index 00000000..67828673 --- /dev/null +++ b/examples/vue3/cypress/integration/contrast-color.js @@ -0,0 +1,36 @@ +/// + +describe('contrast color', () => { + const getIframeBody = () => cy.get('iframe[data-test-id="preview-iframe"]') + .its('0.contentDocument.body').should('not.be.empty') + .then(cy.wrap) + + const colorShouldBe = [ + 'rgb(51, 51, 51)', + 'rgb(51, 51, 51)', + 'rgb(238, 238, 238)', + 'rgb(204, 204, 204)', + 'rgb(255, 255, 255)', + 'rgb(255, 255, 255)', + ] + + it('should provide contrast color (no iframe)', () => { + cy.visit('/story/src-components-complexparameter-story-vue?variantId=_default') + cy.get('[data-test-id="toolbar-background"]').click() + cy.get('[data-test-id="background-popper"]').should('be.visible').find('button').should('have.length', 6).each(($el, index) => { + cy.wrap($el).click() + cy.get('[data-test-id="story-variant-single-view"] .native-story').should('have.css', 'color', colorShouldBe[index]) + cy.get('[data-test-id="toolbar-background"]').click() + }) + }) + + it('should provide contrast color(with iframe)', () => { + cy.visit('story/src-components-contrastcolor-story-vue?variantId=_default') + cy.get('[data-test-id="toolbar-background"]').click() + cy.get('[data-test-id="background-popper"]').should('be.visible').find('button').should('have.length', 6).each(($el, index) => { + cy.wrap($el).click() + getIframeBody().find('.contrast-color').should('have.css', 'color', colorShouldBe[index]) + cy.get('[data-test-id="toolbar-background"]').click() + }) + }) +}) diff --git a/examples/vue3/cypress/integration/stories-list.js b/examples/vue3/cypress/integration/stories-list.js index b79aa44d..a6acb601 100644 --- a/examples/vue3/cypress/integration/stories-list.js +++ b/examples/vue3/cypress/integration/stories-list.js @@ -4,7 +4,7 @@ describe('Stories list', () => { it('should display the stories', () => { cy.clearLocalStorage() cy.visit('/') - cy.get('[data-test-id="story-list-item"]').should('have.length', 26) + cy.get('[data-test-id="story-list-item"]').should('have.length', 27) cy.get('[data-test-id="story-list-item"]').contains('🐱 Meow') cy.get('[data-test-id="story-list-item"]').contains('BaseButton') .contains('3') // Variants count diff --git a/examples/vue3/histoire.config.ts b/examples/vue3/histoire.config.ts index a9fed307..b5d97e69 100644 --- a/examples/vue3/histoire.config.ts +++ b/examples/vue3/histoire.config.ts @@ -1,4 +1,4 @@ -import { defineConfig } from 'histoire' +import { defineConfig, getDefaultConfig } from 'histoire' import { HstVue } from '@histoire/plugin-vue' export default defineConfig({ @@ -6,4 +6,12 @@ export default defineConfig({ plugins: [ HstVue(), ], + backgroundPresets: [ + ...(getDefaultConfig().backgroundPresets || []), + { + label: 'Custom gray', + color: '#bbb', + contrastColor: '#fff', + }, + ], }) diff --git a/packages/histoire-app/src/app/components/toolbar/ToolbarBackground.vue b/packages/histoire-app/src/app/components/toolbar/ToolbarBackground.vue index 8c137e37..6286d349 100644 --- a/packages/histoire-app/src/app/components/toolbar/ToolbarBackground.vue +++ b/packages/histoire-app/src/app/components/toolbar/ToolbarBackground.vue @@ -13,6 +13,7 @@ const settings = usePreviewSettingsStore().currentSettings placement="bottom-end" :skidding="6" class="htw-h-full htw-flex-none" + data-test-id="toolbar-background" >