diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 000000000..68694c777 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,5 @@ +{ + "permissions": { + "allow": ["Bash(npx eslint *)", "Bash(git stash *)"] + } +} diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 109f6dfa4..5f2f87836 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -1,7 +1,6 @@ # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json language: en-US tone_instructions: "Expert code reviewer specializing in TS, React, and Design Systems. Deep knowledge of monorepos and Nimbus. Focus on atomic design, accessibility, and maintainability. Provide precise, actionable feedback on technical implementations." -auto_resolve_threads: true reviews: profile: assertive high_level_summary: true diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2349c3b3d..eb76ed858 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,11 +14,6 @@ jobs: publish-packages-npm: runs-on: ubuntu-latest timeout-minutes: 30 - permissions: - id-token: write - contents: write - pull-requests: write - env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ secrets.TURBO_TEAM }} @@ -31,16 +26,10 @@ jobs: sudo mkswap /swapfile sudo swapon /swapfile sudo swapon --show - + - name: Checkout uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20' - registry-url: 'https://registry.npmjs.org/' - auth-oidc: true - - uses: ./.github/actions/setup-node-deps - name: Create .env file @@ -52,7 +41,7 @@ jobs: - name: Build icons run: yarn build:icons - + - name: Build components run: | export NODE_OPTIONS="--max_old_space_size=12288" @@ -67,14 +56,9 @@ jobs: run: yarn build:docs - name: Publish packages - run: | - if [ -f ".yarnrc.yml" ]; then - yarn config set npmAuthIdent "" - yarn config set npmAlwaysAuth false - fi - yarn publish:stable + run: yarn publish:stable env: - NODE_AUTH_TOKEN: "" + YARN_NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTOMATION_PUBLISH }} - name: Create release PR uses: peter-evans/create-pull-request@v7 @@ -90,6 +74,7 @@ jobs: .yarn/versions/** branch: release/publish-${{ github.run_id }} base: master + trigger-action-create-github-tag: runs-on: ubuntu-latest @@ -97,6 +82,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + - name: Trigger github action create github tag run: | curl --request POST \ @@ -110,6 +96,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + - name: Trigger github action send slack notifications run: | curl --request POST \ @@ -128,6 +115,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + - name: Trigger github action update documentation run: | curl --request POST \ diff --git a/.gitignore b/.gitignore index bd7de13c6..2c1a24b4b 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,6 @@ TODO.md # Snyk Security Extension - AI Rules (auto-generated) .cursor/rules/snyk_rules.mdc + +# Claude +.claude.settings.json \ No newline at end of file diff --git a/.yarn/versions/240394ca.yml b/.yarn/versions/240394ca.yml new file mode 100644 index 000000000..fbc4ea878 --- /dev/null +++ b/.yarn/versions/240394ca.yml @@ -0,0 +1,11 @@ +releases: + "@nimbus-ds/components": minor + "@nimbus-ds/modal": minor + "@nimbus-ds/styles": minor + "@nimbus-ds/tokens": minor + +declined: + - nimbus-design-system + - "@nimbus-ds/split-button" + - "@nimbus-ds/stepper" + - "@nimbus-ds/time-picker" diff --git a/packages/core/styles/CHANGELOG.md b/packages/core/styles/CHANGELOG.md index fc314a35f..012460866 100644 --- a/packages/core/styles/CHANGELOG.md +++ b/packages/core/styles/CHANGELOG.md @@ -2,11 +2,11 @@ Nimbus Styles deprive all styles needed to build nimbus components. -## 2026-03-04 `9.61.0` +## 2026-05-04 `9.62.0` #### 🎉 New features -- `ProgressBar`: Added fill color CSS variable, background color variants, box shadow support, and no-overflow container style. ([#441](https://github.com/TiendaNube/nimbus-design-system/pull/441) by [@joacotornello](https://github.com/joacotornello)) +- Improved styles for modal. ([#460](https://github.com/TiendaNube/nimbus-design-system/pull/460) by [@joacotornello](https://github.com/joacotornello)) ## 2026-03-02 `9.60.1` diff --git a/packages/core/styles/src/packages/composite/modal/nimbus-modal.css.ts b/packages/core/styles/src/packages/composite/modal/nimbus-modal.css.ts index 5ca4ddaad..b6c3dd00d 100644 --- a/packages/core/styles/src/packages/composite/modal/nimbus-modal.css.ts +++ b/packages/core/styles/src/packages/composite/modal/nimbus-modal.css.ts @@ -1,4 +1,4 @@ -import { style, keyframes } from "@vanilla-extract/css"; +import { style, styleVariants, keyframes } from "@vanilla-extract/css"; import { defineProperties as defineSprinkleProperties, createSprinkles, @@ -28,7 +28,11 @@ export const container = style({ backgroundColor: varsThemeBase.colors.neutral.background, borderRadius: varsThemeBase.shape.border.radius[2], boxSizing: "border-box", - zIndex: varsThemeBase.zIndex[700], +}); + +const containerZIndex = styleVariants({ + base: { zIndex: varsThemeBase.zIndex[700] }, + top: { zIndex: varsThemeBase.zIndex[1100] }, }); const container__close = style({ @@ -82,7 +86,6 @@ const baseOverlay = style({ left: 0, right: 0, backgroundColor: "rgba(0, 0, 0, 0.5)", - zIndex: varsThemeBase.zIndex[600], animation: `${overlayAnimation} 0.5s ease`, }); @@ -91,15 +94,32 @@ const overlay = style([ { position: "fixed", height: "100vh", width: "100vw" }, ]); +const overlayZIndex = styleVariants({ + base: { zIndex: varsThemeBase.zIndex[600] }, + top: { zIndex: varsThemeBase.zIndex[1000] }, +}); + const overlayScoped = style([ baseOverlay, - { position: "absolute", height: "100%", width: "100%" }, + { + position: "absolute", + height: "100%", + width: "100%", + }, ]); +const overlayScopedZIndex = styleVariants({ + base: { zIndex: varsThemeBase.zIndex[600] }, + top: { zIndex: varsThemeBase.zIndex[1000] }, +}); + export const styles = { overlay, + overlayZIndex, overlayScoped, + overlayScopedZIndex, container, + containerZIndex, container__close, container__footer, }; diff --git a/packages/core/styles/src/properties/css.ts b/packages/core/styles/src/properties/css.ts index 456a730cb..73c75952c 100644 --- a/packages/core/styles/src/properties/css.ts +++ b/packages/core/styles/src/properties/css.ts @@ -274,6 +274,8 @@ export const zIndexProperties = { "700": varsThemeBase.zIndex[700], "800": varsThemeBase.zIndex[800], "900": varsThemeBase.zIndex[900], + "1000": varsThemeBase.zIndex[1000], + "1100": varsThemeBase.zIndex[1100], }; export const wordBreakProperties: WordBreak[] = [ diff --git a/packages/core/styles/src/themes/contract.css.ts b/packages/core/styles/src/themes/contract.css.ts index 97f9151fd..57f42afbf 100644 --- a/packages/core/styles/src/themes/contract.css.ts +++ b/packages/core/styles/src/themes/contract.css.ts @@ -174,6 +174,8 @@ export const vars = createGlobalThemeContract( 700: "", 800: "", 900: "", + 1000: "", + 1100: "", }, motion: { speed: { diff --git a/packages/core/styles/src/themes/globals.css.ts b/packages/core/styles/src/themes/globals.css.ts index 23ad1679c..0065aee5a 100644 --- a/packages/core/styles/src/themes/globals.css.ts +++ b/packages/core/styles/src/themes/globals.css.ts @@ -186,6 +186,8 @@ export const globalTheme = { 700: zIndex[700].value, 800: zIndex[800].value, 900: zIndex[900].value, + 1000: zIndex[1000].value, + 1100: zIndex[1100].value, }, motion: { speed: { diff --git a/packages/core/tokens/CHANGELOG.md b/packages/core/tokens/CHANGELOG.md index f91f8f9cb..18bfdb29c 100644 --- a/packages/core/tokens/CHANGELOG.md +++ b/packages/core/tokens/CHANGELOG.md @@ -2,6 +2,12 @@ Our design tokens are the foundations of Nimbus Design System. +## 2026-05-04 `9.6.0` + +#### 🎉 New features + +- Added 1000 and 1100 zIndex tokens. ([#460](https://github.com/TiendaNube/nimbus-design-system/pull/460) by [@joacotornello](https://github.com/joacotornello)) + ## 2025-11-11 `9.5.0` #### 🎉 New features diff --git a/packages/core/tokens/src/zIndex/sys.json b/packages/core/tokens/src/zIndex/sys.json index af0a46149..b51718a88 100644 --- a/packages/core/tokens/src/zIndex/sys.json +++ b/packages/core/tokens/src/zIndex/sys.json @@ -22,7 +22,15 @@ }, "900": { "value": "900", - "comment": "The highest z-index value, use not defined." + "comment": "The highest general-purpose z-index value, use not defined." + }, + "1000": { + "value": "1000", + "comment": "Reserved for Modal overlay when zIndex='top'. Do not use elsewhere." + }, + "1100": { + "value": "1100", + "comment": "Reserved for Modal container when zIndex='top'. Do not use elsewhere." } } } diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 05988d226..02d05b65d 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -3,6 +3,12 @@ Nimbus is an open-source Design System created by Tiendanube / Nuvemshop's team to empower and enhance more stories every day, with simplicity, accessibility, consistency and performance. +## 2026-05-04 `5.57.0` + +#### 🎉 New features + +- Modal: `renderDismissButton` and `zIndex` support. ([#460](https://github.com/TiendaNube/nimbus-design-system/pull/460) by [@joacotornello](https://github.com/joacotornello)) + ## 2026-03-04 `5.56.0` #### 🎉 New features diff --git a/packages/react/src/composite/Modal/src/Modal.tsx b/packages/react/src/composite/Modal/src/Modal.tsx index 6fd419a7b..d032b25b5 100644 --- a/packages/react/src/composite/Modal/src/Modal.tsx +++ b/packages/react/src/composite/Modal/src/Modal.tsx @@ -34,6 +34,8 @@ const Modal: React.FC & ModalComponents = ({ root, closeOnOutsidePress = true, ignoreAttributeName = DEFAULT_OUTSIDE_PRESS_IGNORE_ATTRIBUTE, + renderDismissButton = true, + zIndex = "base", ...rest }: ModalProps) => { const { @@ -93,7 +95,12 @@ const Modal: React.FC & ModalComponents = ({ {...otherProps} ref={context.refs.setFloating} style={style} - className={[className, modal.classnames.container, classNameStyles] + className={[ + className, + modal.classnames.container, + modal.classnames.containerZIndex[zIndex], + classNameStyles, + ] .filter(Boolean) .join(" ")} aria-labelledby={headingId} @@ -102,7 +109,7 @@ const Modal: React.FC & ModalComponents = ({ {...rest} > {children} - {onDismiss && ( + {onDismiss && renderDismissButton && ( + + + ); +}; + +const renderWithArgs = (args: ModalProps) => { + const [{ open }, updateArgs] = useArgs(); + const handleClose = () => updateArgs({ open: !open }); + return ( + <> + + + + ); +}; + export const basic: Story = { - render: (args) => { - const [{ open }, updateArgs] = useArgs(); - const handleClose = () => updateArgs({ open: !open }); - return ( - <> - - - - ); - }, + render: renderWithArgs, args: { children: ( <> @@ -88,17 +102,6 @@ export const withRoot: Story = { }, }; -const render = (args: ModalProps) => { - const [open, setOpen] = useState(false); - const handleClose = () => setOpen((prevState) => !prevState); - return ( - <> - - - - ); -}; - export const WithHeader: Story = { render, args: { @@ -231,6 +234,63 @@ export const noDismiss: Story = { }, }; +export const noDismissButton: Story = { + render: renderWithArgs, + args: { + renderDismissButton: false, + children: ( + <> + + + + The X icon is hidden, but Escape key and clicking outside still + close the modal. + + + + ), + }, +}; + +export const modalOverSidebar: Story = { + render: (args) => { + const [{ open }, updateArgs] = useArgs(); + const handleClose = () => updateArgs({ open: !open }); + return ( + + + The modal overlay and container uses higher zIndex than Sidebar when + zIndex=Top + + + + + + Another modal + + + + ); + }, + args: { + zIndex: "top", + children: ( + <> + + + + This modal uses zIndex="top" and renders above tooltips, + toasts, and popovers. + + + + + + + ), + }, +}; + export const withIgnoreAttribute: Story = { render: (args) => { // ⚡ Use a simple local state instead of useArgs for open/close diff --git a/packages/react/src/composite/Modal/src/modal.types.ts b/packages/react/src/composite/Modal/src/modal.types.ts index e6dbf0e3f..4a2116c20 100644 --- a/packages/react/src/composite/Modal/src/modal.types.ts +++ b/packages/react/src/composite/Modal/src/modal.types.ts @@ -51,6 +51,20 @@ export interface ModalProperties extends ModalSprinkle { * @default base */ padding?: keyof typeof modal.properties.padding; + /** + * Controls whether the built-in close (X) button renders. + * Only takes effect when `onDismiss` is provided. + * @default true + */ + renderDismissButton?: boolean; + /** + * Stacking layer for the modal. + * - "base": standard modal layer (above the page, below floating components like tooltip/toast/popover). + * - "top": renders above all other floating components. Reserved exclusively for Modal. + * Only effective on the default portaled path; has no effect when `root` is provided. + * @default "base" + */ + zIndex?: "base" | "top"; } export type ModalProps = ModalProperties & {