From c792eb0d082bf4dd14fafc138499ec2bdc278bcd Mon Sep 17 00:00:00 2001 From: Benedikt Kulmann Date: Thu, 23 Mar 2023 00:00:57 +0100 Subject: [PATCH] [full-ci] feat: introduce contrast colors in swatches (#8563) --- changelog/unreleased/change-theme-colors | 7 + docker-compose.yml | 1 + docs/theming/_index.md | 14 ++ .../change-remove-inverse-variation | 6 + .../unreleased/enhancement-contrast-token | 5 + .../docs/components/tokens/IconList.vue | 18 --- .../src/components/OcButton/OcButton.vue | 130 +++++++++--------- .../src/components/OcCheckbox/OcCheckbox.vue | 10 +- .../src/components/OcIcon/OcIcon.vue | 18 +-- .../src/components/OcInfoDrop/OcInfoDrop.vue | 7 +- .../src/components/OcModal/OcModal.vue | 2 +- .../components/OcSearchBar/OcSearchBar.vue | 17 ++- .../OcStatusIndicators/OcStatusIndicators.vue | 6 +- .../src/styles/theme/oc-form.scss | 2 +- .../design-system/src/tokens/ods/color.yaml | 16 +++ .../components/AppBar/SharesNavigation.vue | 4 +- .../src/components/AppBar/ViewOptions.vue | 7 +- .../components/FilesList/ResourceTable.vue | 4 +- .../components/FilesList/ResourceTiles.vue | 2 +- .../Shares/Collaborators/RoleDropdown.vue | 28 +--- .../SideBar/Shares/Links/DetailsAndEdit.vue | 32 ++--- .../SharesNavigation.spec.ts.snap | 2 +- .../__snapshots__/RoleDropdown.spec.ts.snap | 40 +++--- .../__snapshots__/DetailsAndEdit.spec.ts.snap | 10 +- .../__snapshots__/SpaceMembers.spec.ts.snap | 6 +- packages/web-app-preview/src/App.vue | 26 ++-- .../web-app-search/src/portals/SearchBar.vue | 7 +- packages/web-client/src/helpers/share/role.ts | 4 +- .../web-pkg/src/components/ItemFilter.vue | 6 - .../src/components/LoadingIndicator.vue | 2 +- .../src/components/SidebarNav/SidebarNav.vue | 2 +- .../components/SidebarNav/SidebarNavItem.vue | 6 +- .../components/Topbar/ApplicationsMenu.vue | 34 +++-- .../src/components/Topbar/FeedbackLink.vue | 4 +- .../components/Topbar/NotificationBell.vue | 4 +- .../src/components/Topbar/ThemeSwitcher.vue | 6 +- .../web-runtime/src/components/UploadInfo.vue | 6 +- .../ApplicationsMenu.spec.ts.snap | 6 +- .../NotificationBell.spec.ts.snap | 2 +- .../__snapshots__/ThemeSwitcher.spec.ts.snap | 24 ++-- .../web-runtime/themes/owncloud/theme.json | 16 ++- 41 files changed, 282 insertions(+), 267 deletions(-) create mode 100644 changelog/unreleased/change-theme-colors create mode 100644 packages/design-system/changelog/unreleased/change-remove-inverse-variation create mode 100644 packages/design-system/changelog/unreleased/enhancement-contrast-token diff --git a/changelog/unreleased/change-theme-colors b/changelog/unreleased/change-theme-colors new file mode 100644 index 00000000000..2701f023ca8 --- /dev/null +++ b/changelog/unreleased/change-theme-colors @@ -0,0 +1,7 @@ +Change: theme colors + +We've introduced `contrast` color variables for all the color swatches in the design system. As a result the `contrast` color variable needs to be added to all existing web themes. + +BREAKING CHANGE for non-default themes in existing deployments: You need to add the `contrast` color variable to all swatches in your theme. A good default is the `color-text-inverse` value. You can find an example here: https://owncloud.dev/clients/web/theming/#example-theme + +https://github.com/owncloud/web/pull/8563 diff --git a/docker-compose.yml b/docker-compose.yml index 5dabc622b7b..e8315db41f5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,6 +22,7 @@ services: # WEB WEB_UI_CONFIG: ${WEB_UI_CONFIG:-/web/config.json} WEB_ASSET_PATH: ${WEB_ASSET_PATH:-/web/dist} + WEB_UI_THEME_PATH: ${WEB_UI_THEME_PATH:-/themes/owncloud/theme.json} #FRONTEND FRONTEND_SEARCH_MIN_LENGTH: "2" diff --git a/docs/theming/_index.md b/docs/theming/_index.md index 281ad127e75..e15b5a68d8b 100644 --- a/docs/theming/_index.md +++ b/docs/theming/_index.md @@ -156,25 +156,32 @@ Again, you can use the [ownCloud design tokens](https://owncloud.design/#/Design "input-text-muted": "", "swatch-brand-default": "", "swatch-brand-hover": "", + "swatch-brand-muted": "", + "swatch-brand-contrast": "", "swatch-danger-default": "", "swatch-danger-hover": "", "swatch-danger-muted": "", + "swatch-danger-contrast": "", "swatch-inverse-default": "", "swatch-inverse-hover": "", "swatch-inverse-muted": "", "swatch-passive-default": "", "swatch-passive-hover": "", "swatch-passive-muted": "", + "swatch-passive-contrast": "", "swatch-primary-default": "", "swatch-primary-hover": "", "swatch-primary-muted": "", "swatch-primary-gradient": "", + "swatch-primary-contrast": "", "swatch-success-default": "", "swatch-success-hover": "", "swatch-success-muted": "", + "swatch-success-contrast": "", "swatch-warning-default": "", "swatch-warning-hover": "", "swatch-warning-muted": "", + "swatch-warning-contrast": "", "text-default": "", "text-inverse": "", "text-muted": "" @@ -288,25 +295,32 @@ An empty template for your custom theme is provided below, and you can use the i "input-text-muted": "", "swatch-brand-default": "", "swatch-brand-hover": "", + "swatch-brand-muted": "", + "swatch-brand-contrast": "", "swatch-danger-default": "", "swatch-danger-hover": "", "swatch-danger-muted": "", + "swatch-danger-contrast": "", "swatch-inverse-default": "", "swatch-inverse-hover": "", "swatch-inverse-muted": "", "swatch-passive-default": "", "swatch-passive-hover": "", "swatch-passive-muted": "", + "swatch-passive-contrast": "", "swatch-primary-default": "", "swatch-primary-hover": "", "swatch-primary-muted": "", "swatch-primary-gradient": "", + "swatch-primary-contrast": "", "swatch-success-default": "", "swatch-success-hover": "", "swatch-success-muted": "", + "swatch-success-contrast": "", "swatch-warning-default": "", "swatch-warning-hover": "", "swatch-warning-muted": "", + "swatch-warning-contrast": "", "text-default": "", "text-inverse": "", "text-muted": "" diff --git a/packages/design-system/changelog/unreleased/change-remove-inverse-variation b/packages/design-system/changelog/unreleased/change-remove-inverse-variation new file mode 100644 index 00000000000..c13c7c27cc0 --- /dev/null +++ b/packages/design-system/changelog/unreleased/change-remove-inverse-variation @@ -0,0 +1,6 @@ +Change: "inverse" variation removed from buttons and icons + +The "inverse" variation has been removed from the `OcButton` and `OcIcon` components respectively. They are unused in the ownCloud affiliated code bases, hence the clean up. +For `OcButton` there is a new `raw-inverse` variation which utilizes the new `contrast` color swatch token of the chosen variation. + +https://github.com/owncloud/web/pull/8563 diff --git a/packages/design-system/changelog/unreleased/enhancement-contrast-token b/packages/design-system/changelog/unreleased/enhancement-contrast-token new file mode 100644 index 00000000000..5e685c3f8da --- /dev/null +++ b/packages/design-system/changelog/unreleased/enhancement-contrast-token @@ -0,0 +1,5 @@ +Enhancement: Contrast token in swatches + +We've added a `contrast` token to each of our color swatches. Its purpose is to provide a high contrast color in comparison to the `default` token of the color swatch. + +https://github.com/owncloud/web/pull/8563 diff --git a/packages/design-system/docs/components/tokens/IconList.vue b/packages/design-system/docs/components/tokens/IconList.vue index dbcc08cc4fe..f72e401dd07 100644 --- a/packages/design-system/docs/components/tokens/IconList.vue +++ b/packages/design-system/docs/components/tokens/IconList.vue @@ -46,19 +46,6 @@ - @@ -126,11 +113,6 @@ export default defineComponent({ title: 'Danger', type: 'slot' }, - { - name: 'inverse', - title: 'Inverse', - type: 'slot' - }, { name: 'fillType', title: 'Fill type' diff --git a/packages/design-system/src/components/OcButton/OcButton.vue b/packages/design-system/src/components/OcButton/OcButton.vue index 50f5e76e7f6..a1458bfab93 100644 --- a/packages/design-system/src/components/OcButton/OcButton.vue +++ b/packages/design-system/src/components/OcButton/OcButton.vue @@ -95,25 +95,29 @@ export default defineComponent({ /** * Style variation to give additional meaning. * Defaults to `primary`. - * Can be `passive, primary, danger, success, warning`. + * Can be `passive, primary, danger, success, warning, brand`. */ variation: { type: String, default: 'passive', validator: (value: string) => { - return ['passive', 'primary', 'danger', 'success', 'warning', 'inverse'].includes(value) + return ['passive', 'primary', 'danger', 'success', 'warning', 'brand'].includes(value) } }, /** * Style variation to give additional meaning. * Defaults to `outline`. - * Can be `outline, filled, raw`. + * Can be `outline, filled, raw, raw-inverse` with following characteristics: + * - outline: transparent button with text- and border-color according to variation default-color + * - filled: button filled in variation default-color, text in variation contrast-color + * - raw: text-only button with text in variation default-color + * - raw-inverse: text-only button with text in variation contrast-color */ appearance: { type: String, default: 'outline', validator: (value: string) => { - return ['filled', 'outline', 'raw'].includes(value) + return ['filled', 'outline', 'raw', 'raw-inverse'].includes(value) } }, /** @@ -193,9 +197,7 @@ export default defineComponent({ line-height: $oc-size-icon-default * $factor; } -@mixin oc-button-variation($color, $hover-color, $muted-color) { - background-color: $color; - +@mixin oc-button-variation($color, $hover-color, $muted-color, $contrast-color) { &:disabled { background-color: $muted-color; } @@ -205,32 +207,51 @@ export default defineComponent({ background-color: $hover-color; } - &-raw { + &-raw, + &-raw-inverse { background-color: transparent; border-style: none; - color: $color; font-size: var(--oc-font-size-medium); font-weight: normal; min-height: 0; padding: 0; - .oc-icon > svg { - fill: $color; + &:focus:not([disabled]), + &:hover:not([disabled]) { + background-color: transparent; + } + + &:focus:not([disabled]):not(button), + &:hover:not([disabled]):not(button) { + text-decoration: underline; } &:disabled { background-color: transparent; color: $muted-color; } + } + &-raw { + color: $color; - &:focus:not([disabled]), - &:hover:not([disabled]) { - background-color: transparent; + .oc-icon > svg { + fill: $color; } + } + &-raw-inverse { + color: $contrast-color; - &:focus:not([disabled]):not(button), - &:hover:not([disabled]):not(button) { - text-decoration: underline; + .oc-icon > svg { + fill: $contrast-color; + } + } + + &-filled { + background-color: $color; + color: $contrast-color; + + .oc-icon > svg { + fill: $contrast-color; } } @@ -252,12 +273,12 @@ export default defineComponent({ &-outline:hover:not([disabled]), &-outline:focus:not([disabled]) { - color: var(--oc-color-text-inverse); + color: $contrast-color; background-color: $color; border-color: $color; .oc-icon > svg { - fill: var(--oc-color-text-inverse); + fill: $contrast-color; } } } @@ -268,7 +289,6 @@ export default defineComponent({ align-items: center; border: 0; box-sizing: border-box; - color: var(--oc-color-text-inverse); display: inline-flex; font-weight: 400; padding: 0.5rem 0.8rem; @@ -348,15 +368,21 @@ export default defineComponent({ min-height: 2rem; } - .oc-icon > svg { - fill: var(--oc-color-text-inverse); - } - &-passive { @include oc-button-variation( var(--oc-color-swatch-passive-default), var(--oc-color-swatch-passive-hover), - var(--oc-color-swatch-passive-muted) + var(--oc-color-swatch-passive-muted), + var(--oc-color-swatch-passive-contrast) + ); + } + + &-brand { + @include oc-button-variation( + var(--oc-color-swatch-brand-default), + var(--oc-color-swatch-brand-hover), + var(--oc-color-swatch-brand-muted), + var(--oc-color-swatch-brand-contrast) ); } @@ -364,14 +390,15 @@ export default defineComponent({ @include oc-button-variation( var(--oc-color-swatch-primary-default), var(--oc-color-swatch-primary-hover), - var(--oc-color-swatch-primary-muted) + var(--oc-color-swatch-primary-muted), + var(--oc-color-swatch-primary-contrast) ); &-filled { @include oc-background-primary-gradient; - color: var(--oc-color-swatch-inverse-default) !important; + color: var(--oc-color-swatch-primary-contrast) !important; span > svg { - fill: var(--oc-color-swatch-inverse-default) !important; + fill: var(--oc-color-swatch-primary-contrast) !important; } } } @@ -380,7 +407,8 @@ export default defineComponent({ @include oc-button-variation( var(--oc-color-swatch-success-default), var(--oc-color-swatch-success-hover), - var(--oc-color-swatch-success-muted) + var(--oc-color-swatch-success-muted), + var(--oc-color-swatch-success-contrast) ); } @@ -388,7 +416,8 @@ export default defineComponent({ @include oc-button-variation( var(--oc-color-swatch-warning-default), var(--oc-color-swatch-warning-hover), - var(--oc-color-swatch-warning-muted) + var(--oc-color-swatch-warning-muted), + var(--oc-color-swatch-warning-contrast) ); } @@ -396,39 +425,9 @@ export default defineComponent({ @include oc-button-variation( var(--oc-color-swatch-danger-default), var(--oc-color-swatch-danger-hover), - var(--oc-color-swatch-danger-muted) - ); - } - - &-inverse { - @include oc-button-variation( - var(--oc-color-swatch-inverse-default), - var(--oc-color-swatch-inverse-hover), - var(--oc-color-swatch-inverse-muted) + var(--oc-color-swatch-danger-muted), + var(--oc-color-swatch-danger-contrast) ); - - &:not([disabled]) { - color: var(--oc-color-swatch-brand-default); - .oc-icon-passive > svg { - fill: var(--oc-color-swatch-brand-default); - } - } - - &-outline:not([disabled]), - &-raw:not([disabled]) { - color: var(--oc-color-swatch-inverse-default); - .oc-icon-passive > svg { - fill: var(--oc-color-swatch-inverse-default); - } - } - - &-outline:hover:not([disabled]), - &-outline:focus:not([disabled]) { - color: var(--oc-color-swatch-brand-default); - .oc-icon-passive > svg { - fill: var(--oc-color-swatch-brand-default); - } - } } &:disabled { @@ -611,10 +610,6 @@ export default { { title: "danger", description: "Use for triggering possible destructive and non-reversible actions, like permanently deleting a file" - }, - { - title: "inverse", - description: "Use on a dark background" } ] }, @@ -622,7 +617,8 @@ export default { return [ "outline", "filled", - "raw" + "raw", + "raw-inverse" ] }, }, diff --git a/packages/design-system/src/components/OcCheckbox/OcCheckbox.vue b/packages/design-system/src/components/OcCheckbox/OcCheckbox.vue index 77248c8af35..4affe6029e3 100644 --- a/packages/design-system/src/components/OcCheckbox/OcCheckbox.vue +++ b/packages/design-system/src/components/OcCheckbox/OcCheckbox.vue @@ -179,20 +179,16 @@ export default defineComponent({ &-checked, :checked, &:indeterminate { - background-color: var(--oc-color-swatch-inverse-default); + background-color: white; } &-checked, :checked { - @include svg-fill($internal-form-checkbox-image, '#000', $form-radio-checked-icon-color); + @include svg-fill($internal-form-checkbox-image, '#000', '#000'); } &:indeterminate { - @include svg-fill( - $internal-form-checkbox-indeterminate-image, - '#000', - $form-radio-checked-icon-color - ); + @include svg-fill($internal-form-checkbox-indeterminate-image, '#000', '#000'); } &:disabled { diff --git a/packages/design-system/src/components/OcIcon/OcIcon.vue b/packages/design-system/src/components/OcIcon/OcIcon.vue index 7da50cc563e..46a4e948663 100644 --- a/packages/design-system/src/components/OcIcon/OcIcon.vue +++ b/packages/design-system/src/components/OcIcon/OcIcon.vue @@ -133,14 +133,17 @@ export default defineComponent({ /** * Style variation to give additional meaning. * Defaults to `passive`. - * Can be `passive, primary, danger, success, warning or inverse`. - * Inverse is meant to be used for icons on a colorful background. + * Can be `passive, primary, danger, success, warning, brand or inherit`. + * `inherit` will not set any color but instead rely on a container element already + * setting the icon fill. */ variation: { type: String, default: 'passive', validator: (value: string) => { - return ['passive', 'primary', 'danger', 'success', 'warning', 'inverse'].includes(value) + return ['passive', 'primary', 'danger', 'success', 'warning', 'brand', 'inherit'].includes( + value + ) } }, /** @@ -205,7 +208,6 @@ export default defineComponent({ svg { display: block; - fill: var(--oc-color-swatch-passive-default); } &, @@ -282,8 +284,8 @@ export default defineComponent({ fill: var(--oc-color-swatch-danger-default); } - &-inverse > svg { - fill: var(--oc-color-text-inverse) !important; + &-brand > svg { + fill: var(--oc-color-swatch-brand-default); } } @@ -318,7 +320,7 @@ export default defineComponent({ {{ variation.name }} - + @@ -379,7 +381,7 @@ export default defineComponent({ name: "warning", }, { id: "2324-8956-9042", - name: "inverse", + name: "brand", }] }, sizes() { diff --git a/packages/design-system/src/components/OcInfoDrop/OcInfoDrop.vue b/packages/design-system/src/components/OcInfoDrop/OcInfoDrop.vue index 07317b9f93d..3d7ea9745f7 100644 --- a/packages/design-system/src/components/OcInfoDrop/OcInfoDrop.vue +++ b/packages/design-system/src/components/OcInfoDrop/OcInfoDrop.vue @@ -11,7 +11,7 @@
- +

@@ -26,15 +26,14 @@

Read more + v-text="$gettext('Read more')" + /> diff --git a/packages/design-system/src/components/OcModal/OcModal.vue b/packages/design-system/src/components/OcModal/OcModal.vue index 9c0816f1d47..38d1bff2522 100644 --- a/packages/design-system/src/components/OcModal/OcModal.vue +++ b/packages/design-system/src/components/OcModal/OcModal.vue @@ -464,7 +464,7 @@ export default defineComponent({ } > h2 { - color: var(--oc-color-swatch-inverse-default); + color: var(--oc-color-swatch-brand-contrast); font-size: 1rem; font-weight: bold; margin: 0; diff --git a/packages/design-system/src/components/OcSearchBar/OcSearchBar.vue b/packages/design-system/src/components/OcSearchBar/OcSearchBar.vue index b1040e5b24f..61eaa2475d6 100644 --- a/packages/design-system/src/components/OcSearchBar/OcSearchBar.vue +++ b/packages/design-system/src/components/OcSearchBar/OcSearchBar.vue @@ -50,8 +50,8 @@ @@ -203,7 +203,18 @@ export default defineComponent({ required: false, default: 'primary', validator: (value: string) => { - return ['passive', 'primary', 'danger', 'success', 'warning', 'inverse'].includes(value) + return ['passive', 'primary', 'danger', 'success', 'warning', 'brand'].includes(value) + } + }, + /** + * Appearance of the cancel button + */ + cancelButtonAppearance: { + type: String, + required: false, + default: 'raw', + validator: (value: string) => { + return ['outline', 'filled', 'raw', 'raw-inverse'].includes(value) } }, /** @@ -294,7 +305,7 @@ export default defineComponent({ &-button { border-bottom-left-radius: 0; border-top-left-radius: 0; - // Prevend double borders + // Prevent double borders // from input and button transform: translateX(-1px); z-index: 0; diff --git a/packages/design-system/src/components/OcStatusIndicators/OcStatusIndicators.vue b/packages/design-system/src/components/OcStatusIndicators/OcStatusIndicators.vue index 36350738654..755bf36c2af 100644 --- a/packages/design-system/src/components/OcStatusIndicators/OcStatusIndicators.vue +++ b/packages/design-system/src/components/OcStatusIndicators/OcStatusIndicators.vue @@ -9,13 +9,13 @@ class="oc-status-indicators-indicator oc-background-primary-gradient oc-p-xs oc-ml-xs" :aria-label="$gettext(indicator.label)" :aria-describedby="getIndicatorDescriptionId(indicator)" - appearance="raw" - variation="inverse" + appearance="raw-inverse" + variation="primary" :data-testid="indicator.id" :data-test-indicator-type="indicator.type" @click="indicator.handler(resource, indicator.target, $router)" > - + diff --git a/packages/web-app-files/src/components/AppBar/ViewOptions.vue b/packages/web-app-files/src/components/AppBar/ViewOptions.vue index 5bee6b5ae52..7f3817bff2e 100644 --- a/packages/web-app-files/src/components/AppBar/ViewOptions.vue +++ b/packages/web-app-files/src/components/AppBar/ViewOptions.vue @@ -13,7 +13,12 @@ :aria-label="$gettext(viewMode.label)" @click="setViewMode(viewMode)" > - +