diff --git a/resources/js/components/ui/Alert.vue b/resources/js/components/ui/Alert.vue index b23a5f50fdb..532fbe1baf4 100644 --- a/resources/js/components/ui/Alert.vue +++ b/resources/js/components/ui/Alert.vue @@ -8,7 +8,7 @@ const props = defineProps({ text: { type: [String, Number, Boolean, null], default: null }, /** The alert heading to display */ heading: { type: [String, null], default: null }, - /** Controls the appearance of the alert.

Options: `default`, `warning`, `error`, `success` */ + /** Controls the appearance of the alert.

Options: `default`, `tip`, `warning`, `error`, `success` */ variant: { type: String, default: 'default' }, /** Icon name to display. [Browse available icons](/?path=/story/components-icon--all-icons) */ icon: { type: String, default: null }, @@ -52,6 +52,11 @@ const alertClasses = computed(() => { '[&_code]:bg-gray-200! dark:[&_code]:bg-gray-800!', 'dark:[&_svg]:text-gray-400', ], + tip: [ + 'bg-blue-50 dark:bg-blue-300/6 border-blue-200 dark:border-blue-400/25 text-blue-800 dark:text-blue-200', + '[&_code]:bg-blue-200/50! dark:[&_code]:bg-blue-300/8!', + 'dark:[&_svg]:text-blue-300', + ], warning: [ 'bg-amber-50 dark:bg-amber-300/6 border-amber-200 dark:border-amber-400/25 text-amber-800 dark:text-amber-200', '[&_code]:bg-amber-200/50! dark:[&_code]:bg-amber-300/8!', @@ -76,6 +81,8 @@ const defaultIcon = computed(() => { if (props.icon) return props.icon; switch (props.variant) { + case 'tip': + return 'lightbulb-idea'; case 'warning': return 'warning-diamond'; case 'error': diff --git a/resources/js/pages/Playground.vue b/resources/js/pages/Playground.vue index 7bd3a7188d8..eab50eff1c7 100644 --- a/resources/js/pages/Playground.vue +++ b/resources/js/pages/Playground.vue @@ -321,12 +321,14 @@ defineProps(['icons']); Alerts + + diff --git a/resources/js/stories/Alert.stories.ts b/resources/js/stories/Alert.stories.ts index 940606067b4..dbd64295045 100644 --- a/resources/js/stories/Alert.stories.ts +++ b/resources/js/stories/Alert.stories.ts @@ -8,7 +8,7 @@ const meta = { argTypes: { variant: { control: 'select', - options: ['default', 'warning', 'error', 'success'], + options: ['default', 'tip', 'warning', 'error', 'success'], }, icon: { control: 'select', @@ -46,6 +46,7 @@ export const _DocsIntro: Story = { const variantsCode = ` + @@ -69,6 +70,7 @@ export const Variants: Story = { template: `
+ @@ -265,6 +267,13 @@ export const RichContent: Story = { }), }; +export const Tip: Story = { + args: { + text: 'This is a helpful tip', + variant: 'tip', + }, +}; + export const Warning: Story = { args: { text: 'This is a warning alert message', @@ -333,4 +342,3 @@ export const WithHeadingAndDescription: Story = { template: headingAndDescriptionCode, }), }; - diff --git a/resources/js/stories/docs/Alert.mdx b/resources/js/stories/docs/Alert.mdx index 062c702f888..cdc98a53cd7 100644 --- a/resources/js/stories/docs/Alert.mdx +++ b/resources/js/stories/docs/Alert.mdx @@ -9,7 +9,7 @@ Alerts are used to display important messages, notifications, and feedback to us ## Variants -Use the `variant` prop to change the appearance and semantic meaning of the alert. Available variants are `default`, `warning`, `error`, and `success`. +Use the `variant` prop to change the appearance and semantic meaning of the alert. Available variants are `default`, `tip`, `warning`, `error`, and `success`. diff --git a/resources/js/tests/components/ui/Alert.test.js b/resources/js/tests/components/ui/Alert.test.js new file mode 100644 index 00000000000..cdcbcf16884 --- /dev/null +++ b/resources/js/tests/components/ui/Alert.test.js @@ -0,0 +1,26 @@ +import { mount } from '@vue/test-utils'; +import { expect, test } from 'vitest'; +import { Alert, Icon } from '@/components/ui'; + +test('tip variant is blue and uses the tip icon', () => { + const wrapper = mount(Alert, { + props: { + text: 'This is a helpful tip', + variant: 'tip', + }, + }); + + const alert = wrapper.get('[data-ui-alert]'); + + expect(alert.classes()).toEqual(expect.arrayContaining([ + 'bg-blue-50', + 'border-blue-200', + 'text-blue-800', + ])); + expect(alert.attributes()).toMatchObject({ + role: 'status', + 'aria-live': 'polite', + 'data-variant': 'tip', + }); + expect(wrapper.findComponent(Icon).props('name')).toBe('lightbulb-idea'); +});