Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 57 additions & 2 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,59 @@
import type { StorybookConfig } from '@storybook/html-vite';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import remarkGfm from 'remark-gfm';
import type { Plugin } from 'vite';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(__dirname, '..');
const distFolder = path.join(repoRoot, 'dist');

/**
* Dev-bundle fallback for /osui/*.
*
* `preview-head.html` (and the Theme toolbar toggle) load the PRODUCTION file
* names (`ODC.OutSystemsUI.{css,js}`), but `npm run dev -- --target ODC` wipes
* `dist/` and emits only `dev.`-prefixed files. Without this fallback, running
* Storybook against a dev watch build 404s the whole OUI bundle.
*
* When a requested `/osui/<name>` is missing from `dist/` but `dist/dev.<name>`
* exists, serve the dev file instead. Static-dir serving (sirv) falls through
* to the Vite middleware chain on a miss, which is where this plugin runs.
* Dev-server only — `storybook build` copies staticDirs verbatim and expects a
* prior production build, as before.
*/
function osuiDevBundleFallback(): Plugin {
const contentTypes: Record<string, string> = {
'.css': 'text/css',
'.js': 'text/javascript',
'.map': 'application/json',
};
return {
name: 'osui-dev-bundle-fallback',
configureServer(server) {
server.middlewares.use((req, res, next) => {
const url = (req.url ?? '').split('?')[0];
if (!url.startsWith('/osui/')) {
return next();
}
const requested = url.slice('/osui/'.length);
// Only flat file names — no nested paths, no traversal, not already dev-prefixed.
if (requested === '' || /[/\\]/.test(requested) || requested.includes('..') || requested.startsWith('dev.')) {
return next();
}
const prodPath = path.join(distFolder, requested);
const devPath = path.join(distFolder, `dev.${requested}`);
if (fs.existsSync(prodPath) || !fs.existsSync(devPath)) {
return next();
}
res.setHeader('Content-Type', contentTypes[path.extname(requested)] ?? 'application/octet-stream');
res.setHeader('Cache-Control', 'no-store');
fs.createReadStream(devPath).pipe(res);
});
},
};
}

/**
* Storybook for OutSystems UI.
Expand All @@ -17,8 +66,10 @@ const repoRoot = path.resolve(__dirname, '..');
* calls its public `Create(id, configs)` API — exactly what OutSystems Service
* Studio does at runtime, transcribed to high-code.
*
* Prerequisite: run `npm run build:osui` (or `npm run dev -- --target ODC`)
* once so `dist/ODC.OutSystemsUI.{js,css}` exist. They are served from `/osui`.
* Prerequisite: build the library so `dist/` is populated — either `npm run build`
* (production names, `ODC.OutSystemsUI.{js,css}`) or `npm run dev -- --target ODC`
* (dev watch, `dev.`-prefixed names — resolved by the osuiDevBundleFallback plugin
* above). Files are served from `/osui`.
*/
const config: StorybookConfig = {
stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|ts|tsx)'],
Expand Down Expand Up @@ -67,6 +118,10 @@ const config: StorybookConfig = {
{ from: path.join(repoRoot, 'node_modules/@floating-ui/dom/dist'), to: '/vendor/floating-ui-dom' },
{ from: path.join(repoRoot, 'node_modules/virtual-select-plugin/dist'), to: '/vendor/virtual-select' },
],
viteFinal(viteConfig) {
viteConfig.plugins = [...(viteConfig.plugins ?? []), osuiDevBundleFallback()];
return viteConfig;
},
};

