okonomi_ui_kit 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +165 -7
  3. data/app/assets/builds/okonomi_ui_kit/application.tailwind.css +664 -187
  4. data/app/helpers/okonomi_ui_kit/application_helper.rb +8 -0
  5. data/app/helpers/okonomi_ui_kit/attribute_section_helper.rb +5 -5
  6. data/app/helpers/okonomi_ui_kit/component.rb +44 -21
  7. data/app/helpers/okonomi_ui_kit/components/alert.rb +1 -1
  8. data/app/helpers/okonomi_ui_kit/components/badge.rb +5 -5
  9. data/app/helpers/okonomi_ui_kit/components/breadcrumbs.rb +69 -0
  10. data/app/helpers/okonomi_ui_kit/components/button_base.rb +56 -0
  11. data/app/helpers/okonomi_ui_kit/components/button_tag.rb +23 -0
  12. data/app/helpers/okonomi_ui_kit/components/button_to.rb +4 -15
  13. data/app/helpers/okonomi_ui_kit/components/code.rb +41 -37
  14. data/app/helpers/okonomi_ui_kit/components/confirmation_modal.rb +130 -0
  15. data/app/helpers/okonomi_ui_kit/components/forms/check_box_with_label.rb +38 -0
  16. data/app/helpers/okonomi_ui_kit/components/forms/collection_select.rb +57 -0
  17. data/app/helpers/okonomi_ui_kit/components/forms/date_field.rb +9 -0
  18. data/app/helpers/okonomi_ui_kit/components/forms/datetime_local_field.rb +9 -0
  19. data/app/helpers/okonomi_ui_kit/components/forms/email_field.rb +9 -0
  20. data/app/helpers/okonomi_ui_kit/components/forms/field.rb +24 -0
  21. data/app/helpers/okonomi_ui_kit/components/forms/field_set.rb +17 -0
  22. data/app/helpers/okonomi_ui_kit/components/forms/input_base.rb +57 -0
  23. data/app/helpers/okonomi_ui_kit/components/forms/label.rb +27 -0
  24. data/app/helpers/okonomi_ui_kit/components/forms/multi_select.rb +18 -0
  25. data/app/helpers/okonomi_ui_kit/components/forms/number_field.rb +9 -0
  26. data/app/helpers/okonomi_ui_kit/components/forms/password_field.rb +9 -0
  27. data/app/helpers/okonomi_ui_kit/components/forms/search_field.rb +9 -0
  28. data/app/helpers/okonomi_ui_kit/components/forms/select.rb +57 -0
  29. data/app/helpers/okonomi_ui_kit/components/forms/show_if.rb +28 -0
  30. data/app/helpers/okonomi_ui_kit/components/forms/telephone_field.rb +9 -0
  31. data/app/helpers/okonomi_ui_kit/components/forms/text_area.rb +9 -0
  32. data/app/helpers/okonomi_ui_kit/components/forms/text_field.rb +9 -0
  33. data/app/helpers/okonomi_ui_kit/components/forms/time_field.rb +9 -0
  34. data/app/helpers/okonomi_ui_kit/components/forms/upload_field.rb +25 -0
  35. data/app/helpers/okonomi_ui_kit/components/forms/url_field.rb +9 -0
  36. data/app/helpers/okonomi_ui_kit/components/forms.rb +6 -0
  37. data/app/helpers/okonomi_ui_kit/components/icon.rb +36 -0
  38. data/app/helpers/okonomi_ui_kit/components/link_to.rb +8 -19
  39. data/app/helpers/okonomi_ui_kit/components/navigation.rb +98 -0
  40. data/app/helpers/okonomi_ui_kit/components/page.rb +8 -8
  41. data/app/helpers/okonomi_ui_kit/components/table.rb +9 -10
  42. data/app/helpers/okonomi_ui_kit/components/typography.rb +16 -16
  43. data/app/helpers/okonomi_ui_kit/components.rb +4 -0
  44. data/app/helpers/okonomi_ui_kit/config.rb +5 -1
  45. data/app/helpers/okonomi_ui_kit/configs.rb +4 -0
  46. data/app/helpers/okonomi_ui_kit/form_builder.rb +39 -130
  47. data/app/helpers/okonomi_ui_kit/form_component.rb +7 -0
  48. data/app/helpers/okonomi_ui_kit/svg_icons.rb +5 -5
  49. data/app/helpers/okonomi_ui_kit/t_w_merge.rb +114 -0
  50. data/app/helpers/okonomi_ui_kit/ui_helper.rb +17 -58
  51. data/app/views/okonomi/components/breadcrumbs/_breadcrumbs.html.erb +46 -0
  52. data/app/views/okonomi/components/confirmation_modal/_confirmation_modal.html.erb +76 -0
  53. data/app/views/okonomi/components/forms/check_box_with_label/_check_box_with_label.html.erb +6 -0
  54. data/app/views/okonomi/components/forms/field/_field.html.erb +3 -0
  55. data/app/views/okonomi/components/forms/field_set/_field_set.html.erb +3 -0
  56. data/app/views/okonomi/components/forms/upload_field/_upload_field.html.erb +1 -0
  57. data/app/views/okonomi/components/icon/_icon.html.erb +38 -0
  58. data/app/views/okonomi/components/navigation/_link.html.erb +18 -0
  59. data/app/views/okonomi/components/navigation/_navigation.html.erb +4 -0
  60. data/app/views/okonomi/forms/tailwind/_checkbox_label.html.erb +2 -2
  61. data/app/views/okonomi/forms/tailwind/_field.html.erb +6 -6
  62. data/app/views/okonomi/forms/tailwind/_multi_select.html.erb +2 -4
  63. data/app/views/okonomi/forms/tailwind/_upload_field.html.erb +10 -10
  64. data/config/importmap.rb +1 -1
  65. data/lib/okonomi_ui_kit/engine.rb +0 -3
  66. data/lib/okonomi_ui_kit/version.rb +1 -1
  67. metadata +43 -12
  68. data/app/helpers/okonomi_ui_kit/breadcrumbs_helper.rb +0 -60
  69. data/app/helpers/okonomi_ui_kit/icon_helper.rb +0 -39
  70. data/app/helpers/okonomi_ui_kit/navigation_helper.rb +0 -72
  71. data/app/helpers/okonomi_ui_kit/theme.rb +0 -159
  72. data/app/helpers/okonomi_ui_kit/theme_helper.rb +0 -17
  73. data/app/views/okonomi/forms/tailwind/_field_set.html.erb +0 -3
  74. data/app/views/okonomi/modals/_confirmation_modal.html.erb +0 -77
  75. data/app/views/okonomi/navigation/_link.html.erb +0 -15
  76. data/app/views/okonomi/navigation/_menu.html.erb +0 -3
  77. data/app/views/okonomi/navigation/_navbar.html.erb +0 -105
