Skyroc Native UI

Notify

贴边横幅通知,命令式调用为主

通知(Notify)在屏幕顶部或底部贴边浮出一条整宽色带,用于系统级消息:断网、版本更新、后台任务结果。主用法是命令式的 showNotify,面板通过 Portal 挂载(zIndex 1100,高于 Toast —— 它贴边显示不会压住居中的 Toast,即便与 Toast 的遮罩同时存在也应保持可见可点)。

import { showNotify, closeNotify } from '@skyroc/native-ui';

命令式调用依赖 PortalHost,请确保 App 内已经挂了它。

基础用法

showNotify 参数可以直接传字符串(等价于 { message }),返回一个实例句柄;closeNotify() 关闭当前通知。

NotifyBasic.tsx
Loading…
import { Button, closeNotify, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';

const NotifyBasic = () => {
  return (
    <View className="flex-row flex-wrap items-center gap-3 bg-background p-4">
      <Button
        variant="tonal"
        onPress={() => showNotify('这是一条基础通知')}
      >
        字符串简写
      </Button>
      <Button
        variant="tonal"
        onPress={() => showNotify({ message: '使用 options 传入通知内容' })}
      >
        options 调用
      </Button>
      <Button
        variant="outline"
        onPress={closeNotify}
      >
        关闭当前通知
      </Button>
    </View>
  );
};

export { NotifyBasic };

同一时刻只显示一条,新的会顶掉旧的(旧的那条会触发 onClose)。

何时使用

  • 系统级、需要横贯全屏宣告的消息。
  • 操作反馈用 Toast;需要用户确认用 Dialog

通知类型

type 决定背景色与文字色,四种语义各取对应的 -foreground token(而不是写死白字:warning / success 的背景在浅色主题下并不深,固定白字对比度不达标,主题切换时也无从跟随):

类型背景
dangerbg-destructive(默认)
primarybg-primary
successbg-success
warningbg-warning
NotifyTypes.tsx
Loading…
import type { NotifyType } from '@skyroc/native-ui';
import { Button, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';

const TYPES: NotifyType[] = ['primary', 'success', 'warning', 'danger'];

const NotifyTypes = () => {
  return (
    <View className="flex-row flex-wrap items-center gap-3 bg-background p-4">
      {TYPES.map(type => (
        <Button
          key={type}
          variant="tonal"
          onPress={() => showNotify({ message: `${type} 通知`, type })}
        >
          {type}
        </Button>
      ))}
    </View>
  );
};

export { NotifyTypes };

显示位置

position 控制贴顶还是贴底,命令式路径下还会自动补对应一侧的安全区(补偿落在带背景色的容器上,色块因此一直铺到状态栏 / home indicator)。

NotifyPositions.tsx
Loading…
import type { NotifyPosition } from '@skyroc/native-ui';
import { Button, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';

const POSITIONS: NotifyPosition[] = ['top', 'bottom'];

const NotifyPositions = () => {
  return (
    <View className="flex-row flex-wrap items-center gap-3 bg-background p-4">
      {POSITIONS.map(position => (
        <Button
          key={position}
          variant="tonal"
          onPress={() => showNotify({ message: `贴 ${position} 显示`, position })}
        >
          {position}
        </Button>
      ))}
    </View>
  );
};

export { NotifyPositions };

展示时长与关闭

duration 默认 3000ms,0 表示常驻 —— 此时用返回实例的 close() 关闭。

NotifyDuration.tsx
Loading…
import { Button, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';

const NotifyDuration = () => {
  function handleManualClose() {
    const instance = showNotify({ duration: 0, message: '常驻通知,2 秒后由实例关闭' });

    setTimeout(() => instance.close(), 2000);
  }

  return (
    <View className="flex-row flex-wrap items-center gap-3 bg-background p-4">
      <Button
        variant="tonal"
        onPress={() => showNotify({ duration: 1000, message: '1 秒后自动关闭' })}
      >
        自定义时长
      </Button>
      <Button
        variant="tonal"
        onPress={handleManualClose}
      >
        常驻 + 实例关闭
      </Button>
    </View>
  );
};

export { NotifyDuration };

点击事件

传了 onClick 后通知可响应点击;不传时不拦截触摸,下层内容照常可点。

NotifyInteraction.tsx
Loading…
import { Button, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';

const NotifyInteraction = () => {
  return (
    <View className="bg-background p-4">
      <Button
        variant="tonal"
        onPress={() =>
          showNotify({
            duration: 0,
            message: '点我触发 onClick',
            onClick: () => showNotify({ message: '收到点击', type: 'success' })
          })
        }
      >
        可点击
      </Button>
    </View>
  );
};

export { NotifyInteraction };

原地更新

实例的 update(options) 原地更新内容与配置,不重放进场动画,并按新的 duration 重新计时。

NotifyUpdate.tsx
Loading…
import { Button, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';

const NotifyUpdate = () => {
  function handleUpdate() {
    const instance = showNotify({ duration: 0, message: '处理中...', type: 'primary' });

    setTimeout(() => instance.update({ duration: 2000, message: '处理成功', type: 'success' }), 1500);
  }

  return (
    <View className="bg-background p-4">
      <Button
        variant="tonal"
        onPress={handleUpdate}
      >
        原地更新通知
      </Button>
    </View>
  );
};

export { NotifyUpdate };

关闭回调

onClose 在超时关闭、主动关闭、被新通知顶替三条路径下都会触发,且每条通知只触发一次

NotifyLifecycle.tsx
Loading…
import { Button, Text, showNotify } from '@skyroc/native-ui';
import { useState } from 'react';
import { View } from 'react-native';

const NotifyLifecycle = () => {
  const [closeCount, setCloseCount] = useState(0);

  function handleCountedNotify() {
    showNotify({
      message: '关闭时计数 +1',
      onClose: () => setCloseCount(prev => prev + 1)
    });
  }

  function handleReplaced() {
    // 第一条会被第二条顶替,被顶替同样算关闭,它的 onClose 也应各记一次
    showNotify({ message: '第一条(即将被顶替)', onClose: () => setCloseCount(prev => prev + 1) });
    showNotify({ message: '第二条(顶替了第一条)', onClose: () => setCloseCount(prev => prev + 1) });
  }

  return (
    <View className="bg-background p-4">
      <View className="mb-2 flex-row flex-wrap items-center gap-3">
        <Button
          variant="tonal"
          onPress={handleCountedNotify}
        >
          onClose 计数
        </Button>
        <Button
          variant="tonal"
          onPress={handleReplaced}
        >
          顶替(应 +1)
        </Button>
      </View>
      <Text color="muted">onClose 已触发 {closeCount} 次(每关闭一条只应 +1)</Text>
    </View>
  );
};

export { NotifyLifecycle };

全局默认配置

import { setNotifyDefaultOptions, resetNotifyDefaultOptions } from '@skyroc/native-ui';

setNotifyDefaultOptions({ duration: 5000, type: 'primary' });
resetNotifyDefaultOptions();

setNotifyDefaultOptions增量合并(与已有默认值合并),resetNotifyDefaultOptions 清空全部。合并优先级是「全局默认 < 调用参数」。

NotifyDefaults.tsx
Loading…
import { Button, resetNotifyDefaultOptions, setNotifyDefaultOptions, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';

const NotifyDefaults = () => {
  function handleShowWithDefaults() {
    setNotifyDefaultOptions({ duration: 5000, position: 'bottom', type: 'primary' });
    showNotify('使用全局默认配置');
  }

  function handleResetDefaults() {
    resetNotifyDefaultOptions();
    showNotify('已恢复默认配置');
  }

  return (
    <View className="flex-row flex-wrap items-center gap-3 bg-background p-4">
      <Button
        variant="tonal"
        onPress={handleShowWithDefaults}
      >
        设置并使用默认配置
      </Button>
      <Button
        variant="outline"
        onPress={handleResetDefaults}
      >
        重置默认配置
      </Button>
    </View>
  );
};

export { NotifyDefaults };

自定义样式与内容

className / classNames 优先使用主题类名;background / color 只在颜色来自主题之外(如服务端下发的品牌色)时使用。message 也可以传自定义节点。

slot作用位置
root色带本体(背景色、安全区补偿)
content内容容器(内边距、居中)
message消息文字
NotifyCustom.tsx
Loading…
import { Button, Text, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';

const NotifyCustom = () => {
  return (
    <View className="flex-row flex-wrap items-center gap-3 bg-background p-4">
      <Button
        variant="tonal"
        onPress={() =>
          showNotify({
            className: 'bg-carbon',
            classNames: { content: 'py-4', message: 'text-base text-carbon-foreground' },
            message: '用 className 覆盖(跟随主题)'
          })
        }
      >
        className 覆盖
      </Button>
      <Button
        variant="tonal"
        onPress={() => showNotify({ background: '#7232dd', color: '#ffffff', message: '写死的品牌色' })}
      >
        背景色兜底
      </Button>
      <Button
        variant="tonal"
        onPress={() =>
          showNotify({
            message: (
              <View className="flex-row items-center gap-2">
                <Text className="text-2xl">🎉</Text>
                <Text className="text-sm font-medium text-primary-foreground">自定义节点</Text>
              </View>
            ),
            type: 'primary'
          })
        }
      >
        自定义节点
      </Button>
    </View>
  );
};

export { NotifyCustom };

声明式受控模式

<Notify> 组件就地渲染:show 控制显隐,onUpdateShow 接收自动关闭请求(组件到点后只通知,真正的隐藏仍由调用方改 show 完成)。

NotifyDeclarative.tsx
Loading…
import { Button, Notify } from '@skyroc/native-ui';
import { useState } from 'react';
import { View } from 'react-native';

const NotifyDeclarative = () => {
  const [declarativeShow, setDeclarativeShow] = useState(false);

  return (
    <View className="bg-background p-4">
      <View className="flex-row flex-wrap items-center gap-3">
        <Button
          variant="outline"
          onPress={() => setDeclarativeShow(true)}
        >
          显示受控 Notify
        </Button>
      </View>

      <Notify
        message="受控 Notify,3 秒后自动关闭"
        show={declarativeShow}
        type="success"
        onUpdateShow={setDeclarativeShow}
      />
    </View>
  );
};

export { NotifyDeclarative };

声明式不做贴边定位、也不补安全区 —— 内联在页面里它就是一条普通色块,贴边显示交给命令式路径的渲染器。两条路径共用同一份 duration 默认值规则,不会出现行为分叉。

API

命令式函数

function showNotify(options: NotifyOptions | string): NotifyInstance;
function closeNotify(): void;
function setNotifyDefaultOptions(options: NotifyOptions): void;
function resetNotifyDefaultOptions(): void;

NotifyOptions

属性说明类型默认值
message消息内容,字符串会自动包一层 TextReactNode-
type类型,决定背景色与文字色'danger' | 'primary' | 'success' | 'warning''danger'
position显示位置'top' | 'bottom''top'
duration自动关闭延时(毫秒),0 表示常驻number3000
onClick点击回调;不传时不拦截触摸,下层内容可点() => void-
onClose关闭时回调,三条关闭路径都只触发一次() => void-
background自定义背景色;仅用于主题外的颜色,能写成类名时优先用 classNamestring-
color自定义文字颜色;仅用于主题外的颜色,能写成类名时优先用 classNames.messagestring-
className色带本体类名,合并在 classNames.root 之后string-
classNames各 slot 的类名覆盖SlotClassNames<NotifySlots>-

Notify

声明式组件,属性为 NotifyOptions 加上:

属性说明类型默认值
show是否显示booleanfalse
onUpdateShow显示状态变更回调(到点时触发)(show: boolean) => void-

类型

import type {
  NotifyInstance,
  NotifyOptions,
  NotifyPosition,
  NotifyProps,
  NotifySlots,
  NotifyType
} from '@skyroc/native-ui';

NotifyType

通知类型,决定背景色与文字色。

'danger' | 'primary' | 'success' | 'warning'

NotifyPosition

显示位置,命令式路径下还决定安全区补偿画在哪一侧。

'bottom' | 'top'

NotifySlots

可通过 classNames 覆盖的 slot 名称。

'content' | 'message' | 'root'

SlotClassNames

classNames 的取值形态:把 slot 名映射到类名,每个 slot 都可选。本页用到的 slot 见 NotifySlots。

Partial<Record<Slots, string>>

NotifyInstance

showNotify 的返回值。

字段类型说明
close*() => void关闭此条通知;已被后来的通知顶替时不做任何事。
update*(options: NotifyOptions) => void原地更新此条通知的内容,不重放动画,并按新的 duration 重新计时。

包内还导出了 notifyVariantsnotifyPositionVariantsNotifyRenderer(由命令式路径自动挂载,一般不需要直接使用)。