export default config;
4 changes: 0 additions & 4 deletions gulp/ProjectSpecs/ScssStructure/Keyframes.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ const sectionInfo = {
"name": "Button Loading",
"path": "07-keyframes/btn-loading"
},
{
"name": "List Item",
"path": "07-keyframes/list-item"
},
{
"name": "Feedback Message",
"path": "07-keyframes/feedback-message"
Expand Down
5 changes: 3 additions & 2 deletions src/scripts/OutSystems/OSUI/Utils/ButtonsEffect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ namespace OutSystems.OSUI.Utils {
return;
}

const foundElement =
_hasSomeParentTheClass(target, 'list-item') || _hasSomeParentTheClass(target, 'bottom-bar-item');
// 'list-item' is intentionally not handled here: the List Item click feedback is now a
// pure CSS `:active` background (see src/scss/03-widgets/_list-item.scss).
const foundElement = _hasSomeParentTheClass(target, 'bottom-bar-item');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OS-giulianasilva this way we will impact the old theme.

We either keep this code running always and try to nulify the animation on CSS, or talk with @jessicamendesOS to understand if we can bring the change to the old theme as well (using similar raw values for the active style)


if (foundElement) {
_clickEffect(foundElement);
Expand Down
2 changes: 1 addition & 1 deletion src/scss/01-foundations/_root.scss
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
--osui-motion-duration-130: 130ms; // future: --token-transition-time-130
--osui-motion-duration-180: 180ms; // future: --token-transition-time-180
--osui-motion-duration-400: 400ms; // future: --token-transition-time-400
--osui-bg-surface-hover: #{variables.$token-primitives-neutral-100}; // future: --token-bg-surface-hover (#f3f3f3)
--osui-bg-surface-hover: #{variables.$token-bg-neutral-subtlest-hover};
--osui-bg-surface-active: color-mix(
in srgb,
#{variables.$token-semantics-primary-base} 8%,
Expand Down
55 changes: 18 additions & 37 deletions src/scss/03-widgets/_list-item.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,48 +11,31 @@
--osui-list-item-border-color: var(--color-border);
--osui-list-item-background: var(--color-background-surface);
--osui-list-item-hover-background: var(--osui-bg-surface-hover);
--osui-list-item-selected-background: var(--color-primary-selected);
--osui-list-item-active-background: #{variables.$token-bg-neutral-subtlest-press};
--osui-list-item-selected-background: var(--osui-list-item-background);
--osui-list-item-selected-icon-color: #{variables.$token-icon-select};
// ───────────────────────────────────────────────────────────────────

border-bottom: variables.$token-border-size-025 solid var(--osui-list-item-border-color);
overflow: hidden;
padding: variables.$token-scale-300 variables.$token-scale-600;
padding: variables.$token-space-300 variables.$token-space-600;
position: relative;
transition: background-color variables.$token-transition-time-100 variables.$token-transition-curve-base;

&:last-of-type {
border-bottom: none;
}

&.list-item-no-click-effect {
.scale-animation {
// !important should be in use in order to grant the expected behaviour when this class is assigned!
background: transparent !important;
opacity: 0 !important;
}
}

.scale-animation {
animation: list-item-scale-animation variables.$token-transition-time-1500;
background-color: color-mix(in srgb, var(--color-text) 10%, transparent);
border-radius: var(--border-radius-rounded);
display: block;
height: 10px; // design-spec: fixed ripple size
left: 50%;
pointer-events: none;
position: absolute;
top: 50%;
width: 10px; // design-spec: fixed ripple size
will-change: transform;
z-index: var(--layer-screen);
}
}

///
.list {
.list-item {
background-color: var(--osui-list-item-background);
cursor: pointer;

// Pressed state, on every device — replaces the legacy ripple animation.
&:active {
background-color: var(--osui-list-item-active-background);
}
}
}

Expand All @@ -68,7 +51,8 @@
.desktop {
.list {
.list-item:hover {
&:not(.list-item-no-hover):not(.list-item-selected) {
// `:not(:active)` keeps this higher-specificity rule from masking the pressed state.
&:not(.list-item-no-hover):not(.list-item-selected):not(:active) {
background-color: var(--osui-list-item-hover-background);
}
}
Expand All @@ -80,19 +64,16 @@
.tablet.landscape {
.list {
.list-item-selected {
background-color: color-mix(in srgb, #{variables.$token-semantics-primary-base} 10%, #{variables.$token-bg-surface-default});
background-color: var(--osui-list-item-selected-background);

.list-item-content {
&-title {
color: var(--color-text);
}

&-text {
color: var(--color-text-subtlest);
}
// Restated here so the pressed state also wins over the selected background.
&:active {
background-color: var(--osui-list-item-active-background);
}

.list-item-content {
&-right .icon {
color: var(--osui-list-item-selected-background);
color: var(--osui-list-item-selected-icon-color);
}
}
}
Expand Down
21 changes: 11 additions & 10 deletions src/scss/04-patterns/02-content/_chat-message.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
--osui-chat-message-border-radius: #{variables.$token-border-radius-200};
--osui-chat-message-sent-background: var(--color-primary);
--osui-chat-message-sent-color: var(--color-text-inverse);
--osui-chat-message-status-color: #{variables.$token-text-subtlest};
// ───────────────────────────────────────────────────────────────────

display: flex;
Expand All @@ -21,26 +22,25 @@

.chat {
&-photo {
margin-left: variables.$token-scale-400;
margin-left: variables.$token-space-400;
margin-right: variables.$token-scale-0;
}

&-message {
background-color: var(--osui-chat-message-sent-background);
color: var(--osui-chat-message-sent-color);
text-align: right;
}
}
}

&-photo {
margin-right: variables.$token-scale-400;
margin-right: variables.$token-space-400;

img {
border-radius: var(--border-radius-rounded);
height: variables.$token-scale-1000;
height: variables.$token-scale-800;
object-fit: cover;
width: variables.$token-scale-1000;
width: variables.$token-scale-800;
}
}

Expand All @@ -50,14 +50,15 @@
display: flex;
flex-direction: column;
max-width: 600px;
padding: variables.$token-scale-400;
padding: variables.$token-space-300;
position: relative;
word-break: break-word;

&-status {
color: var(--osui-chat-message-status-color);
display: block;
font-size: variables.$token-font-size-300;
margin-top: variables.$token-scale-200;
font-size: variables.$token-font-size-275;
margin-top: variables.$token-space-100;

&.hidden {
display: none;
Expand All @@ -74,13 +75,13 @@
.chat {
&-photo {
margin-left: variables.$token-scale-0;
margin-right: variables.$token-scale-400;
margin-right: variables.$token-space-400;
}
}
}

&-photo {
margin-left: variables.$token-scale-400;
margin-left: variables.$token-space-400;
margin-right: 0;
}
}
Expand Down
20 changes: 10 additions & 10 deletions src/scss/04-patterns/02-content/_floating-content.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

&-height {
margin-top: 0;
top: calc(var(--size-header) + variables.$token-scale-400 * 2);
top: calc(var(--size-header) + variables.$token-space-400 * 2);

&.absolute-top {
top: var(--os-safe-area-top);
Expand Down Expand Up @@ -53,19 +53,19 @@
&-top {
left: 50%;
margin-top: 0;
top: calc(var(--size-header) + variables.$token-scale-400 * 2);
top: calc(var(--size-header) + variables.$token-space-400 * 2);
transform: translateX(-50%);

&-left {
left: 0;
margin-top: 0;
top: calc(var(--size-header) + variables.$token-scale-400 * 2);
top: calc(var(--size-header) + variables.$token-space-400 * 2);
}

&-right {
margin-top: 0;
right: 0;
top: calc(var(--size-header) + variables.$token-scale-400 * 2);
top: calc(var(--size-header) + variables.$token-space-400 * 2);
}
}

Expand Down Expand Up @@ -154,22 +154,22 @@
}

&-margin {
margin: variables.$token-scale-800;
margin: variables.$token-space-800;

&.floating-content {
&-center {
left: calc(50% - variables.$token-scale-800);
top: calc(50% - variables.$token-scale-800);
left: calc(50% - variables.$token-space-800);
top: calc(50% - variables.$token-space-800);
}

&-left,
&-right {
top: calc(50% - variables.$token-scale-800);
top: calc(50% - variables.$token-space-800);
}
&-top,
&-bottom,
&-center {
left: calc(50% - variables.$token-scale-800);
left: calc(50% - variables.$token-space-800);
}
}
}
Expand All @@ -192,7 +192,7 @@
}

&.floating-content-full-height.floating-content-margin {
margin: variables.$token-scale-800;
margin: variables.$token-space-800;
}
}
}
Expand Down
Loading