@@ -1,72 +0,0 @@
1
- module OkonomiUiKit
2
- module NavigationHelper
3
- def navigation_menu(**options, &block)
4
- builder = NavigationBuilder.new(self)
5
- render 'okonomi/navigation/menu', builder: builder, options: options, &block
6
- end
7
-
8
- class NavigationBuilder
9
- include ActionView::Helpers::TagHelper
10
- include ActionView::Helpers::CaptureHelper
11
-
12
- def initialize(template)
13
- @template = template
14
- end
15
-
16
- def group(title, &block)
17
- group_builder = NavigationGroupBuilder.new(@template)
18
- content = capture(group_builder, &block)
19
-
20
- tag.li do
21
- tag.div(title, class: "text-xs/6 font-semibold text-gray-400") +
22
- tag.ul(content, role: "list", class: "-mx-2 mt-2 space-y-1")
23
- end
24
- end
25
-
26
- def profile_section(&block)
27
- content = capture(&block)
28
- tag.li(content, class: "-mx-6 mt-auto")
29
- end
30
-
31
- private
32
-
33
- def tag
34
- @template.tag
35
- end
36
-
37
- def capture(*args, &block)
38
- @template.capture(*args, &block)
39
- end
40
- end
41
-
42
- class NavigationGroupBuilder
43
- include ActionView::Helpers::TagHelper
44
- include ActionView::Helpers::CaptureHelper
45
-
46
- def initialize(template)
47
- @template = template
48
- end
49
-
50
- def nav_link(title, path, icon: nil, initials: nil, exact: false)
51
- tag.li do
52
- @template.render "okonomi/navigation/link",
53
- path: path,
54
- title: title,
55
- icon: icon,
56
- initials: initials,
57
- exact: exact
58
- end
59
- end
60
-
61
- private
62
-
63
- def tag
64
- @template.tag
65
- end
66
-
67
- def capture(*args, &block)
68
- @template.capture(*args, &block)
69
- end
70
- end
71
- end
72
- end
@@ -1,159 +0,0 @@
1
- module OkonomiUiKit
2
- module Theme
3
- LIGHT_THEME = {
4
- components: {
5
- typography: {
6
- variants: {
7
- body1: "text-base font-normal",
8
- body2: "text-sm font-normal",
9
- h1: "text-3xl font-bold",
10
- h2: "text-2xl font-bold",
11
- h3: "text-xl font-semibold",
12
- h4: "text-lg font-semibold",
13
- h5: "text-base font-semibold",
14
- h6: "text-sm font-semibold"
15
- },
16
- colors: {
17
- default: "text-default-700",
18
- dark: "text-default-900",
19
- muted: "text-default-500",
20
- primary: "text-primary-600",
21
- secondary: "text-secondary-600",
22
- success: "text-success-600",
23
- danger: "text-danger-600",
24
- warning: "text-warning-600",
25
- info: "text-info-600"
26
- }
27
- },
28
- link: {
29
- root: "hover:cursor-pointer text-sm",
30
- outlined: {
31
- root: "inline-flex border items-center justify-center px-2 py-1 rounded-md font-medium focus:outline-none focus:ring-2 focus:ring-offset-2",
32
- colors: {
33
- default: "bg-white text-default-700 border-default-700 hover:bg-default-50",
34
- primary: "bg-white text-primary-600 border-primary-600 hover:bg-primary-50",
35
- secondary: "bg-white text-secondary-600 border-secondary-600 hover:bg-secondary-50",
36
- success: "bg-white text-success-600 border-success-600 hover:bg-success-50",
37
- danger: "bg-white text-danger-600 border-danger-600 hover:bg-danger-50",
38
- warning: "bg-white text-warning-600 border-warning-600 hover:bg-warning-50",
39
- info: "bg-white text-info-600 border-info-600 hover:bg-info-50"
40
- }
41
- },
42
- contained: {
43
- root: "inline-flex border items-center justify-center px-2 py-1 rounded-md font-medium focus:outline-none focus:ring-2 focus:ring-offset-2",
44
- colors: {
45
- default: "border-default-700 bg-default-600 text-white hover:bg-default-700",
46
- primary: "border-primary-700 bg-primary-600 text-white hover:bg-primary-700",
47
- secondary: "border-secondary-700 bg-secondary-600 text-white hover:bg-secondary-700",
48
- success: "border-success-700 bg-success-600 text-white hover:bg-success-700",
49
- danger: "border-danger-700 bg-danger-600 text-white hover:bg-danger-700",
50
- warning: "border-warning-700 bg-warning-600 text-white hover:bg-warning-700",
51
- info: "border-info-700 bg-info-600 text-white hover:bg-info-700"
52
- }
53
- },
54
- text: {
55
- root: "text-base",
56
- colors: {
57
- default: "text-default-700 hover:underline",
58
- primary: "text-primary-600 hover:underline",
59
- secondary: "text-secondary-600 hover:underline",
60
- success: "text-success-600 hover:underline",
61
- danger: "text-danger-600 hover:underline",
62
- warning: "text-warning-600 hover:underline",
63
- info: "text-info-600 hover:underline"
64
- }
65
- }
66
- },
67
- input: {
68
- types: {
69
- text: {
70
- root: "w-full border-0 px-3 py-2 rounded-md ring-1 focus:outline-none focus-within:ring-1",
71
- error: "bg-danger-100 text-danger-400 ring-danger-400 focus:ring-danger-600",
72
- valid: "text-default-700 ring-gray-300 focus-within:ring-gray-400",
73
- disabled: "disabled:bg-gray-50 disabled:cursor-not-allowed"
74
- }
75
- }
76
- },
77
- select: {
78
- root: "col-start-1 row-start-1 w-full appearance-none rounded-md py-2 pr-8 pl-3 text-base outline-1 focus:outline-none sm:text-sm/6",
79
- error: "bg-danger-100 text-danger-400 ring-1 ring-danger-400",
80
- valid: "bg-white outline-default-300 text-default-700",
81
- wrapper: "grid grid-cols-1",
82
- icon: {
83
- file: 'heroicons/solid/chevron-down',
84
- class: "pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-gray-500 sm:size-4"
85
- }
86
- },
87
- label: {
88
- root: "block text-sm/6 font-medium text-default-700"
89
- },
90
- checkbox: {
91
- wrapper: "flex gap-4 items-center",
92
- input: {
93
- root: "cursor-pointer size-5 rounded-sm border-gray-300 text-primary-600 focus:ring-0 focus:ring-primary-600"
94
- },
95
- label: {
96
- root: "cursor-pointer font-medium text-gray-700"
97
- },
98
- hint: {
99
- root: "cursor-pointer text-sm text-gray-400"
100
- }
101
- },
102
- modal: {
103
- backdrop: "fixed inset-0 bg-gray-500/75 transition-opacity duration-300 ease-out opacity-0",
104
- container: "fixed inset-0 z-10 w-screen overflow-y-auto",
105
- wrapper: "flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0",
106
- panel: {
107
- base: "relative transform overflow-hidden rounded-lg bg-white px-4 pt-5 pb-4 text-left shadow-xl transition-all duration-300 ease-out sm:my-8 sm:w-full sm:p-6 opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95",
108
- sizes: {
109
- sm: "sm:max-w-sm",
110
- md: "sm:max-w-lg",
111
- lg: "sm:max-w-2xl",
112
- xl: "sm:max-w-4xl"
113
- }
114
- },
115
- close_button: {
116
- wrapper: "absolute top-0 right-0 hidden pt-4 pr-4 sm:block",
117
- button: "rounded-md bg-white text-gray-400 hover:text-gray-500 focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:outline-none",
118
- icon: {
119
- file: "heroicons/outline/x-mark",
120
- class: "size-6"
121
- }
122
- },
123
- icon: {
124
- wrapper: "mx-auto flex size-12 shrink-0 items-center justify-center rounded-full sm:mx-0 sm:size-10",
125
- class: "size-6",
126
- variants: {
127
- warning: {
128
- wrapper: "bg-red-100",
129
- icon: "text-red-600",
130
- file: "heroicons/outline/exclamation-triangle"
131
- },
132
- info: {
133
- wrapper: "bg-blue-100",
134
- icon: "text-blue-600",
135
- file: "heroicons/outline/information-circle"
136
- },
137
- success: {
138
- wrapper: "bg-green-100",
139
- icon: "text-green-600",
140
- file: "heroicons/outline/check-circle"
141
- }
142
- }
143
- },
144
- content: {
145
- wrapper: "sm:flex sm:items-start",
146
- text_wrapper: "mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",
147
- title: "text-base font-semibold text-gray-900",
148
- message: "mt-2 text-sm text-gray-500"
149
- },
150
- actions: {
151
- wrapper: "mt-5 sm:mt-4 sm:flex sm:flex-row-reverse"
152
- }
153
- }
154
- }
155
- }
156
-
157
- DEFAULT_THEME = LIGHT_THEME
158
- end
159
- end
@@ -1,17 +0,0 @@
1
- module OkonomiUiKit
2
- module ThemeHelper
3
- def theme(t = {}, &block)
4
- old_theme = theme
5
-
6
- @_okonomi_ui_kit_theme = {}.merge(old_theme).merge(t || {})
7
-
8
- yield(@_okonomi_ui_kit_theme)
9
-
10
- @_okonomi_ui_kit_theme = old_theme
11
- end
12
-
13
- def get_theme
14
- @_okonomi_ui_kit_theme ||= OkonomiUiKit::Theme::DEFAULT_THEME
15
- end
16
- end
17
- end
@@ -1,3 +0,0 @@
1
- <div class="w-full flex flex-col gap-4 col-span-1 sm:col-span-3 md:col-span-5">
2
- <%= yield %>
3
- </div>
@@ -1,77 +0,0 @@
1
- <div data-controller="modal"
2
- data-modal-size-value="<%= options[:size] %>"
3
- <% if options[:auto_open] %>data-modal-auto-open-value="true"<% end %>
4
- class="relative z-10"
5
- style="display: none;"
6
- data-modal-target="container"
7
- <%= ui.modal_data_attributes(options) %>>
8
-
9
- <!-- Backdrop -->
10
- <div class="<%= ui.get_theme.dig(:components, :modal, :backdrop) %>"
11
- data-modal-target="backdrop"
12
- data-action="click->modal#close"
13
- aria-hidden="true"></div>
14
-
15
- <!-- Modal container -->
16
- <div class="<%= ui.get_theme.dig(:components, :modal, :container) %>">
17
- <div class="<%= ui.get_theme.dig(:components, :modal, :wrapper) %>">
18
- <!-- Modal panel -->
19
- <div class="<%= ui.modal_panel_class(options[:size]) %>"
20
- data-modal-target="panel"
21
- role="dialog"
22
- aria-modal="true"
23
- aria-labelledby="modal-title">
24
-
25
- <!-- Close button -->
26
- <div class="<%= ui.get_theme.dig(:components, :modal, :close_button, :wrapper) %>">
27
- <button type="button"
28
- class="<%= ui.get_theme.dig(:components, :modal, :close_button, :button) %>"
29
- data-action="click->modal#close">
30
- <span class="sr-only">Close</span>
31
- <%= svg_icon(ui.get_theme.dig(:components, :modal, :close_button, :icon, :file),
32
- class: ui.get_theme.dig(:components, :modal, :close_button, :icon, :class)) %>
33
- </button>
34
- </div>
35
-
36
- <!-- Content -->
37
- <div class="<%= ui.get_theme.dig(:components, :modal, :content, :wrapper) %>">
38
- <!-- Icon -->
39
- <div class="<%= ui.modal_icon_wrapper_class(options[:variant]) %>">
40
- <%= svg_icon(ui.get_theme.dig(:components, :modal, :icon, :variants, options[:variant], :file),
41
- class: [ui.get_theme.dig(:components, :modal, :icon, :class),
42
- ui.get_theme.dig(:components, :modal, :icon, :variants, options[:variant], :icon)].join(' ')) %>
43
- </div>
44
-
45
- <!-- Text content -->
46
- <div class="<%= ui.get_theme.dig(:components, :modal, :content, :text_wrapper) %>">
47
- <h3 id="modal-title" class="<%= ui.get_theme.dig(:components, :modal, :content, :title) %>">
48
- <%= options[:title] %>
49
- </h3>
50
- <div class="<%= ui.get_theme.dig(:components, :modal, :content, :message) %>">
51
- <p><%= options[:message] %></p>
52
- </div>
53
- </div>
54
- </div>
55
-
56
- <!-- Actions -->
57
- <div class="<%= ui.get_theme.dig(:components, :modal, :actions, :wrapper) %>">
58
- <% if options[:has_custom_actions] %>
59
- <%= yield %>
60
- <% else %>
61
- <% button_color = options[:variant] == :warning ? :danger : options[:variant] %>
62
- <button type="button"
63
- class="<%= ui.button_class(variant: :contained, color: button_color) %> sm:ml-3 sm:w-auto"
64
- data-action="click->modal#confirm">
65
- <%= options[:confirm_text] %>
66
- </button>
67
- <button type="button"
68
- class="<%= ui.button_class(variant: :outlined, color: :default) %> mt-3 sm:mt-0 sm:w-auto"
69
- data-action="click->modal#close">
70
- <%= options[:cancel_text] %>
71
- </button>
72
- <% end %>
73
- </div>
74
- </div>
75
- </div>
76
- </div>
77
- </div>
@@ -1,15 +0,0 @@
1
- <%
2
- options = {
3
- exact: defined?(exact) ? exact : false,
4
- class: "group flex gap-x-3 rounded-md p-2 text-sm/6 font-semibold hover:bg-gray-50 hover:text-primary-600 text-gray-700",
5
- active_class: "group flex gap-x-3 rounded-md p-2 text-sm/6 font-semibold hover:bg-gray-50 hover:text-primary-600 bg-gray-50 text-primary-600",
6
- }
7
- %>
8
- <%= active_link_to path, options do %>
9
- <% if defined?(initials) && initials.present? %>
10
- <span class="flex size-6 shrink-0 items-center justify-center rounded-lg border border-gray-200 bg-white text-[0.625rem] font-medium text-gray-400 group-hover:border-primary-600 group-hover:text-primary-600"><%= initials %></span>
11
- <% elsif defined?(icon) && icon.present? %>
12
- <%= svg_icon icon, class: "size-6 text-gray-400 group-hover:text-primary-600" %>
13
- <% end %>
14
- <%= title %>
15
- <% end %>
@@ -1,3 +0,0 @@
1
- <ul role="list" class="flex flex-1 flex-col gap-y-7">
2
- <%= yield(builder) %>
3
- </ul>
@@ -1,105 +0,0 @@
1
- <nav class="border-b border-gray-200 bg-white">
2
- <div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
3
- <div class="flex h-16 justify-between">
4
- <div class="flex">
5
- <div class="flex shrink-0 items-center">
6
- <img class="block h-8 w-auto lg:hidden" src="https://tailwindcss.com/plus-assets/img/logos/mark.svg?color=primary&shade=600" alt="Your Company" />
7
- <img class="hidden h-8 w-auto lg:block" src="https://tailwindcss.com/plus-assets/img/logos/mark.svg?color=primary&shade=600" alt="Your Company" />
8
- </div>
9
- <div class="hidden sm:-my-px sm:ml-6 sm:flex sm:space-x-8">
10
- <!-- Current: "border-primary-500 text-gray-900", Default: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700" -->
11
- <a href="#" class="inline-flex items-center border-b-2 border-primary-500 px-1 pt-1 text-sm font-medium text-gray-900" aria-current="page">Dashboard</a>
12
- <a href="#" class="inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700">Team</a>
13
- <a href="#" class="inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700">Projects</a>
14
- <a href="#" class="inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700">Calendar</a>
15
- </div>
16
- </div>
17
- <div class="hidden sm:ml-6 sm:flex sm:items-center">
18
- <button type="button" class="relative rounded-full bg-white p-1 text-gray-400 hover:text-gray-500 focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 focus:outline-hidden">
19
- <span class="absolute -inset-1.5"></span>
20
- <span class="sr-only">View notifications</span>
21
- <svg class="size-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon">
22
- <path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0" />
23
- </svg>
24
- </button>
25
-
26
- <!-- Profile dropdown -->
27
- <div class="relative ml-3">
28
- <div>
29
- <button type="button" class="relative flex max-w-xs items-center rounded-full bg-white text-sm focus:outline-hidden focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" id="user-menu-button" aria-expanded="false" aria-haspopup="true">
30
- <span class="absolute -inset-1.5"></span>
31
- <span class="sr-only">Open user menu</span>
32
- <img class="size-8 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" />
33
- </button>
34
- </div>
35
-
36
- <!--
37
- Dropdown menu, show/hide based on menu state.
38
-
39
- Entering: "transition ease-out duration-200"
40
- From: "transform opacity-0 scale-95"
41
- To: "transform opacity-100 scale-100"
42
- Leaving: "transition ease-in duration-75"
43
- From: "transform opacity-100 scale-100"
44
- To: "transform opacity-0 scale-95"
45
- -->
46
- <div class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-hidden" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabindex="-1">
47
- <!-- Active: "bg-gray-100 outline-hidden", Not Active: "" -->
48
- <a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-0">Your Profile</a>
49
- <a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-1">Settings</a>
50
- <a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-2">Sign out</a>
51
- </div>
52
- </div>
53
- </div>
54
- <div class="-mr-2 flex items-center sm:hidden">
55
- <!-- Mobile menu button -->
56
- <button type="button" class="relative inline-flex items-center justify-center rounded-md bg-white p-2 text-gray-400 hover:bg-gray-100 hover:text-gray-500 focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 focus:outline-hidden" aria-controls="mobile-menu" aria-expanded="false">
57
- <span class="absolute -inset-0.5"></span>
58
- <span class="sr-only">Open main menu</span>
59
- <!-- Menu open: "hidden", Menu closed: "block" -->
60
- <svg class="block size-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon">
61
- <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
62
- </svg>
63
- <!-- Menu open: "block", Menu closed: "hidden" -->
64
- <svg class="hidden size-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon">
65
- <path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
66
- </svg>
67
- </button>
68
- </div>
69
- </div>
70
- </div>
71
-
72
- <!-- Mobile menu, show/hide based on menu state. -->
73
- <div class="sm:hidden" id="mobile-menu">
74
- <div class="space-y-1 pt-2 pb-3">
75
- <!-- Current: "border-primary-500 bg-primary-50 text-primary-700", Default: "border-transparent text-gray-600 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-800" -->
76
- <a href="#" class="block border-l-4 border-primary-500 bg-primary-50 py-2 pr-4 pl-3 text-base font-medium text-primary-700" aria-current="page">Dashboard</a>
77
- <a href="#" class="block border-l-4 border-transparent py-2 pr-4 pl-3 text-base font-medium text-gray-600 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-800">Team</a>
78
- <a href="#" class="block border-l-4 border-transparent py-2 pr-4 pl-3 text-base font-medium text-gray-600 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-800">Projects</a>
79
- <a href="#" class="block border-l-4 border-transparent py-2 pr-4 pl-3 text-base font-medium text-gray-600 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-800">Calendar</a>
80
- </div>
81
- <div class="border-t border-gray-200 pt-4 pb-3">
82
- <div class="flex items-center px-4">
83
- <div class="shrink-0">
84
- <img class="size-10 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" />
85
- </div>
86
- <div class="ml-3">
87
- <div class="text-base font-medium text-gray-800">Tom Cook</div>
88
- <div class="text-sm font-medium text-gray-500">tom@example.com</div>
89
- </div>
90
- <button type="button" class="relative ml-auto shrink-0 rounded-full bg-white p-1 text-gray-400 hover:text-gray-500 focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 focus:outline-hidden">
91
- <span class="absolute -inset-1.5"></span>
92
- <span class="sr-only">View notifications</span>
93
- <svg class="size-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon">
94
- <path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0" />
95
- </svg>
96
- </button>
97
- </div>
98
- <div class="mt-3 space-y-1">
99
- <a href="#" class="block px-4 py-2 text-base font-medium text-gray-500 hover:bg-gray-100 hover:text-gray-800">Your Profile</a>
100
- <a href="#" class="block px-4 py-2 text-base font-medium text-gray-500 hover:bg-gray-100 hover:text-gray-800">Settings</a>
101
- <a href="#" class="block px-4 py-2 text-base font-medium text-gray-500 hover:bg-gray-100 hover:text-gray-800">Sign out</a>
102
- </div>
103
- </div>
104
- </div>
105
- </nav>